2012-12-22 8 views
5

は、私は値が有効な値のリスト内にあることを保証するために与えられたフィールド(ユーザーモデルで役割)の動作をチェックするRSpecのスペックを持っています。再利用RSpecの動作検証

もう1つ別のモデルでは、別のフィールドに同じ仕様を設定します。別のモデルには、別の有効な値が設定されています。共通のコードをコピーして貼り付け、変数を変更するのではなく、そのコードを抽出したいと思います。

共有の例または他のRSpecの再利用技術を使用するのが妥当かどうか疑問に思っています。

ここでは、関連するRSpecのコードです:のコレクションは、このコードを再利用するための最良のケースだろう何

describe "validation" do 
    describe "#role" do 
    context "with a valid role value" do 
     it "is valid" do 
     User::ROLES.each do |role| 
      build(:user, :role => role).should be_valid 
     end 
     end 
    end 

    context "with an empty role" do 
     subject { build(:user, :role => nil) } 

     it "is invalid" do 
     subject.should_not be_valid 
     end 

     it "adds an error message for the role" do 
     subject.save.should be_false 
     subject.errors.messages[:role].first.should == "can't be blank" 
     end 
    end 

    context "with an invalid role value" do 
     subject { build(:user, :role => 'unknown') } 

     it "is invalid" do 
     subject.should_not be_valid 
     end 

     it "adds an error message for the role" do 
     subject.save.should be_false 
     subject.errors.messages[:role].first.should =~ /unknown isn't a valid role/ 
     end 
    end 
    end 
end 

が、役割(フィールドが検証されている)とユーザー:: ROLESを(抽出有効な値)をこのコードに渡すパラメータに変換しますか?

答えて

2

これは、共有の例では完全に合理的な使用例だと思います。例えばこのような何か:

shared_examples_for "attribute in collection" do |attr_name, valid_values| 

    context "with a valid role value" do 
    it "is valid" do 
     valid_values.each do |role| 
     build(:user, attr_name => role).should be_valid 
     end 
    end 
    end 

    context "with an empty #{attr_name}" do 
    subject { build(:user, attr_name => nil) } 

    it "is invalid" do 
     subject.should_not be_valid 
    end 

    it "adds an error message for the #{attr_name}" do 
     subject.save.should be_false 
     subject.errors.messages[attr_name].first.should == "can't be blank" 
    end 
    end 

    context "with an invalid #{attr_name} value" do 
    subject { build(:user, attr_name => 'unknown') } 

    it "is invalid" do 
     subject.should_not be_valid 
    end 

    it "adds an error message for the #{attr_name}" do 
     subject.save.should be_false 
     subject.errors.messages[attr_name].first.should =~ /unknown isn't a valid #{attr_name}/ 
    end 
    end 
end 

その後、あなたはこのようなあなたのスペックでそれを呼び出すことができます。

describe "validation" do 
    describe "#role" do 
    behaves_like "attribute in collection", :role, User::ROLES 
    end 
end 

はこれをテストしていませんが、私はそれが動作するはずだと思います。

+0

素晴らしい、ありがとう。 – kolrie

2

あなたはshared_examples技術でこのようにあなたのスペックを乾燥させることができる。

shared_examples "no role" do 
    it "is invalid" do 
     subject.should_not be_valid 
    end 
    end 

    context "with an empty role" do 
    subject { Factory.build(:user, :name => nil) } 
    it_behaves_like "no role" 
    end 

    context "with an invalid role value" do 
    subject { Factory.build(:user, :name => '') } 
    it_behaves_like "no role" 
    end 

しかし、どのようなアイデアについて、いくつかのspecs..Iを乾燥させるためには、それはあまりにも多くのことだと思います。私は、スペックが最初に読めるようにしなければならないと確信しています。もしあなたがいくつかの仕様を守らなければ、将来の読書/リファクタリング/変更の頭痛になるでしょう。

+0

合意。私はそれをする良い方法か、あなたがしたことを本当に教えている誰かを探していました。コピーして貼り付け、小さな小片を乾燥させます。ありがとうございました。 – kolrie

+0

それは 'shared_examples'ではなく' shared_examples_for'ですか? –

+0

'shared_examples'はうまくいきます – alex

関連する問題