23.2~4
- TAP(Test Automation Platform)
- Google Takeout(データバックアップ・ダウンロードプロダクト) の CI 事例
- モノリポのおかげで、すべてのコード変更は TAP を通るようになっている
- 日々5万件以上の修正+40億のテストケースを処理
- Continuous Build: 素早く、持続的に Issue を発見するために行われる
- CBを通る意味: 各チームで作った提出前のテストを通過したら 95% 以上の CB テストを通過 (経験的)
- TAPの非同期テスト: 提出後のテストが失敗したら早めに修正するG特有の文化確立(他チームを邪魔しないように)
- Build Cop: ↑のために導入したバグフィックス担当官制度、バグを発見したら一先ずバグフィックスを(Rollback or 追加修正)
- 実際: テスト通過前のコミット(+Build cop)で時短+妨害最小化
- 大型テストの問題: どの修正より失敗したテストか(本来は解決が容易であるはず)
- なぜ解決が難しいか: テストインフラの問題 + TAP が全ての変更に対して全てのテストを毎日回せない(変更関連部分のみテスト実行)
- テスト失敗の原因探しに速度をつけよう
- TAP が失敗した Batch を修正部分別に分けて再びテスト実行
- 変更された部分に対し、バイナリー検索を提供(開発者が確認できるように)
- 失敗を発見したら早く復旧(Build Cop の役目) → その中1番効率的なのはロールバック
- TAP の最新アップデート: 失敗の原因を分かった場合(+自動で可能であれば)自動ロールバック
- 相互補完: テストなしには安全ロールバックもない、ロールバックがなければ失敗したテストも直せなく、システムの信頼度が下がる
- Forge: 大半のビルド・テストはこのシステムで行われる(並列性の最大化のため) → 限られたリソースの問題が発生
- テストの取捨選択: 全ての変化のダウンストリーム依存関係グラフを分析 → Forge/Blaze でほぼリアタイ分析・TAP 転送
- TAP のテスト速度: 変化が小さくなるほどテストが早く進める → 開発者たちがコード変更を小さくこなす
- データバックアップ・ダウンロード用のプロダクト(2011~)
- 効果的な CI の価値: 肥大化された Takeout プロジェクトを健全に運用するようにできた
- 問題
- 他サービスでバックアップ機能を連携し初めて、バックエンド化された
- 各サービスごとにバイナリーを少しずつ修正して提供
- フラグ Issue: 1インスタンスのフラグが他のところにも影響を与え、ビルドが失敗
- さらなる問題: 修正時に手動でテストを回すのが現実的に無理
- 解決
- 各インスタンスをサンドボックス化 → そうしてもテストデータ・統合テスト環境の復旧が問題
- 提出前テストからサンドボックスの環境を引継ぎ使用(コミット後の環境に拡張できるように) → テストアカウントのセキュリティ防護基準の適用を可能にし、E2E テストが実行可能
- コミット後 CI 実行は 2時間ごとに、最新コード・設定を受け止め RC バージョンを生成しテスト
- 教訓
- Takeout プロダクトのテストを提出前に移してから失敗が半分になった
- E2E を提出後 2時間へ移し、犯人の集まりを 1/12に削減した
- 問題
- Takeout PF化 → 各プラダクトがプラグインを追加
- プラグインが多すぎてテスト失敗のログが複雑になった
- 解決
- パラメタ化されたテストの実行で動的・設定ベースへテストをリファクタ
- 失敗ログの情報表示を改善(ログへのリンク、エラーメッセージ) → デバッグ・ログ転送を自動化
- 教訓: CIのアクセス可能・行動可能なフィードバックは生産性を向上
- 問題
- 結局 G全社の Issue を掴めるテストベッド化
- 失敗を切り分けるプレセス(Takeout 内か外か)を改善する必要が発生
- 解決: 本番にもコミット後 CI のようなテストを実行(Gの他サービスリリースなど)
- 教訓: 失敗を切り分けるに効率的な方法は本番にもコミット後 CI テストを行うこと
- 課題: 他サービスが複雑になる程 CI と本番の主導比較はコストが高くなる
- 将来の改善: コミット後 CI での密閉テストで Takeout のテストを安定化
- 問題
- 他プロダクトのバグのせいで Takeout のテストがほぼ全部失敗
- 優先順位が高いバグがビルドを失敗させ、そのテストコードをコメントアウトし始めた
- 環境(機能が追加されたか否か)により、手動でテストの実行・スキップを決定するように
- 解決
- 他チームのバグはバグ内容をタグし、該当チームに転送
- タグされたバグは Suppress し、テストは成功させる
- 機能追加の問題: 環境による結果値を開発者たちから募集、各環境を全部テスト
- バグが解決されたらタグを除去
- テスト自体が信頼不能(Flaky)ならテストが通ってもタグを剥がさない
- 教訓
- すぐ解決し難しいバグのテストを「除外」するのは、テスト失敗より解放され、(プロダクトへの)自信を堤高
- 機能追加の管理を含めるテストのメンテナンス自動化はテスト環境を整理する且つ技術負債を予防 (DevOps 用語で MTTCU: Mean Time To Clean Up)
-
改善: バグ報告とタグつけを自動化
-
さらなる課題: 稀に発生する上流のシステムエラーを切り分ける → セキュリティアップデートなどのせいでファイルの復号化が進んでしまう問題など → 上流のシステムは自主テストを行い、Takeout の CI でチェックする方法がない → 上流のシステムのステージング環境を構築するのも互換性の問題でメンテ難しい
- 本番で跳ねた問題を解決するコスト: ユーザーの被害、チームのストレス蓄積・行き込み低下
- 初期に導入するほど ↑ の費用を払うことが減る
- Gの CI プロセスと自動化が「完璧」とは言えない
- CI 自体もソフトウェアであり、完結されたものではなく、進化する要求により調整されるもの
- Takeout の CI と、今後の改善点を通して確認した
- CI は「どのテストを」、「いつ使うか」を決定
- CI はコードベースが成熟となり、スケールアップされるほど益々必要となる
- CI は素早かで安定的なテストを提出前に、遅くて比較的に「非決定性」を持ったテストは提出後におくべき→テストを最適化
- アクセス可能であり、行動可能なフィードバックは CI を更に効率的にする
感想
- Gの CI は Alerting と言ったことが理解できるほど、CI の説明でテストの比率が高い
- CI でのテストを「提出前テスト」と「提出後テスト」に分割する文化、テスト時間による分類など色々考え直すきっかけになった