お使いのブラウザはサポート対象外です。

2022年08月05日(金) の日報

3

不安定なテストを安定させたいぞ

サバンナでの不安定なテスト対策の一部まとめ

画像のロードをクリック時に自動的に待つようにした

  • ときおりテストが不安定になる→原因を突き止めてなおすというサイクルがある
  • 今回は画像が入ったことによるクリックミスが原因
  • これまで画像のロードを待つメソッドwait_for_image_laodingを定義して画像のロード待ちでコケていそうなところに適宜使ってきたけど、逐一必要なところを探すのがだるい
    • 今回は対象となる箇所がたくさんあるようで結構な確率で 🔴 になる
  • そこでクリックする直前に毎回画像のロード待ちをするようなハックを入れた
  • だいぶ雑な感じだけど効果はあった模様
  • ポイントとして、タイムアウトでもエラーにはしないのが重要だった
    • 一つでも画像の読み込みに失敗したときに 🔴 になってしまい、それで時々テストがコケていた
    • 画像の読み込みに失敗したときはクリックミスの原因にはならないので無視して 🙆‍♀️
module WaitBeforeClick
  def _wait_for_image_loading
    Timeout.timeout(Capybara.default_max_wait_time) do
      sleep 0.5 until evaluate_script(<<~JS)
        Array.prototype.every.call(
          document.querySelectorAll('img'),
          (e) => e.complete
        )
      JS
    end
  rescue Timeout::Error
    Rails.logger.debug 'timeout _wait_for_image_loading'
  end

  def click(*keys, **options)
    _wait_for_image_loading
    super
  end
end

module Capybara
  module Node
    class Element < Base
      prepend WaitBeforeClick
    end
  end
end

非同期APIの改善

flashメッセージが表示されない

  • 非同期APIがサーバに届くタイミングでテストがコケる、というのが時々ある
  • flashメッセージを設定して次の画面でそれを表示する、というときにAPIのリクエストが挟まるとflashメッセージが表示されなかったり上書きされたりする
  • ↓のように、API時にflashを消費しないようにして対応している
    • これだけでは完璧ではないんだけど発生件数自体の抑制にはつながっている
class Api::BaseController < ApplicationController
  before_action :keep_flash

  def keep_flash
    flash.keep
  end
end

flashメッセージが変わる

テスト中に一回ログアウトしてなにかする、というときにflashメッセージが正しく表示されない問題があった

  • 「ログアウトしました」というflashメッセージを出したい

  • が、ログアウト処理〜トップページの表示の間にAPIが実行される

  • APIはログイン前提なので「ログインしてください」というflashメッセージが設定される

  • トップページには「ログインしてください」と表示される

  • という流れだった。未ログインでAPIを実行したときはflashメッセージを追加せずに403を返すようにして対応した

    • 403を返すようにしたらjsでエラーになった、と解釈されて 🔴 になったので、これを無視するような設定を追加した

ログイン後のページがおかしくなる

  • 「flashメッセージが変わる」件と原因が近い
  • 未ログイン状態でログインが必要なページにアクセスするとトップページに遷移する
  • その後、ログインすると↑でアクセスしたページにリダイレクトする仕様になっている
  • なので未ログイン状態で意図せずAPIを叩いてしまい、ログイン後にAPIのパスにリダイレクトして 🔴 になる、という事案があった
  • APIのパスはログイン後のリダイレクトから除外する、ということにして対応