Ruby 是否可以通过组合现有的RSpec匹配器来创建新的RSpec匹配器?

Ruby 是否可以通过组合现有的RSpec匹配器来创建新的RSpec匹配器?,ruby,rspec,Ruby,Rspec,在我的一份说明书中,我发现自己经常重复这样的话: expect(result.status).to be(:success) expect(result.offers).not_to be_empty expect(result.comments).to be_empty 为了使我的测试更加简洁易懂,我想将它们组合成一行,如下所示: expect(result).to be_successful RSpec::Matchers.define :be_successful do matc

在我的一份说明书中,我发现自己经常重复这样的话:

expect(result.status).to be(:success)
expect(result.offers).not_to be_empty
expect(result.comments).to be_empty
为了使我的测试更加简洁易懂,我想将它们组合成一行,如下所示:

expect(result).to be_successful
RSpec::Matchers.define :be_successful do

  match do |result|
    result.status == :success &&
    result.offers.length > 0 &&
    result.comments.empty?
  end

  failure_message do |result|
    "Should have #{result} equal to be successful"
  end

  failure_message_when_negated do |result|
    "Should not have #{result} to be successful"
  end
end
我可以通过创建自定义匹配器来实现这一点:

matcher :be_successful do
  match { |result|
    result.status == :success &&
    result.offers.length > 0 &&
    result.comments.empty?
  }
end
但是我现在有一个失败的测试,失败的消息是完全无用的。它现在所说的一切都是希望成功

我知道我可以覆盖失败消息,但现在这个解决方案变得越来越复杂,不值得为每个规范示例节省2行代码。最初的3行生成了有用的失败消息,我只想把它们合并成一行

我可以将这3行移到一个单独的函数中(例如,
assert\u successful
),并从每个规范示例中调用它,但我希望保留matcher语法

可以这样做吗?

根据

你可以这样做:

expect(result).to be_successful
RSpec::Matchers.define :be_successful do

  match do |result|
    result.status == :success &&
    result.offers.length > 0 &&
    result.comments.empty?
  end

  failure_message do |result|
    "Should have #{result} equal to be successful"
  end

  failure_message_when_negated do |result|
    "Should not have #{result} to be successful"
  end
end

如果您在其他地方重复使用此测试超过3次,那么创建一个新的匹配器并覆盖失败消息是有意义的(这不是开销)。如果您只使用此测试一次,那么在不过度抽象的情况下保留它是有意义的。

组织此测试的一种方法是:将真正的测试代码放入 方法本身的检查(预期、实际), 返回
[true]
[false,消息]

这称为:

  RSpec::Matchers.defined :check_ok do |expected|
    match do |actual|
      return _check_ok(expected, actual)[0]
    end
    failure_message do |actual|
      return _check_ok(expected, actual)[1]
    end
  end
这将在故障情况下重复
\u check\u ok
调用, 这通常不是问题