今天我在定义自定义 RSpec 匹配器时遇到了一个问题,我解决了这个问题,但实际上看不出为什么其中一种方法有效而另一种方法无效的任何原因,下面是代码:
方法 1 - if + else:
RSpec::Matchers.define :have_success_message do |message|
match do |page|
if message.nil?
page.should have_selector('div.alert.alert-success')
else
page.should have_selector('div.alert.alert-success', text: message)
end
end
end
方法 2——如果后面跟着除非
RSpec::Matchers.define :have_success_message do |message|
match do |page|
page.should have_selector('div.alert.alert-success') if message.nil?
page.should have_selector('div.alert.alert-success', text: message) unless message.nil?
end
end
我认为第一种方法更好,因为它只检查一次条件,但是结果应该是一样的,对吧?
好吧,事实证明第一种方法的测试通过了,而第二种方法的测试没有。我完全不知道为什么会这样,如果有人能对此有所了解,我会很高兴。
编辑:
忘记添加实际测试(使用方法 2):
存在以下 HTML 标记:
<div class="alert alert-success">Profile updated</div>
我运行 4 个单独的测试:
it { should have_success_message } # fails
it { should have_success_message('Profile updated') } # passes
it { should have_selector('div.alert.alert-success') } # passes
it { should have_selector('div.alert.alert-success', text: "Profile updated") } # passes
失败带有以下消息:
1) User pages edit with valid information
Failure/Error: it { should have_success_message }
expected #<Capybara::Session> to have success message
# ./spec/requests/user_pages_spec.rb:80:in `block (5 levels) in <top (required)>'
当 HTML 标记不存在时,所有 4 个测试都失败。
编辑2:
我尝试了另一种方法来验证控制流是否正确:
方法3:
if message.nil?
puts "In if, message is: #{message.inspect}"
page.should(have_selector('div.alert.alert-success'))
end
unless message.nil?
puts "In unless, message is: #{message.inspect}"
page.should(have_selector('div.alert.alert-success', text: message))
end
使用这种方法,行为与方法 2 相同 - 第一次测试失败,然后通过 3 次。
输出如下:
在 if 中,消息是:nil
在除非,消息是:“配置文件已更新”
所以控制流看起来不错,但是
page.should(have_selector('div.alert.alert-success'))
失败,即使它通过了匹配器之外。这真是一个谜。
最终编辑:
只是为了响应批准的答案-当我像这样切换代码时:
page.should have_selector('div.alert.alert-success', text: message) unless message.nil?
page.should have_selector('div.alert.alert-success') if message.nil?
测试如下所示:
it { should have_success_message } # passes
it { should have_success_message('Profile updated') } # fails
it { should have_selector('div.alert.alert-success') } # passes
it { should have_selector('div.alert.alert-success', text: "Profile updated") } # passes
所以我认为确实最后一行,当它不正确时,被评估为零,这会导致整个混乱。无论如何,第一种方法更好,但我很高兴我没有想到这个问题:)