2016-04-13 18 views
0

私はテストを開始していますが、letを使用するときは正確にはわかりません。rspecモデル仕様vs工場

遅延ロードのモデルテストではletを使用する必要がありますか、またはすべてのテストでデータが少し異なるため、そのまま使用できますか?いくつかの例で見たように、コントローラーテストの方が重要です。具体的には、:taskはそれぞれのアクションテストで同じです。

モデルの仕様

require 'rails_helper' 

RSpec.describe Task, type: :model do 

    describe "model validations" do 

    it "has a valid factory" do 
     expect(build(:task)).to be_valid 
    end 

    it "is invalid without executor" do 
     expect(build(:task, executor_id: nil)).not_to be_valid 
    end 

    it "is invalid without assigner" do 
     expect(build(:task, assigner_id: nil)).not_to be_valid 
    end 

    it "is invalid without content" do 
     expect(build(:task, content: nil)).not_to be_valid 
    end 

    it "is invalid without deadline" do 
     expect(build(:task, deadline: nil)).not_to be_valid 
    end 

    it "is invalid with deadline in the past" do 
     expect(build(:task, deadline: Faker::Time.between(DateTime.now - 1, DateTime.now - 2))).not_to be_valid 
    end 
    end 
end 

工場

FactoryGirl.define do 
    factory :task do 
    content { Faker::Lorem.sentence } 
    deadline { Faker::Time.between(DateTime.now + 2, DateTime.now + 3) } 
    association :executor, factory: :user 
    association :assigner, factory: :user 
    end 
end 

答えて

1

メリット:何が価値がある、あなたがそこに持っているものを達成するためにshoulda-matchers宝石を使用することができるため

。このグループを想像してみてください。

context "completing tasks" do 
    let(:completing_a_task){ task.complete } 
    context "that aren't due yet" do 
    let(:task){ create(:not_due_task) } 
    it "should not send an email" do 
     expect(TaskMailer).not_to receive(:deliver_message) 
     expect{ completing_a_task }.not_to raise_error 
    end 
    end 
    context "overdue" do 
    let(:task){ create(:overdue_task) } 
    it "should send an email" do 
     expect(TaskMailer).to receive(:deliver_message) 
     expect{ completing_a_task }.not_to raise_error 
    end 
    end 
end 

遅延バインディングを使用すると、変更を最小限に抑えることができますが、最大限のカバレッジが得られます。テストに必要な適切な動作を設定するために必要な共同作業者が多いほど、letの恩恵を受ける可能性が高くなります。特にテストスイートでDRYを実行する必要はありませんが、テスト用の巨大なセットアップブロックは匂いです。letテクニックは、ドメインが複雑になっても明快でシンプルに戦うのに役立つ素晴らしいツールです。自分の例にはまだ協力者はいませんが、そのコンセプトはまだ十分明確です。

+0

Jim、コピーすることもできますこのコードは工場との違いを正確に見るために? –

+0

@SzilardMagyarの工場は、はるかに異なる目標を達成しています。ファクトリの仕事は、ドメインオブジェクトをプロビジョニングして(おそらくそれらをデータベースに保持する)ことです。上記のテストのこのスタンザは、私のアプリケーションのいずれかで意味のあるすべてのモデルのために書いたものと本質的に同じです。私の 'let'ステートメントは、しばしば工場出力自体、または工場で作成されたオブジェクトに対して呼び出されるドメインメソッドのいずれかを含んでいます。希望が助けてくれる! –

+0

ジム、例えば 'let(:task){create(:not_due_task)}' 'や' let(:task){'' create(:overdue_task)} 'の '実際にあなたの例を得ることはできません。 –

1

私はletを使用して、あなたがそれを持ってどのようにそれを維持していないことをお勧めしたいです。あなたのテストのDRYを心配しないでください。それらはお互いに対話しないので、アプリケーションロジックでコードの重複が発生することはありません。あなたは上記の使用の形のものではないテストから来lethttps://github.com/thoughtbot/shoulda-matchers

describe Task do 
    describe "validations" do 
    it { is_expected.to validate_presence_of(:content) } 
    it { is_expected.to validate_presence_of(:deadline) } 
    end 
end 
+0

ニック、私はshouldaマッチャーを使用していますが、ここでコードをコピーしませんでした。私が知っている限り、それらはバリデーションの存在をチェックするだけです。このコードでは、私の工場とオブジェクトが正常に動作することを確認したいと思います。 –

+0

@SzilardMagyar 'shoulda-matchers'は、バリデーションの存在ではなく、値に対する大部分のチェックです。たとえば、 'validate_presence_of'を使用した場合は、組み込みのRailsの存在確認ツールをスキップして、独自に再作成することができます(' content.blank 'ならばerrors.add(:content、 "空白にすることはできません")。 。 shoulda matcherは期待どおりに動作します。ソースでは、実際のブランク値と比較して確認できます。https://github.com/thoughtbot/shoulda-matchers/blob/master/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb – Nick

関連する問題