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
调用,
这通常不是问题