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