今日、解決したカスタム RSpec マッチャーの定義に関する問題がありましたが、実際には、アプローチの 1 つが機能し、もう 1 つが機能しない理由の背後にある理由を理解できませんでした。コードは次のとおりです。
アプローチ 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 -- if が続く場合
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
条件を1回だけチェックするため、最初のアプローチの方が優れていると思いますが、それでも結果は同じはずですよね?
さて、最初のアプローチのテストはパスしますが、2 番目のアプローチのテストはパスしません。それがなぜなのか、私は完全に無知であり、誰かがそれに光を当てることができれば幸いです.
編集:
実際のテストを追加するのを忘れました(アプローチ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
したがって、最後の行が真でない場合、実際には nil と評価され、それが全体の混乱を引き起こすと思います。とにかく最初のアプローチの方が優れていますが、この問題が頭から離れてうれしいです:)