在我的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 (有效值的集合)提取到参数传递给这段代码?
答案 0 :(得分: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
但是你干掉几个规格的想法怎么样......我认为这太过分了。我相信规范必须首先是可读的,然后才能干。如果您的规格很少,那么将来阅读/重构/更改此代码可能会令您头疼。
答案 1 :(得分: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
没有对此进行测试,但我认为它应该可行。