4

私が取り組んでいるコーディング標準では、関数をテストする仕様のグループには、呼び出される関数であるサブジェクトが必要であると指定されています。次のようになります。

define User do
  context :foo do
    let(:user) { FactoryGirl.create(:user) }
    subject { user.foo }
    it { ... }
  end
end

ブロックの典型的な用途は、subjectテストしているクラスをインスタンス化することです:

define User do
  subject { FactoryGirl.create(:user) }
  it { ... }
end

スタイル ガイドの意図した効果は、テスト対象のメソッドごとに異なるサブジェクト ブロックを用意することです。これは私たちのテストを遅くしていますか? 通常の方法で使用subjectした場合、クラスごとに 1 つのサブジェクト ブロックのみを使用することで、組み込みのメモ化やその他の高速化の恩恵を受けるでしょうか?

余談:

私たちのスタイルがうまくいかないケースに遭遇しました。使用any_instance.should_receiveする場合、スタイル ガイドに従わないと、仕様が常に失敗します。代わりに、より伝統的なアプローチを使用する必要があります。ここでsubjectは、テストしているオブジェクトであり、仕様でそのオブジェクトに対してメソッドを呼び出します。

# passing spec
define Foo do
  before { Bar.any_instance.stub(:baz) }
  subject { FactoryGirl.create(:foo) }
  it "bazzes Bars" do
    Bar.any_instance.should_receive(:baz)
    subject.baz_the_bars
  end
end

# spec follows style guide but fails
define Foo do
  before { Bar.any_instance.stub(:baz) }
  let(:foo) { FactoryGirl.create(:foo) }
  subject { foo.baz_the_bars }

  it "bazzes Bars" do
    Bar.any_instance.should_receive(:baz)
    subject
  end
end

class Foo
  has_many :bars

  def baz_the_bars
    bars.collect do |bar|
      bar.baz
    end.count(true)
  end
end

このスタイルで他に注意すべき点はありますか?

4

1 に答える 1

6

subjectのように遅延して作成され、テストごとに、スコープがcontext/describeに設定されletます。それらに余分なオーバーヘッドがあってはなりません。

私は個人的にあなたが示すスタイルが好きではありませんが、メソッドから返される非常に複雑な (または単に大きな) データ オブジェクトがある場合に同様のことを行いました。

describe "A thing" do
  subject(:foo) { FactoryGirl.create(:foo) }

  # A very complicated object from this method
  describe "the result of calling frob" do
    subject(:result) { foo.frob }

    it { should be_active }
    it { should be_alive }
  end
end
于 2013-10-27T14:33:45.287 に答える