QAの山下です。
QAグループという名前で横断組織として手動&自動テストやツール開発、プロセス改善など仕組みづくりに取り組んでいます。
今回は LIFULL HOME'S の開発で実行されているE2Eテスト(リグレッションテスト)をシフトレフトし、実行時間を80%短縮した話を紹介します。
ざっくり何をやったのか
- 大規模なリポジトリでのdevelopマージ後のE2Eテストの9割をPR上で実行可能にした
- コードのpushからE2Eテスト完了まで5~8分で完了できる
- 運用上の課題も頑張って解消した
目次
- ざっくり何をやったのか
- 目次
- 結論
- 前提情報
- テストの削除とリファクタを行い、テストケースを3割削減した
- デプロイ後のアプリケーションに対してe2eテストを実行できるようにした
- 開発チームとのコミュニケーションを積極的に行い、運用課題の発見と改善を実施した
- これからやりたいこと
結論
以下の図の通りです。
Git-Flowをベースとしたフローに則り開発されていたリポジトリで、developマージ後に実施されていたE2Eテストの9割をPR上で実⾏できるようにシフトレフトしました。
コードのpushからE2Eテスト完了まで5~8分で完了します。
前提情報
今回のPJの紹介にあたって前提となる情報を記載します。
E2Eテストとは
本番相当の環境で、ビジネスプロセスを最初から最後まで実⾏するテストの⼀種です。(ISTQBより)
LIFULL HOME'Sでは内製の⾃動テストフレームワーク「Bucky」を使ってE2Eテストを実施しています。
リグレッションテストとは
ソフトウェアの変更されていない領域の欠陥を検出するためテストの⼀種。(ISTQBより)
Aの機能に手を加えたのにBの機能でバグが出た!のような現象を検知するテストです。
LIFULL HOMESでのE2Eテストの位置付け
- 重大な問題点がないことを(回帰テスト観点で主要機能の動作)を保証する。
- テストした結果、不具合が発見された場合は修正を行う。修正が完了しない限り、本番へリリースすることはできない。
テストスコープは以下です
- 動かなくなると重大な被害を被る機能群
- 物件の検索や資料請求等
- 過去に障害が起こった機能群
- 確認が漏れそうな機能群
シフトレフトとは
テストおよび品質保証の活動の実施を、ソフトウェア開発ライフサイクル内で可能な限り早く⾏うためのアプローチ。(ISTQBより)
今回はdevelopブランチで実施されていたテストをPR上で実行するようにしたことでシフトレフトを実現しています。
シフトレフトするメリットは以下が挙げられます
- 早期にフィードバックできることで大きな手戻りやバグを未然に防ぎ、全体のテスト時間を短縮しソフトウェアの品質向上が期待できます。
EEとは
- 瞬時に検証環境が手に入るEphemeral Environmentの略称。
- Pull Requestの内容をもとに一定期間アクセス可能な環境の複製をデプロイする機能。
- Vercelのpreview環境のようなもの
- 弊社の全社アプリケーション実行基盤であるKEELの1つの機能です。
対象のプロダクトの規模
今回実施した対象のリポジトリの規模を記載します。
- LIFULLの看板サービスであるLIFULL HOME'Sの主要機能が実装されているリポジトリ
- 1ヶ月間のauthor数: 約100人、Merged PR数: 約200
起こっていた課題
- developブランチマージから本番環境反映まで8.5時間かかっていた
- QAGの工数が1~4時間/日かかっていた
- 基本的に朝9時からdevelopブランチに対して自動テストを実行
- 実行後の結果を確認、バグが検知されれば開発チームに仕様確認
- 14時くらいに本番環境反映
- E2Eテストでバグを検知した時の手戻りの多さ
- Revert対応率は3年連続で50%を超えていた
- QAGと開発チームのコミュニケーションに時間がかかる
- 弊社QAGは横断組織で、機能開発チームに常駐しているわけではありません。そのためE2Eテストが失敗した際に、E2Eテストのメンテナンスが必要なのか、バグなのかがすぐに判断できませんでした。
- 都度開発チームに調査依頼を投げていたので、両チームの負担となっていました。
ここまではこのPJに関する前提状況を書きました。ここからはPJの中で実施したことを時系列順で書いていきます。
テストの削除とリファクタを行い、テストケースを3割削減した
前述したdevelopブランチマージ後に実施していたテストは、合計400ケースほどありました。これらをそのまますべてシフトレフトすると以下の懸念がありました。
※後述のリファクタは保証したい内容は変えずにシナリオを変えることを指してます。例えば元々1ケース1アサート*2 だったシナリオを1ケースで2アサーションするように変更する等です。
- 実行時間が長いことで開発者体験が悪くなる
- 最悪の場合、QAと開発者の対立の原因になる
- 再実行数が増えコストが上がる
これらの問題を解決するため、テストの再設計を実施しました。結果としてテストケース数を3割削減、またテストの実行時間も削減できました。
この項目で実施したことは以下です。
- テストを実行時間順にソートする
- 実行時間が長いものから削除、リファクタ、再設計箇所の洗い出し
- テスト技法を用いて検討
- 該当のテストケースが追加された時の意図(バグチケット等)を基に、現在でも同じテストケースが必要か検討
- レビュー実施
- 開発者との合意形成
- テストの削除、リファクタ、再設計を実施したことによりステークホルダーに影響があるため合意を形成する必要がありました。
- ステークホルダーは機能開発のエンジニア、企画職
- 合意は以下の内容で形成しました
- 対象テストケース
- 削除対象とした理由
- 実装
デプロイ後のアプリケーションに対してe2eテストを実行できるようにした
本題とは離れるので詳しくは割愛しますが、HelmにおけるChart Hooksを編集し、前述のEEデプロイ後にEEに対して E2Eテストを実行するようにデプロイパイプラインを修正しました。
開発チームとのコミュニケーションを積極的に行い、運用課題の発見と改善を実施した
ここまでで「リモートブランチにPushされる度にPR上でE2Eテストが実行される」状態にはできました。しかし作ったら終わりではありません。ここから運用課題とどう向き合ったのかを書いていきます。
挙がっていた運用課題は以下です。
それぞれについて問題の概要、検討事項、解決法を書いていきます。
テスト結果通知のコメントが量産されPRが見づらくなる
問題の概要
現状E2Eテストが完了した際に以下のようなコメントがされます。
画像
開発している時には気づけなかったのですが、コミット数が多くなってくるとコメントがその分量産されPRの見渡しが悪くなるとのフィードバックをもらいました。
検討事項
「PR内に存在する過去のE2E結果コメントを削除→新規のテスト結果コメントを投稿」の処理に変えれば良いのでは?と考えました。
懸念としては、PR内で過去のテスト結果を見ることができなくなることでした。
しかし
- 過去のテスト結果を見ることはユースケースとして多くない
- 別のマネジメントツールがあり、過去の結果を見たくなった時はそこからPRの番号で閲覧できる
ので問題無しと判断しました。
解決法
以下の処理に変更しました。
- PR内に存在する過去のE2E結果コメントを削除
- 新規のテスト結果コメントを投稿
マージ要件を満たせない
問題の概要
このE2EテストはCIとしてPushの度に実行されます。またリグレッションテストとしての役割も持っているので、当然全てのテストが成功してからdevelopブランチに反映されるべきです。
そのため導入時はテストが100%成功していないとマージができないようにしていました。
しかし、このルールでは開発者体験が悪化してしまいました。原因は以下です。
- E2Eテストは他のテストレベルと比較して不安定さが高い
- ネットワークの問題等で1個でも失敗してしまうとマージができない
- 後述の「テストの再実行がやりづらい」問題のため、テストの再実行に10分かかってしまう。
- ABテストが多い
- LIFULL HOME'Sでは多くのプロジェクトが並行して進んでおり、それに比例してABテストも数多く存在します。
- 基本的にはE2Eテストシナリオではメインに採用されている方を期待していますが、自動テスト時に期待していない方を引いてしまった場合、UIやロケーターが変わるので失敗してしまいます。
- 開発者も他チームのABテスト事情を全て把握しているわけではない
解決法
マージ要件に閾値を設ける手段を取りました。
具体的には自動テストのpass率が90%を超えている場合にはマージ可能としました。
検討事項
チーム内で話し合った結果、避けたかったこととしては以下が列挙されました。
- バグの流出
- 自動テストで検知されているバグを無視してマージした結果本番で障害が出る
- E2Eテストの形骸化
- テストが失敗してもマージ可能なため自動テストのメンテナンスをせずに放置される可能性がある。
- 自動テストのメンテナンス不足で失敗が増え、テスト結果が信頼できなくなる等が起こる傾向にある
- 開発者体験が悪くなること
- プロダクトコードに問題が無く、flakyテストによってマージが阻まれる事
- 他チームで実施されているABテストによってテストが失敗し、マージが阻まれる事
- テスト成功率100%を求め続けることで開発者のストレスになる
- 最悪の場合QAと開発者で対立が生まれる
上記の「バグの流出」と「E2Eテストの形骸化」は自動テスト成功率を100%を強いることで解決できますが、3つ目に関しては自動テスト成功率を100%を強いると起こり得てしまう問題です。
過去の自動テストの結果を見て、flakyテストとABテストで期待していないパターンを引いた場合でも90%は下回らないということが分かりました。
そのためマージ要件をE2Eテストのpass率100%→90%に変更しました。
テストの再実行がやりづらい
問題の概要
テストの再実行を行いたい場合、以下の手順を踏む必要がありました。
- EEの再起動
- E2Eテストの実行
- E2Eテストの結果
特にコードの修正をしていない場合の再実行では、E2Eを再実行したいだけのためにEEの再構築も行わなければなりません。
EE再構築からテスト完了まで10分を超えることもあり、これはユーザーにとってストレスでした。
解決法
GitHub Actionsのworkflow_dispatchを使い、E2Eテストの再実行を楽にしました。
以下の流れでテストの再実行が実施されます。
- workflow_dispatchでPR番号を入力する
- 入力されたPR番号から再実行すべきテストケースを取得
- 入力されたPR番号から再実行対象のFQDNを取得
- WorkflowでE2Eテストの再実行用スクリプトを実行
これによってコードの変更をしていない場合でのE2Eテスト再実行の手間が軽減され、時間としては10分→5分ほどにまで削減できました。
これからやりたいこと
シフトレフトすることでE2Eテストの実行時間を80%短縮することができ、早期にフィードバックができるようになりましたが、まだまだ改善できる部分があります。
e2eテストの安定化
現在はUIの変更や改修に対して脆いテストが存在しています。これを解消するためにdata-testidのような自動テスト用の属性をプロダクトコードに導入し、テストの安定化を図りたいです。アラートの仕組み化
前述の通り閾値を設けてマージの可否を決めています。そのため本来メンテが必要なテストケースが放置されてしまう可能性があります。
現在はQAGが定期的にテスト結果をモニタリングし、担当部署にアナウンスしていますが今後はアラートの仕組みを導入して一定の条件で担当部署に通知するようにしたいです。ABテストに対応するためのcookie固定化
前述の通りLIFULL HOME'Sでは多くのプロジェクトが並行して進んでおり、ABテストも数多く存在し、この数に比例して「自動テストで期待していないパターンを引いてしまう」という問題が発生しやすくなります。
これを解消するために「e2eテストからのリクエストだった場合はABテストのcookieを固定化する」ような仕組みを開発者と協力し導入したいです。
これからもQAとして品質改善、開発スピード、開発者体験向上に貢献していきたいと考えています。