LoginSignup
2
0

運ゲー化していた動的UIのテストをリトライするためにrspec-retry_ex gemを導入しました

Posted at

発生した問題

私たちが扱うプロダクト内では、ユーザーの入力値に基づき表示が変化する動的なUIが存在します。
このフロントエンドのテストはRSpecを用いて行っていました。

しかし、このような動的UIの自動テストは、何回かに1回の確率で落ちてしまい、GREENになるかどうかがある意味「運次第」となる傾向がありました。

問題が発生することの課題

変更していない箇所に対してテストが落ち、CIツールの画面上で「Retry」をすることは開発スピードの足を引っ張ります。
そこで、落ちやすいテストに関して自動でリトライしてくれるgemを導入しました。

対象となるテスト

example '試算ができないこと' do
  visit('/try/input')
  fill_in('simulation_postcode_1', with: '100')
  fill_in('simulation_postcode_2', with: '0102')
  sleep(1)
  expect(page).to have_content('申し訳ございません。お住まいの地域はシミュレーションに対応しておりません。')

  fill_in('simulation_postcode_1', with: '100')
  fill_in('simulation_postcode_2', with: '0601')
  sleep(1)
  expect(page).to have_content('申し訳ございません。お住まいの地域はシミュレーションに対応しておりません。')
end

郵便番号の上3桁と下4桁を入力し、その地域がサービスに対応しないことを確認するためのテストです
郵便番号を入力した後 sleep(1) で1秒待ち、画面が変わってからexpectでテストしています。
この箇所でテストが落ちやすく、sleep(10)にしても効果が無いことを確認しました(なぜ?)。

rspec-retry gemとの違い

テストをリトライするgemといえばrspec-retry gemですが、今回導入したのはrspec-retry_ex gemです。
というのも、spec-retry gemは、scenario単位でのリトライを行うgemです。
scenario内に複数のexpectがある場合、途中のexpectでコケるとscenarioを最初からやり直すため、時間がかかる可能性があります。

一方、rspec-retry_ex gemはscenarioの中のexpect単位でリトライを行うため、小さな単位でのリトライができます。
これは、テストに要する時間を短縮することに繋がります。

機能の説明

GitHubに記載されていた例を用いて解説します。

rspec-retry_ex gem導入前

以下のテストに対し、リトライを追加します。

scenario "Some scenario" do
  visit "/some_page"

  fill_in "postcode", with: "1300012"
  expect(page).to have_select("ward", selected: "Sumida")
end

この例ではexpect(page).to have_select("ward", selected: "Sumida")が動的UIなので、これについてリトライを追加します。

基本形

リトライを3回するには、expectに対してretry_ex(count: 3)ブロックで挟みます。

scenario "Some scenario" do
  visit "/some_page"

  fill_in "postcode", with: "1300012"
  retry_ex(count: 3) do
    expect(page).to have_select("ward", selected: "Sumida")
  end
end

リトライ前に処理を追加

リトライ前に画面をリフレッシュさせ、イベントを再発火させるという狙いです。

scenario "Some scenario" do
  visit "/some_page"

  fill_in "postcode", with: "1300012"

  # These codes are executed after the retry fails
  after_retry = -> {
    fill_in "postcode", with: "1000004"
    fill_in "postcode", with: "1300012"
  }
  retry_ex(count: 3, after_retry: after_retry) do
    expect(page).to have_select("ward", selected: "Sumida")
  end
end

導入方法

  • Gemfileに記載
group :test do
  gem 'rspec-retry_ex'
end
  • bundle install
$ bundle install
  • spec/rails_helper.rbに追記
include RSpec::RetryEx

実装したテスト

先程紹介したように、リトライ前にイベントを再発火させるようにテストしました。

example '試算ができないこと' do
  visit('/try/input')
  fill_in('simulation_postcode_1', with: '100')
  fill_in('simulation_postcode_2', with: '0102')
  retry_ex(count: 5, after_retry: -> {
    fill_in('simulation_postcode_1', with: '101')
    fill_in('simulation_postcode_1', with: '100')
    fill_in('simulation_postcode_2', with: '0102')
  }) do
    sleep(1)
    expect(page).to have_content('申し訳ございません。お住まいの地域はシミュレーションに対応しておりません。')
  end

  fill_in('simulation_postcode_1', with: '100')
  fill_in('simulation_postcode_2', with: '0601')
  retry_ex(count: 5, after_retry: -> {
    fill_in('simulation_postcode_1', with: '101')
    fill_in('simulation_postcode_1', with: '100')
    fill_in('simulation_postcode_2', with: '0601')
  }) do
    sleep(1)
    expect(page).to have_content('申し訳ございません。お住まいの地域はシミュレーションに対応しておりません。')
  end

end

結果

「運ゲー」化していたテストが確実に通るようになり、CIでの余計なリトライが不要になりました。

参考

https://tech.enechange.co.jp/entry/2019/02/22/083700
https://github.com/yuyasat/rspec-retry_ex/tree/master

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0