sleep rand(1.year) 年に一度は更新するであろうブログ

Capybara + Poltergeistで不安定なテストはCSSでアニメーションを切ってみよう

今関わっているプロジェクトではRailsのfeature specでCapybara + Poltergeist を使っているのですが、 以前から不安定なテストに悩まされていました。そして、今年に入ってからその不安定さが大きく増し、テストの 実行回数に影響が出てきました。そのため、きちんと原因を調査することになりました。

調べてみると、ボタンを押す操作が正しく動いていないケースが多いことがわかりました。そこで、以下の3つの 仮説を立て、 それぞれについて検証してみました。

  • 仮説1:そもそもボタンが表示されていない。
  • 仮説2:ボタンは表示されているが、ボタンが押せていない。
  • 仮説3:ボタンが押せているが、JS側が関知できていない(JSフレームワークはVueを利用)。

まず最初の「そもそもボタンが表示されていないケース」ですが、これは

find('#id_of_button', visible: false)

とすれば検出可能です。調査したところ、要素自体はあることがわかりました。

次に「ボタンは表示されているが、ボタンが押せていない。」ケースですが、これについては

click_on 'ボタンの値'

となっているところを、

find('#id_of_button').trigger(:click)

と置き換えれば検証できます。これを行ったところ、テストによってはこれで通るようになりましたが、 ボタン押下後に表示されるべき要素が表示されない(正確にはvisibleな要素をだけを対象にしたときに見つからない) という問題が新たに発生しました。また、これにより最後の「ボタンが押せているが、JS側が関知できていない」 という 部分については、調査する前に仮説が否定された形になりました。

ここまできてまた原因不明の状態に戻ったのですが、 さらに調べるとCSS animationが原因という情報を得ました。 Capybaraのclick_onで呼び出されるPoltergeistのメソッドは、要素の位置を取得してその座標をクリックしているらしく、 CSS animationが効いているとクリックした座標に要素が無くなっている、ということが起こるようでした。

そこで、先ほどのエントリにあるCSSをview側でRails.env.test? が真のときに読み込むようにした結果、動作が不安定なfeature specは大きく減り、 retry回数も激減しました。

不安定なfeature specにお悩みの方は、一度トライする価値があると思いますが、CSS animationを無効にしているため、実際にユーザーが 見る画面とは異なる画面をテストしているという点は留意が必要です。また、当然ですがfeature specでCSS animationに関連するような テストを書いている場合はそのテストだけCSS animationを無効化しないなどの方法が必要でしょう。