OpenWork Tech Blog

OpenWork を運営するエンジニアによるテックブログです。

自動テスト改善の歴史

f:id:miriejob:20211006215309p:plain
警報装置の定期メンテナンスはとても重要

Webエンジニアの入江です。気づけば入社5年目、かなりの古株になってしまいました。
勤続5年で、2週間の休暇が取得できるのですが、このコロナ禍、果たしてバカンスできるのでしょうか・・。


さて、弊社では、有志で自動テストの改善に取り組んでいるのですが、過去の変遷を振り返ってみると意外に面白かったので、ご紹介してみようかと思います。
まずは、テスト実行時間とテストクラス数のグラフをお見せします。
(直近数ヶ月以外のデータは、Slackやコミット履歴から算出しているので不正確ですが、雰囲気が伝われば幸いです。)

f:id:miriejob:20211006215618p:plain

青い太線がテスト実行時間(左軸)で、それ以外がレイヤ毎のテストクラス数(右軸)です。

以下、phpunitの導入期から時系列で振り返っていきます。
グラフと見比べながら読んでいただくとイメージが湧くかもしれません。

2016年 テスト文化黎明期

このあたりからphpunitの運用が始まったと推測されます。
phpunitの実行方法は、シェルスクリプトにコマンドをずらりと羅列する形でした。
内訳を見ると、FunctionalTestがほとんどな逆ピラミッド状態でした。
また、所々コメントアウトされており、恐らく動かなくなったテストと推測されます。

2017年 E2Eテストの導入

SeleniumIDEの運用が開始されました。
当時は、リリース担当者が日次で実行し、必要に応じてメンテナンスも行うという形で運用されていました。

またphpunitのテストも順調に増加し、利便性のためSlack通知の方法も見直されました。

  • PlainTextから、テキストファイル形式への変更
  • 実行結果にテストクラス名を記載するように変更

2018年 SeleniumIDE 卒業

SeleniumIDEは、運用に載せるには保守性の面で課題がありました。
また、当時利用していたツールのサポート期限が切れることもあり、E2Eテストツールの乗り換えが検討されました。

いくつかのツールを検証した結果、学習コストを重視してphp-webdriverが導入されました。
phpunitから起動できるため、リリース時のCIにも組み込まれました。
そしてこの頃から、E2Eテストの不安定さと実行時間に悩まされることになりました。
実行時間については、暫定的に並列化(2並列)することで急場を凌ぐことができましたが、不安定さとの戦いは今も続いています。

また、テストが増えたことによりエラーを見逃すリスクがあったため、エラー周辺のログが別途summaryとして投稿されるようになりました。

2019年 自動再実行の導入

E2Eテストは不安定になりがちです。
エラーになったテストは、リリース担当者が都度手動で再実行をしていたのですが、コスト削減のため自動で再実行する仕組みを導入しました。
当時の実装は、phpunitが出力するERRORやFAILUREを拾っていたため、メモリエラーなどphpunitが異常終了した場合は依然手動再実行のままでした。

f:id:miriejob:20211007083309p:plain
ランプの魔人が再実行してくれる

2020年 テストリファクタ

この頃から、テスト実行時間が40分を超え始めました。
1日4回リリースのタイミングを守るには、ギリギリの状態です。
無駄なテストの削減/効率化を行い、さらに負荷の小さなテスト群を3並列化しました。

また、下半期にはリファクタチームの創設やDDD勉強会など設計に関する意識が醸成され、適切なレイヤ分けや依存の整理、責務分割により、ユニットテストがかなり書きやすくなったと感じます。その影響か、直近のユニットテスト数が急増していることがグラフから読み取れます。
(テストコードそのものの品質は未検証)

2021年

自動再実行のリファクタ

メモリエラーの頻度がそれなりにあったり、phpunitの構文エラーでそもそも実行できていない事例が見つかったことなどから、phpunitの終了コードを拾って再実行する方法に変更、異常終了も再実行対象になりました。

テスト実行ログの記録

テストコードの実行結果を分析できるように、実行ログをDWHに格納するようにしました。
時系列で実行時間の推移を調べたり、エラーが起きやすい不安定なテストがわかるようになりました。

超不安定なテストの修正

高頻度でエラーになるテストがいくつかあったため、改善しました。
主な原因は以下の2点でした。

  • E2Eテストで使用する要素の待ち時間の設定ミス(sleepで決め打ちにしていたり、待つべき要素が違ったり・・・)
  • DBに一括で登録すると作成日が同一になるためソート順が不安定になる

(運が悪ければ、OKになるまで数十回というテストもあり、E2Eテストを敬遠するようになってしまった人も少なからずいると思います・・。)

今後の展望

色々と改良を重ねてきましたが、改善ポイントはまだまだ多いです。
当面は、実行時間の短縮をメインに行う予定ですが、長期的には不足しているテストを拡充するための環境整備などに着手していきたいと考えています。

短期目標

  • SQLテスト専用のDB設置
    条件が複雑になるとテストしたくなりますが、SQLテストは時間がかかります。
    複雑なクエリを書くべきではないという話もありますが、まずはデータ量を減らしたDBを利用してテストすることを検討しています。

  • DBアクセスの削減
    ユニットテストなのにDBにデータ登録してテストしているケースがあるため、永続化をやめる修正を入れようとしています。
    プロダクションコードの作りの問題もあるので、全てに手を付けるのは難しいですが、費用対効果の大きな部分を解消できればと考えています。

  • E2Eのあり方を再検討する
    現状、E2Eで何を検証すべきかという指針がありません。
    また、機能の重要度によってはリリース時のCIに載せないという考え方もできるのではと考えています。

長期目標

  • テスト関連のサマリレポート通知(週次or月次)
  • テストカバレッジの計測
  • ビジュアルリグレッションテスト
  • ElasticsearchへのデータIOテスト
  • javascriptのユニットテスト

業務の合間に進めているため、歩みはゆっくりですが、少しずつ良い方向に進んでいければと思います。

さいごに

オープンワークでは、一緒に働く仲間を募集しています。
自動テストに限らず、色々な所に落ちている改善のタネを拾って、生産性向上につなげていきましょう。

vorkers.jp vorkers.jp