Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 指定显式';受试者';s_Ruby On Rails_Ruby_Ruby On Rails 3_Rspec_Rspec2 - Fatal编程技术网

Ruby on rails 指定显式';受试者';s

Ruby on rails 指定显式';受试者';s,ruby-on-rails,ruby,ruby-on-rails-3,rspec,rspec2,Ruby On Rails,Ruby,Ruby On Rails 3,Rspec,Rspec2,我正在使用RubyonRails3.0.9和RSpect2。我正试图以以下方式重构一些spec文件(以便用更少的代码类似Userclass对象属性值进行测试): 但是,如果运行上述测试,则会出现以下错误: Failure/Error: it "should be whatever" do NoMethodError: undefined method `it' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2::Nested

我正在使用RubyonRails3.0.9和RSpect2。我正试图以以下方式重构一些spec文件(以便用更少的代码类似
User
class对象属性值进行测试):

但是,如果运行上述测试,则会出现以下错误:

Failure/Error: it "should be whatever" do
  NoMethodError:
    undefined method `it' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2::Nested_2:0x00000106ccee60>
undefined local variable or method `user1' for #<Class:0x00000105310758> (NameError)

问题是一个规范嵌套在另一个规范中。您需要将
it“foreach user”
替换为
context“foreach user”

编辑以添加:经过一些调查后,使用
let
设置的帮助程序似乎仅在
它“应该…”
块中可用,而不在周围的上下文中。我建议你尝试找到一个不同的结构性解决方案。最佳解决方案取决于您实际尝试测试的内容。我猜您要做的是确保在删除任何必需属性时用户无效。在这种情况下,我所做的是这样的:

describe User do
  let(:user_attributes){ Factory.attributes_for(:user) }

  # Testing missing values aren't valid
  [:name, :email, :phone].each do |required_attribute|
    it "should not be valid without #{required_attribute}" do
      User.new(user_attributes.except(required_attribute)).should_not be_valid
    end
  end

  # Testing invalid values aren't valid
  [[:email, 'not_an_email'], [:phone, 'not a phone']].each do |(attribute, value)|
    it "should not be valid with bad value for #{attribute}" do
      User.new(user_attributes.update(attribute => value)).should_not be_valid
    end
  end
end
context "for all users" do
  [:user1, :user2, :user3].each do |user|
    it "does something" do
      send(user).valid?.should be_true
    end
  end
end
如果您正在做的事情需要在您创建的实例中有更复杂的差异,那么可能没有一种干净的方法可以通过迭代来完成。我不认为DRY在测试中像在代码的其他部分一样重要。对于这三种用户类型,有三种不同的上下文,并在每种上下文中进行有效性测试,没有什么错

describe User do
  context "with user1" do
    subject{ Factory(:user, :users_attribute_a => 'invalid_value') }
    it{ should_not be_valid }
  end

  context "with user2" do
    subject{ Factory(:user, :users_attribute_b => 'invalid_value') }
    it{ should_not be_valid }
  end

  context "with user3" do
    subject{ Factory(:user, :users_attribute_c => 'invalid_value') }
    it{ should_not be_valid }
  end
end

问题是,设置为“let”的助手不存在于示例上下文之外

您试图做的事情可以通过以下方式实现:

it "does something with all users" do
  [user1, user2, user3] do |user|
    user.valid?.should be_true
  end
end
两种情况都不同

另一种可能有效的方法(没有尝试过)是这样的:

describe User do
  let(:user_attributes){ Factory.attributes_for(:user) }

  # Testing missing values aren't valid
  [:name, :email, :phone].each do |required_attribute|
    it "should not be valid without #{required_attribute}" do
      User.new(user_attributes.except(required_attribute)).should_not be_valid
    end
  end

  # Testing invalid values aren't valid
  [[:email, 'not_an_email'], [:phone, 'not a phone']].each do |(attribute, value)|
    it "should not be valid with bad value for #{attribute}" do
      User.new(user_attributes.update(attribute => value)).should_not be_valid
    end
  end
end
context "for all users" do
  [:user1, :user2, :user3].each do |user|
    it "does something" do
      send(user).valid?.should be_true
    end
  end
end

你在混合和匹配各种rspec材料。这是你的东西,修正了:

describe User do
  let(:user1) { Factory(:user, :users_attribute_a => 'invalid_value') }
  let(:user2) { Factory(:user, :users_attribute_b => 'invalid_value') }
  let(:user3) { Factory(:user, :users_attribute_c => 'invalid_value') }

  it "should not be valid" do
    [ user1, user2, user3 ].each do |user|
      user.should_not be_valid
    end
  end
end
我会这样做:

describe User do
  subject{Factory.build(:user)}
  it "should not be valid with invalid users_attribute_a" do
    subject.users_attribute_a = "invalid_value"
    subject.should_not be_valid
  end
  it "should not be valid with invalid users_attribute_b" do
    subject.users_attribute_b = "invalid_value"
    subject.should_not be_valid
  end
end
  • 如果你想有“上下文”,那么很酷,但是你不能在上下文之前有变量
  • 如果你想有一个规范,那么就有一个规范,但你不能用“it”语句
用最少可能的代码更新

describe User do

  it "should not be valid with other attributes" do
    {:users_attribute_a => 'invalid_value', :users_attribute_b => 'invalid_value', :users_attribute_c => 'invalid_value'}.each do |key, value|
      Factory.build(:user, key => value).should_not be_valid
    end
  end

end

这应该行得通。注意上下文是如何编写的,它将使测试的输出更加清晰。这样写意味着(对我来说)你应该分别对每个属性进行测试,但这是你的选择:

describe User do
  let!(:users) { 
    [:users_attribute_a, :users_attribute_b, :users_attribute_c].map do |a|
      Factory(:user,  => 'invalid_value')
    end
  }

  context "Given a user" do
    context "With an invalid value" do
      subject { users }
      it { subject.all?{|user| should_not be_valid }
    end
  end
end

仅供参考,
subject
的使用在这里是一种误导。您从未实际使用示例中设置的主题。在第二个块中重构代码以减少代码编写量的方法是什么?您可以使用
let
将变量过滤到上下文中