このPJは
- 詳細を[自社テックブログで公開](https://www.lifull.blog/entry/2024/06/11/070000)
- 全社MVP受賞
しています。
## 概要
E2Eテストをシフトレフトし、PR上でテスト実行できるようにした。
またテストのメンテナンスもPR作成者が担当できるように運用フローも作成した。
これにより
- リリース時にかかっていたe2eテスト実行時間を2.5→0に短縮した
- featureブランチ→本番環境へ直接反映するフローが選択できるようになった
## 課題と解決法
### 課題
全社横断でE2Eテスト(回帰テスト)をGitflowにおけるdevelopブランチマージ後に実施していたが、以下の課題があった。
1. developブランチマージから本番環境反映まで8.5時間かかっていた
2. QAチームの工数が1~4時間/日かかっていた
2-1.基本的に朝9時からdevelopブランチに対して自動テストを実行
2-2.実行後の結果を確認、バグが検知されれば開発チームに仕様確認
2-3.14時に本番環境反映
3. E2Eテストでバグを検知した時の手戻りの多さ
3-1.Revert対応率は3年連続で50%を超えていた
4. QAGと開発チームのコミュニケーションに時間がかかる
4-1.弊社QAGは横断組織で、機能開発チームに常駐しているわけではありません。そのためE2Eテストが失敗した際に、E2Eテストのメンテナンスが必要なのか、バグなのかがすぐに判断できませんでした。都度開発チームに調査依頼を投げていたので、両チームの負担となっていました。
### 解決法
E2EテストをPR上で実行できるようにし、以下のフローへ改善した
1. featureブランチで開発
2. featureブランチでpushするたびにE2Eテスト実施
3. 必要があればプロダクトコード or テストコードの修正
4. developブランチへマージ
※developブランチではE2Eテスト実施 **しない**
## PJ詳細
### 大まかなタスク
1. PJ全体のWBS作成
2. MTGの頻度や内容の決定
3. 現状の課題の洗い出し
4. E2Eテストの再設計
4-1.テスト実行時間が長く、開発者体験悪化を防ぐためテストの実行時間を短縮する必要があった。不要なテストの削除、テストのリファクタを実施。
これにより合計400ケースから3割削減した
5. 運用フロー作成
コードのpush→自動テストの実行→通知先の選定→自動テスト/プロダクトの修正の流れ
6. テスト実行基盤となるk8sの構築
6-1.インフラチームが環境は作ってくれていた(後述のKEEL)ので、job, pod, containerの構成
7. 運用開始
8. 運用課題(後述)を開発チームと協力しながら解決
### 工夫した点
#### GitHub ActionsでのAWS認証をOIDCで実装
このPJではAWS認証をIAMユーザー認証からOIDCによるIAMロール認証に切り替えました。
IAMユーザー認証の場合、GitHub Actionsのシークレット変数にAWS_ACCESS_KEYやAWS_SECRET_ACCESS_KEYなどの機密情報を保存する必要があります。万が一これらが漏洩してしまうと、AWSのリソースが不正に操作されてしまいます。
OIDCによるIAMロール認証を導入することで、GitHub Actionsのシークレット変数に機密情報を保存する必要がなくなり、セキュリティを向上させることができました。
### 運用課題とその解消法
#### テスト結果通知のコメントが量産されPRが見づらくなる
テスト結果はPRにコメントする形で表示しています。
開発している時には気づけなかったのですが、コミット数が多くなってくるとコメントがその分量産されPRの見渡しが悪くなるとのFBをもらいました。
#### 解決法
以下の処理に変更しました。
PR内に存在する過去のE2E結果コメントを削除
新規のテスト結果コメントを投稿
#### マージ要件を満たせない
このE2EテストはCIとしてPushの度に実行されます。またリグレッションテストとしての役割も持っているので、当然全てのテストが成功してからdevelopブランチに反映されるべきです。
そのため導入時はテストが100%成功していないとマージができないようにしていました。
しかし、このルールでは開発者体験が悪化してしまいました。原因は以下です。
- E2Eテストは他のテストレベルと比較して不安定さが高い
ネットワークの問題等で1個でも失敗してしまうとマージができない
後述の「テストの再実行がやりづらい」問題のため、テストの再実行に10〜17分かかってしまう。
- 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%に変更しました。
#### テストの再実行がやりづらい
テストの再実行を行いたい場合、以下の手順を踏む必要がありました。
1. EEの再起動
2. E2Eテストの実行
3. E2Eテストの結果
特にコードの修正をしていない場合の再実行では、E2Eを再実行したいだけのためにEEの再構築も行わなければなりません。
EE再構築からテスト完了まで17分かかることもあり、これはユーザーにとってストレスでした。
#### 解決法
GitHub Actionsの[workflow_dispatch](https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch)を使い、E2Eテストの再実行を楽にしました。
以下の流れでテストの再実行が実施されます。
1. workflow_dispatchでPR番号を入力する
2. 入力されたPR番号から再実行すべきテストケースを取得
3. 入力されたPR番号から再実行対象のFQDNを取得
4. WorkflowでE2Eテストの再実行用スクリプトを実行
これによってコードの変更をしていない場合でのE2Eテスト再実行の手間が軽減され、時間としては17分→7分ほどにまで削減できました。
## 使用技術
- 弊社のアプリケーション実行基盤を利用。
- AWS ECS
- 内製テストフレームワークである[bucky](https://qiita.com/rueyjye/items/570ce17d698819f99091)
- shell
E2Eテストの実行フローは以下の通りです。
1. PR作成後に一時的な検証環境であるEphemeralEnvironment起動
2. EphemeralEnvironmentの起動後にdockerコンテナが起動
3. dockerコンテナからECSを実行
4. ECSに定義されているタスクからE2Eテスト実行
5. テストの実行結果がをshell scriptで処理しPRにコメントで通知
6. 基本的にはテストが全成功がマージの必須要件
## 結果
- リリースの速度が向上。
- リグレッションによるrevertの回数が減少。
##### 多重実行防止
テスト実行時に同じテストが複数回実行されることを防ぐため、テスト実行中にテストの実行を操作する仕組みを導入しました。
###### 起こっていた問題
「pushされるたびに自動テストが走る」仕組みになっているので、連続でpushされた場合に同じテストが複数回実行されることになります。
これでは余計なコストがかかるだけでなく、アプリケーションに余計な負荷がかかっていました。
###### 解決策
新規でテストが実行される際に、実行中のテストを停止する仕組みを導入しました。
具体的には以下の流れです。
1. コードがpushされた際に、同じPRに対して実行中のテストがあるかを確認
2. 実行中のテストがある場合、そのテストを[stop-task](https://docs.aws.amazon.com/cli/latest/reference/ecs/stop-task.html)を使って停止
3. 新規でテストを実行
##### 結果
同じテストが複数回実行されることを防ぐことができ、テストの実行回数を減らすことができました。
またECSのコストも削減でき、アプリケーションにかかる負荷も軽減できました。
##### data-test-idの推進
E2Eテストのlocatorを記述する際に、data-test-idを利用することで、テストの安定性を向上させました。
###### 起こっていた問題
シフトレフトによりテストの実行回数が増えたことで、flakyテストの存在が顕在化しました。
またPR作成者がテスト結果を確認する手間が増えてしまいます。
###### 解決策
QAグループで議論した結果data-test-idの導入を決定しました。横断プロダクトでの導入になるため他部署との調整が必要で以下の流れで進めました。
1. プロダクトエンジニアで興味ある方を巻き込み、E2Eテスト安定化チームを立ち上げた
1. フロントエンドに手を加えることになるためその領域のスペシャリストにも参加してもらいました
2. そのチームでdata-test-idの導入について共有し、チームメンバーの所属部署に種まき&懸念がないかの確認を依頼
1. ここで皆さんが早めに動いてくださってとてもとても助かりました
3. QAグループでdata-test-idの命名規則の決定し導入リポジトリのgithub Discussionsにて共有
1. 命名規則や運用フロー等に関してすり合わせを行い導入決定
##### 結果
少しずつですが導入され、導入されたプロダクトコードでのテストは安定性が向上しました。
ある程度導入された段階で、flakyテストをモニタリングし数字も出していこうと思います。