Ruby 使用rspec断言用户数组中的所有user.name都以前缀开头的更好方法?
这是我的。还有那种工作Ruby 使用rspec断言用户数组中的所有user.name都以前缀开头的更好方法?,ruby,unit-testing,rspec,Ruby,Unit Testing,Rspec,这是我的。还有那种工作 it "should filter by name" do users = users.search(:name => "s") users.each {|u| u.name.should be_starts_with("s") } end 但是,rspec返回的错误消息非常糟糕 期望以“(“s”)开头的u返回true,得到false 有没有办法获得更精确的消息,显示失败的元素,或者至少是它的索引?之所以只得到预期的true而得到false
it "should filter by name" do
users = users.search(:name => "s")
users.each {|u|
u.name.should be_starts_with("s")
}
end
但是,rspec返回的错误消息非常糟糕
期望以“(“s”)开头的u返回true,得到false
有没有办法获得更精确的消息,显示失败的元素,或者至少是它的索引?之所以只得到预期的true而得到false,是因为start_with方法返回true或false,而不是实际值 我不确定这是否是最好的方法,但您可以自己输出它
users.each {|u|
p u.name if !u.name.starts_with?("s")
u.name.should be_starts_with("s")
}
我在这里发现了Rspec对matchers的一个有趣的扩展: 所以我把那个助手粘贴到我的spec_助手中
RSpec::Matchers.define :each do |meta|
match do |actual|
actual.each_with_index do |i, j|
@elem = j
i.should meta
end
end
failure_message_for_should do |actual|
"at[#{@elem}] #{meta.failure_message_for_should}"
end
这样我就可以写作了
users.should each satisfy {|u| u.name.should be_starts_with 's'}
然后,错误消息是:
在[1]处,期望用户满足块
这给了我失败的第一个指标。
通过添加一些错误消息,我确信我可以输出不匹配的对象的详细信息,这似乎是一个很好的解决方案
有什么想法吗?我不是一个红宝石爱好者,只是刚开始使用rails。如果能从中获得更多的输入,那就太好了。下面是我在这种情况下使用的几次方法:
describe 'user' do
before :each do
@users = users.search(:name => "s")
end
@users.each do |u|
it "should filter user with name '#{u.name}'" do
u.name.should be_starts_with("s")
end
end
end
在您的示例描述中,用户名将失败。在这样的二进制测试中,我将创建两个用户,一个以s开头,另一个不以s开头。然后检查是否只返回了预期的元素 像 在失败的情况下,你会看到类似
expected ["Sam"]
got ["Fred", "Sam"]
这将更明确地说明您正在做什么这将为您提供更好的失败消息
it "should filter by name" do
users = users.search(:name => "s")
users.each do |u|
u.name.should match /^s/
end
end
我同意科里的说法,叫“be_Start_with”很粗糙。RSpec期望值旨在作为一个句子流畅地阅读。他们都不必使用“be”。我想我找到了一个很好的解决方案,我把它作为一个答案,然后等着看RuuyStor对我的解决方案的评论,这感觉更像是一个关于测试问题的创可贴。如果失败消息不明显,这应该(通常是)提示测试编写方式不正确。这会不会对每个“it”should…”进行搜索?before:所有可能?let与示例同时评估,而不是在示例构建时评估。不同的作用域,因此在构建示例时您将无法访问筛选的用户。(除非我读到你缺少parens和:错。@coreyhaines-你是对的,在这种情况下我们不工作。before:all或before:each将。@vanyak对此不确定。范围仍然不同。before:each的块在每个示例中执行一次。因此,在运行示例之前不会设置实例变量@users。在你的代码中,@users是nil,所以如果运行此操作,您应该会得到一个异常。此外…您不再需要:每个,只需执行“before do”也…我编写的“按名称筛选”不是“应按名称筛选”也应该是读取非常糟糕的。是的,谢谢您的反馈:)。这也感觉有点像api问题。搜索(:name=>“s”)不会显示它是以开头的。你能做一些类似用户的事情吗?按名称搜索(:以=>“s”开头)?或者放一个通配符,users.search(:name=>“s*”)Spec::Matchers看起来有点有趣:用正则表达式的
match
替换字符串的start\u,以满足rspec的要求听起来有点拖沓。@Andrew:显然u.name.should\u以(“s”)
开头也行。我认为调用应该(以(x)开头)也可以,但这是我在运行rspec2.7的新Rails3.1.1应用程序中收到的错误<代码>失败:1)示例执行某些操作失败/错误:名称。应以“j”名称开头错误:未定义的方法“start”with for##./spec/models/Sample#spec.rb:6:in“block(2个级别)in”
it "should filter by name" do
users = users.search(:name => "s")
users.each do |u|
u.name.should match /^s/
end
end