5

Rails 3アプリケーションには、特定のフィールド(ユーザーモデルでの役割)の動作をチェックして、値が有効な値のリスト内にあることを保証するRSpec仕様があります。

次に、別の有効な値のセットを持つ別のモデルで、別のフィールドに対してまったく同じ仕様を使用します。単にコピーして貼り付けたり、変数を変更したりするのではなく、共通のコードを抽出したいと思います。

これが共有の例または他の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

このコードを再利用するのに最適なケースは何ですか?ただし、このコードに渡されるパラメーターにロール(検証されるフィールド)とUser :: ROLES(有効な値のコレクション)を抽出しますか?

4

2 に答える 2

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

しかし、いくつかのスペックを乾かすというあなたのアイデアはどうですか..私はそれが多すぎると思います。スペックは最初に読み取り可能でなければならず、次にDRYする必要があると私は確信しています。いくつかのスペックを乾かすと、このコードを将来読んだり、リファクタリングしたり、変更したりするのにおそらく頭痛の種になるでしょう。

于 2012-12-22T17:46:07.003 に答える
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

これはテストしていませんが、動作するはずです。

于 2012-12-23T16:38:47.093 に答える