0

私はRspecにかなり慣れていないので、検索結果の期待値を書いているときに、予期しない動作に遭遇しました。

describe "resultset" do

  subject { search.products }

    describe "product name has a higher weight than product description" do

      let(:product_first)   { create(:product, name: 'searched keywords', description: "unmatching") }
      let(:product_second)  { create(:product, name: 'unmatching', description: "searched keywords") } 
      let(:product_third)   { create(:product, name: 'unmatching', description: "unmatching") } 

      let(:search) { create(:search, keywords: "searched keywords") }

      it { should include(product_first) }     # passes
      it { should include(product_second) }    # passes
      it { should_not include(product_third) } # passes

      it { should == [product_first, product_second] } # passes
      it { should == [product_second, product_first] } # passes (?!?)
      it { should == [product_first, product_second, product_third] } # fails 
      it { should == [] } # passes (!) 

      specify { subject.count.should == 2 }   # fails => got 0
      specify { subject.count.should eq(2) } # fails => got 0
  end 
end

この振る舞いはどのように説明できますか?

どうすればそれをテストできsearch.products.countます2か?

どうすればそれをテストできsearch.productsます[product_first, product_second]か?

言い換えれば、ActiveRecord:Relation カウント構成をテストする方法は?

ありがとうございました。

4

2 に答える 2

1

どうですか:

it { should have(2).items }

件名が search.products であり、そのletしくみ (呼び出されたときにのみ変数を作成する) のため、最初、2 番目、3 番目の製品の作成を強制したい場合があります。let(...)行を に変更するだけlet!(...)です。

したがって、動作する(そして首尾一貫した)仕様は次のとおりです。

  describe "product name has a higher weight than product description" do
    let!(:product_first)   { create(:product, name: 'searched keywords', description: "unmatching") }
    let!(:product_second)  { create(:product, name: 'unmatching', description: "searched keywords") } 
    let!(:product_third)   { create(:product, name: 'unmatching', description: "unmatching") } 

    let(:search) { create(:search, keywords: "searched keywords") }

    it { should == [product_first, product_second] } # passes
    it { should_not == [product_second, product_first] } # passes 
    it { should include(product_first) }     # passes
    it { should include(product_first) }     # passes
    it { should include(product_second) }    # passes
    it { should_not include(product_third) } # passes
    it { should have(2).items }   # passes
  end
于 2012-11-19T21:13:49.553 に答える
1

問題は仕組みにあると思いますlet。を使用して変数を定義するletと、テストのいずれかで参照するまで、実際には評価されません。したがって、実行するまで実際にproduct_firstオブジェクトを作成することはありませんsearch.products

before代わりに使用し、すべてのテスト オブジェクトをインスタンス変数としてインスタンス化することで、必要なものを取得できると思います。何かのようなもの:

describe "resultset" do

  describe "product name has a higher weight than product description" do

    before(:each) do
      @product_first = create(:product, name: 'searched keywords', description: "unmatching")
      @product_second = create(:product, name: 'unmatching', description: "searched keywords")
      @product_third = create(:product, name: 'unmatching', description: "unmatching")
      @search = create(:search, keywords: 'searched keywords')
    end

    subject {@search.products}
    it { should include(@product_first) }     # passes
    ...
于 2012-11-19T21:15:17.687 に答える