フィードバックループを高速に回すためのテスト自動化アーキテクチャを設計した話

# フィードバックループを高速に回すためのテスト自動化アーキテクチャを設計した話

## はじめに

はじめまして。

食べログの技術部 Developer Productivity チームの @hagevvashi です。

Developer Productivity チームは 2021 年 10 月に誕生したできたてほやほやのチームです。

「開発サイクルのフィードバックを素早く、リッチにすることで最高の開発・テスト体験を実現する」というミッションを掲げています。

食べログ Advent Calendar 2021 の初日にチームメンバーの @shibu_shibu が「[カバレッジ10%のテスト自動化で7割以上のテスト工数を削減できる!?〜ゆもつよメソッドを使った要求分析〜](https://qiita.com/shibu_shibu/items/b6a7e39ac5760e26b7cb
)」というタイトルで、開発者のテスト工数の削減と、バグの検知率の維持を目的としたテスト自動化の要求分析についての記事をお届けしました。

https://qiita.com/shibu_shibu/items/b6a7e39ac5760e26b7cb

この記事ではその自動テストをどのようにアーキテクチャ設計するかについて得た学びを共有したいと思います。

## 解決すべき課題

テスト自動化はうまくフィードバック獲得のプロセスが設計できると、生産性向上のための非常に有効な手段となります。

ですが一方で闇雲に自動化してしまうと、プロセスに新たな課題を生んでしまう懸念があります。

というのも、自動化後はフィードバックループを細かく回していきたくなるため、並行してたくさんのテストを同時に実行したり、コード変更毎にデプロイとテストを自動実行するようになりますよね。

闇雲にたくさんのテストを並行して同時に実行すると下記の問題が発生します。

- テストの実行結果が不安定になり毎回異なるので調査時間がかかる
- 不安定なテストが続くとテスト結果が信用できなくなってしまう

また、コード変更毎にデプロイとテストを自動実行すると下記の問題が発生します。

- どのバージョンのプロダクトのテスト結果なのかを判別するのが大変

これら 3 つの原因によって、コード変更後、テストの結果をフィードバックとして得るまでに時間がかかるという課題が発生してしまいます。

こういったテスト自動化の課題を洗い出すためにユースケースダイアグラムを用いてプロセスの洗い出しを行いました。

## ユースケースダイアグラム

### ユースケースダイアグラムの作成

食べログでは100人を超える開発者に個人のテスト環境が割り当てられており、個々人がテストしたいバージョンのプロダクトを一通りの開発が終わった後デプロイしてテストを手動で実行しています。

そのプロセスがテスト自動化によってどのように変化するのかをユースケースダイアグラムを用いて表現することで、アーキテクチャのリスクを可視化することにしました。

図はテスト実行とデプロイのプロセスについてのユースケースダイアグラムになっております。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137031/cff9ac85-3640-fa20-bc7f-bc0bc4333ca1.png" width="600">

### 学び

テストクライアントとテスト対象環境が N 対 1 の関係になっているため、テスト自動化をした後にコード変更毎にテストを実行するようにプロセスを変更すると、テスト対象環境が圧倒的に足りなくなります。

ユースケースダイアグラムでプロセスを表現することで、テスト自動化によって変化する点とアーキテクチャのリスクが分かってきたことが大きな成果でした。

#### テスト自動化によってプロセスに起きる変化

- 自動化前は1週間に1回程度、同時実行する人は一人だけ
- 自動化後は開発者100人以上がコード変更の度に実行したい

#### アーキテクチャのリスク

- テストクライアントとテスト対象環境が N 対１の関係になっている

## 品質要求

### 品質特性を用いて要求分析

ユースケースダイアグラムを用いてテスト自動化によって変化する点とアーキテクチャのリスクが分かってきました。

アーキテクチャのリスクがなんとなく分かってきたため、洗い出したプロセスで担保する必要のある品質がどのようなものなのか分析を進めてみました。

分析の際に用いた品質特性の分類は [ISO25000](http://kikakurui.com/x25/X25010-2013-01.html) です。

これは私が JSTQB の勉強の時に触れたので、親しみやすかったからという理由で使用しています。

図ではテスト実行とテスト対象環境の 1 対 N 関係に関しての品質要求が表現されています。

|機能性（合目的性/正確性/相互運用性/気密性/適合性）|信頼性（成熟性/障害許容性/回復性/適合性）|効率性（時間効率性/資源効率性/適合性）|
|:---|:---|:---|
|どのバージョンに対してテスト実行したかが追跡可能（トレーサビリティ）|同一バージョンに対して実行したテストは常に同じ結果になる（再現性）|コード変更後テスト結果がすぐに分かる（スケーラビリティ）|

### 学び

要求分析表を作ってみてよかったことは、品質特性の分類ごとに考えることができるため、隠れている品質要求を漏らしにくかったことです。

再現性やトレーサビリティについてもプロセスで達成すべき重要な品質要求であることが分かったことが成果です。

プロセスで達成すべき重要な品質要求は下記です。

- 実行頻度とエンジニアの数に対してスケールしたい（スケーラビリティ）
- どのバージョンに対して実行したかを追跡できる（トレーサビリティ）
- 同一バージョンに対して実行したテストが常に同じ結果になる（再現性）

これら３つの品質が達成されていないと、テストプロセスの中でいつでも誰でも自動テストを実行すること、という自動テストから効果的にフィードバックを獲得するために重要なことが実現できなくなってしまいます。

## アーキテクチャ設計

テスト自動化で達成すべきプロセスの品質要求が判明したのでどのようなアーキテクチャで品質要求を達成していくか設計します。

### トレーサビリティと再現性の担保のための設計

トレーサビリティと再現性の担保のために 2 つ大きなアーキテクチャの設計をしました。

- デプロイとテスト実行を一緒にする
- デプロイ開始からテスト完了までの間、ロックする

手動実行の時はデプロイのプロセスとテスト実行のプロセスは別々に行われていました。

テスト自動化のアーキテクチャではデプロイからテスト実行までを一つのトランザクションの単位とします。

なぜこうしたのかについて説明します。

どのバージョンでテストが実行されたのかをレポートで確認するために、デプロイしてからテスト完了までの間に他の方のコード変更によるデプロイが挟まれないようにする必要があります。

また、デプロイからテスト完了までの間に他のデプロイが挟まれてしまうことによってテストの再現性が失われる可能性があります。

これらを防ぐためにデプロイしてからテスト完了までの間は環境を専有することにして、他のデプロイとテスト実行ができないようにします。

### スケーラビリティ担保のための設計

ロックするとスケーラビリティが損なわれないのか？という疑問があると思います。

スケーラビリティ担保のために 1 つアーキテクチャの設計をしました。

- プロジェクトチーム単位で、CI とテスト環境をスケールできるようにする

食べログはマトリクス型の組織構造を取っており、職能別の組織とは別に、解決すべき課題毎にプロジェクトチームが組まれています。

このプロジェクトチームごとに CI Pipeline、テスト実行 job、テスト対象環境がそれぞれ独立して動くようにすることでスケーラビリティを担保します。

こうすればビジネスが成長し、プロジェクトチームが増えた時にもうまくスケールすることができるようになります。

### 設計図

これらの設計を図にしたのがこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137031/085905e5-a382-70ae-04a5-f2b98d47db2f.png)

デプロイとテスト実行が一つの単位であること、他のソースコード変更に対してロックの機能が働いていること、プロジェクトチーム数に対してスケールしていることを示しています。

「ロック中」のイメージは、例えば、プロジェクトチームAのブランチproject-a/feature-fooのコミットazのデプロイとテスト実行中に、project-a/feature-barのコミットbzがあったとしても、コミットbzのデプロイとテスト実行を止めていることを想像していただくとよいかと思います。

### 学び

最初に挙げた課題を解決する方法がアーキテクチャとして表現できたことが非常によかったです。

また、図示していくことで、将来的には一回のテスト実行ごとに捨てられる環境を作れるようにするという構想を考えられたりしました。

## 考察

今回アーキテクチャ設計について触れてきましたが、テスト自動化のアーキテクチャ設計については、2014 年頃に「システムテスト自動化 標準ガイド」が日本語訳されてからテスト自動化に関する議論が活発になりました。

しかし、2021 年現在でもテスト自動化の導入失敗に関する言説は散見されます。

[テストを自動化するのをやめ、自動テストを作ろう](https://speakerdeck.com/tsuemura/tesutowozi-dong-hua-surufalsewoyame-zi-dong-tesutowozuo-rou)

[なぜ自動テストの導入は失敗するのか？](https://nagise.hatenablog.jp/entry/2021/04/29/135959)

テスト自動化を成功させるためには、フィードバックループによってテストを起点に設計品質を改善するプロセスに変えていく必要があります。

どのようなプロセス品質が必要か要求分析をし、その品質を満たすためのアーキテクチャ設計をすることで、設計品質を改善するフィードバックループが回るプロセスをテスト自動化によって実現することができます。

今回やった品質要求分析は、テスト自動化によってどのプロセスでどのような品質要求を達成すべきかリストアップするものでした。

トレーサビリティ、再現性、スケーラビリティを担保することでフィードバックループを高速に回すことができるようになり、テスト自動化が成功する目処が立ちました。

## まとめ

アーキテクチャ設計によってどのような課題が解決できるのかを改めて確認してみましょう。

解決すべき課題はコード変更後、テストの結果をフィードバックとして得るまでに時間がかかってしまうことでした。

ユースケースダイアグラムと品質特性による分析から「トレーサビリティ」「再現性」「スケーラビリティ」を同時に達成することが求められる品質要求という事がわかり、上記の課題を解決する方法がアーキテクチャとして表現できました。

今回はモブでアーキテクチャ設計を進めたのですが、そのおかげで不慣れな私でもなんとかめっちゃよいアーキテクチャが設計できたかと思います。

課題を解決するためのアーキテクチャが表現できたことでテスト自動化が成功する自信を持てるようになりました。

現在はこのアーキテクチャを実現するためにモリモリ実装中なのですが、このアーキテクチャを実現するところまで実装すれば後はテストコードを増やしていくだけですのでプロジェクトの見通しがよくなったと思っています。

## 最後に

現在、食べログでは一緒にお仕事をしてくれるSETエンジニアを募集しています。

これからもりもり自動化に取り組んで参りますので、ご応募お待ちしております。

正式なご応募以外にも、転職活動前の情報収集やランチを交えた情報交換なども大歓迎です。その場合はご応募いただくときに、フリーテキスト記入欄に「カジュアル面談希望」とご記載ください。

https://hrmos.co/pages/kakakucom/jobs/1011026

明日は@yzusaさんで「食べログでNewRelic導入した話」です。

お楽しみに。