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

时间:2019-07-03 11:40:15

标签: 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

我可以通过创建自定义匹配器来做到这一点:

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

但是我现在测试失败,并且失败消息完全没有用。现在只说Expected #<Result ...> to be successful

我知道我可以覆盖失败消息,但是现在,此解决方案变得比为每个规格示例节省2行所值得的要复杂得多。最初的3行产生了有用的故障消息,我要做的就是将它们组合成1行。

我可以将3行移动到一个单独的函数(例如assert_successful)中,并从每个规范示例中调用它,但我想保留匹配器语法。

可以做到吗?

2 个答案:

答案 0 :(得分:0)

根据this

您可以执行以下操作:

item.categories

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

答案 1 :(得分:0)

一种组织方式是:将真实的测试代码放入 自己的方法Cell.Range.Text=" *" , 返回_check_ok(expected, actual)[true]

这称为:

[false, message]

在失败的情况下,此操作重复 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 调用, 通常这不是问题。