3

Rails アプリから単一のクラスをgemに抽出しました。非常に単純ですが、もちろん完全にテストしたいと思います (私は rspec を使用しています)。

このクラスは、簡単な日付計算を行います。Rails には依存していませんが、Rails アプリで開始され、現在も使用されているため、可能な場合は ActiveSupport のタイム ゾーン対応メソッドを使用します。ただし、ActiveSupport が利用できない場合は、std-libDateメソッドを使用する必要があります。

具体的には、これは 1 つの場所でのみ行われます: オプションの引数を「今日の日付」にデフォルト設定する:

arg ||= if Date.respond_to?(:current)
  Date.current # use ActiveSupport's time zone-aware mixin if possible
else
  Date.today   # stdlib fallback
end

質問: これを適切にテストするにはどうすればよいですか? で ActiveSupport が必要な場合は、spec_helper.rb明らかに常にそれを使用します。私がどこでもそれを必要としないなら、決してそれを使用しません。また、単一の例のグループに必要な場合、AS がいつ必要になるか分からないため、rspec のランダムな実行順序によりテストが予測不能になります。

before(:all)ネストされたグループは(私が信じている)最も高いものから最も深いものまで処理されるため、ネストされたグループでそれを要求することができます。しかし、それはひどくエレガントではないようです。

スペックを 2 つのファイルに分割して、別々に実行することもできますが、これも不要のようです。

rspec のランダムな順序付けを無効にすることもできますが、それは一種の逆行です。なるべくランダムにした方がいいと思います。

何か案は?

4

2 に答える 2

2

current別の解決策は、メソッドとメソッドをモックし、todayそれらをテストに使用することです。例えば:

# you won't need these two lines, just there to make script work standalone
require 'rspec'
require 'rspec/mocks/standalone'

def test_method(arg = nil)
    arg ||= if Date.respond_to?(:current)
      Date.current # use ActiveSupport's time zone-aware mixin if possible
    else
      Date.today   # stdlib fallback
    end
    arg
end

describe "test_method" do
    let(:test_date) { Date.new(2001, 2, 3) }
    it "returns arg unchanged if not nil" do
        test_method(34).should == 34
    end

    context "without Date.current available" do
        before(:all) do
            Date.stub(:today) { test_date }
        end
        it "returns Date.today when arg isn't present" do
            test_method.should == test_date
        end
    end

    context "with Date.current available" do
        before(:all) do
            Date.stub(:current) { test_date }
        end
        it "returns Date.current when arg isn't present" do
            test_method.should == test_date
        end
    end
end

実行するとrspec test.rb、テストに合格します。

また、スタブは各コンテキストにのみ存在するため、spec が実行される順序は関係ありません。

于 2013-06-07T14:43:34.763 に答える
0

これは少しひねくれたものではありませんが、うまくいくはずです。ActiveSupport を含めると、次のようになります。

context "without ActiveSupport's Date.current" do
  before(:each) do
    class Date
      class << self
        alias_method :current_backup, :current
        undef_method :current
      end
    end
  end

  # your test

  after(:each) do
    class Date
      class << self
        alias_method :current, :current_backup
      end
    end
  end
end

これはあまりお勧めできません。あなたが提案したように、この1つの仕様を分割して別々に実行したいと思います。

于 2013-06-07T14:06:49.703 に答える