テストの分類として開発者に馴染み深いのは、検証の対象となるコードの範囲や粒度での分類でしょう。範囲が狭く粒度が細かい順に、ユニットテスト、インテグレーションテスト、E2E
現場の混乱
実は、範囲や粒度による分類に現場は混乱しがちです。
複数のレイヤ、たとえばコントローラとモデルをまたいで検証するテストをインテグレーションテストと呼ぶ人もいれば、それもユニットテストと呼ぶ人もいます。ユニットテストはファイルシステムに触ってはならないという人もいれば、データベースに触ってもよいという人もいます。こういった混乱は、組織や時間をまたいだ知見の共有を妨げます。
テストサイズとは何か
そこで、近年注目される自動テストの分類がテストサイズです。これはGoogle社内から広まり始めた分類で、自動テストに使用されるリソースの量や実行場所、実行時間に注目します。テストサイズにはSmall、Medium、Largeがあります。小中大というわけですね
単一のプロセス内で動作するテストをSmallテストと言います。非常に高速に動作し、かつスケールしますが、単一プロセス内で動作させるので外部リソース
Smallテストの制約を緩和し、単一のマシンに閉じた環境であれば外部リソースの利用を許容するテストをMediumテストと呼びます。たとえば、コンテナ技術を使えば単一のマシンの中でもデータベースサーバやWebサーバを立ち上げて通信するテストもできます。動作速度目標は1件1秒未満で、最長5分で強制終了されます。
Mediumテストの制約をさらに緩和し、自動テストからリモートマシンへのネットワークアクセスなども許容するテストをLargeテストと言います。本番環境やそれと同等のインフラを利用したテストなどが相当します。動作速度目標は
明確な基準を備える
短くまとめると、Smallテストは単一のプロセス内、Mediumテストは単一のマシン上で実行され、Largeテストの実行には制約がありません。
テストサイズとテストの範囲や粒度は独立した概念ですが、おおむね相関しています。多くの場合ユニットテストはSmallテストでもあります。ただ、現場で混乱が生じがちなあいまいな領域でこそ、テストサイズの明確な基準が活きてきます。
たとえば、コントローラ、モデル、ビューをまるごと実行範囲に入れていても、データベースをテストダブルで置き換えていて単一のプロセス内で動作するテストはSmallテストです。モデルのメソッド1つだけのユニットテストでも、テストの実行にローカルホストの実データベースとの接続が必要なものはMediumテストというわけです。
Webシステムの場合、言語の実行環境だけで動かせるのがSmallテスト、Dockerのコンテナなどを組み合わせて動かすのがMediumテスト、本番同等の環境にデプロイして動かすのがLargeテストと考えるとイメージしやすいでしょう。
CIとの親和性が高い
現代の開発で重要なのは、質の高いソフトウェアをより高頻度でより確実に提供できるように複数のフィードバックループを形成することです。そのために、コミットが自動的にビルドされ、さまざまな環境でのテスト実行結果が報告され、マージやデプロイ、リリースなどの判断を支えるCI
CIの目的の一つが、問題のあるコード変更をできるだけ早くかつ自動的に捕捉することです。その実現には、高速で信頼性の高いテストが鍵になります。
この目標にテストサイズがフィットします。Smallテストは高速かつ決定性のある動作をします
Largeテストは通信先のサービスやデータベースなどに本物を使うので本番環境で動作する自信を得られます。その代わり、準備が難しく、動作は遅くかつ非決定的になりがちです。テスト失敗時も原因の分析は難航します。実はコードに問題はなく、実行が不安定なだけというようなテストは信頼不能テスト
実行しているテスト環境が本物の挙動を反映している度合いを忠実性
自動テストを常に実行し続ける時代では、CIのワークフローのどこでどのような自動テストを実行するかが重要です。自動テスト群をテストサイズでフィルタリングできれば、ワークフローの最初のほうで小さいサイズのテストのみを実行し、後半でより大きいサイズのテストを実行できます。これにより、できるだけ早期に効率的に問題を把握し、チームの判断や自信を支える、速度と忠実性のバランスがとれたワークフローを構築できます。
テストサイズを支えるスキル
Smallテストでは、自分で書くテストダブル
Mediumテストでは、単一マシン内でテストの忠実性を高めるために、第三者が開発した代替実装
Largeテストでは、不安定な外部ネットワーク通信や、ゼロリセットができず、ほかのテストの実行とも干渉する環境などに起因する非決定性を可能な限り抑えるテスト実装スキルが求められます。
テストコードにテストサイズを紐付ける方法は、テストのタグ付け[2]や、ディレクトリ名やファイル名、関数名への命名規則適用などが挙げられます。
おわりに
基準が明確でCIとも相性が良いテストサイズを活用し、開発を効率化していきましょう。