RSpecのFeatureテストでshared_exampleみたいなことをする
🤔 状況: 同じ内容が多く、true/falseの判断が分かりづらい
この例では1つの要素をクリックした場合だけをテストしていますが、これをコピペして何通りものテストを書くと考えると、書き間違いや、読んでもよく理解できないコードになりそうです。
scenario 'それぞれのパネルが開いたり閉じたりすること' do
visit hoge_path(hoge_params)
within('div.section-fugas') do
expect(find('div.section-fuga:nth-child(1)')).to have_selector('div.section-fuga-body')
expect(find('div.section-fuga:nth-child(2)')).to have_selector('div.section-fuga-body')
expect(find('div.section-fuga:nth-child(3)')).not_to have_selector('div.section-fuga-body')
expect(find('div.section-fuga:nth-child(4)')).not_to have_selector('div.section-fuga-body')
find('div.section-fuga:nth-child(1)').find('a.section-fuga-a').click
expect(find('div.section-fuga:nth-child(1)')).not_to have_selector('div.section-fuga-body')
expect(find('div.section-fuga:nth-child(2)')).to have_selector('div.section-fuga-body')
expect(find('div.section-fuga:nth-child(3)')).not_to have_selector('div.section-fuga-body')
expect(find('div.section-fuga:nth-child(4)')).not_to have_selector('div.section-fuga-body')
end
end
👍 POROで解決!ふつうにdefを使う
ふつうにメソッドに切り出します。
さらに、matcherを変化できるようにsend(method, args)
を引数と組み合わせて使うことで、柔軟性が高まります。
結果、テスト本体では、見える/見えない(true/false)に集中できるようになりました。
def visibility_test(visibilities)
expect(find('div.section-fuga:nth-child(1)')).send(visibilities[0] ? :to : :not_to, have_selector('div.section-fuga-body'))
expect(find('div.section-fuga:nth-child(2)')).send(visibilities[1] ? :to : :not_to, have_selector('div.section-fuga-body'))
expect(find('div.section-fuga:nth-child(3)')).send(visibilities[2] ? :to : :not_to, have_selector('div.section-fuga-body'))
expect(find('div.section-fuga:nth-child(4)')).send(visibilities[3] ? :to : :not_to, have_selector('div.section-fuga-body'))
end
scenario 'それぞれのパネルが開いたり閉じたりすること' do
visit hoge_path(hoge_params)
within('div.section-fugas') do
visibility_test([true,true,false,false])
find('div.section-fuga:nth-child(1)').find('a.section-fuga-a').click
visibility_test([false,true,false,false])
end
end
👌 展望
さきほどのコードを完成させてみましょう。
4箇所クリックしてパネルが独立に開閉する ということが読み取りやすくなったでしょうか。
scenario 'それぞれのパネルが開いたり閉じたりすること' do
visit hoge_path(hoge_params)
within('div.section-fugas') do
visibility_test([true,true,false,false])
find('div.section-fuga:nth-child(1)').find('a.section-fuga-a').click
visibility_test([false,true,false,false])
find('div.section-fuga:nth-child(2)').find('a.section-fuga-a').click
visibility_test([false,false,false,false])
find('div.section-fuga:nth-child(3)').find('a.section-fuga-a').click
visibility_test([false,false,true,false])
find('div.section-fuga:nth-child(4)').find('a.section-fuga-a').click
visibility_test([false,false,true,true])
end
end