結合テストと呼ぶのをやめた話
はじめに
最近、意図的に﹁単体テスト﹂﹁結合テスト﹂という呼び方を避け、Google Testing Blogで紹介されてるTest Sizesによる分類︵small / medium / large︶に従った呼び方でテストを呼んでいる。
この分類方が自分の身の回りに徐々に浸透してきて、実際のチーム内のテスト戦略も一歩進んだ議論ができるようになってきたので、改めてまとめる。
ちなみにこの記事の話は手動で行われるテストではなく、自動テストを対象としているが本質はあまり変わらないと思う。
続き書きました。
akito0107.hatenablog.com
﹁単体テスト﹂﹁結合テスト﹂という呼び方について
ソフトウェア開発に従事していれば必ず聞く言葉だと思う。改めて他のサイトから引用する形で定義をまとめておく。単体テストとは *1
単体テストとは、プログラムを検証する作業の中でも、プログラムを手続きや関数といった個々の機能ごとに分割し、そのそれぞれについて動作検証を行う手法のことである。単体テストでは、個々の機能を果たすためのプログラム部品︵プログラムモジュール︶がそれぞれしっかりと動作しているかを検証する。モジュールのインターフェースや処理手順が正しく動作するか、仕様書の通りに動作しているか、が単体テストによって確認される。単体テストで不備が発見された際には、コーディングの段階に戻ってプログラムの書き直しが行われる。そして再度単体テストが行われ、問題ないことが確認されたら、それらのモジュールどうしを組み合わせた場合にもうまく機能するかどうかを検証する﹁結合テスト﹂の段階に引き渡される。結合テストとは *2
結合テストとは、システム開発におけるプログラムの検証作業の中でも、手続きや関数といった個々の機能を結合させて、うまく連携・動作しているかを確認するテストのことである。 結合テストでは、個々の機能を果たすためのプログラム部品︵プログラムモジュール︶を組み合わせて、データの受け渡しがうまく行われているか、コードの記述様式は揃っているか、データを授受するタイミングはずれていないか、といった点が確認される。結合テストで不備が発見された際には、再度コーディングが行われる。なぜこの呼び方が問題なのか
出典により様々な言い方の違いはあるが、非常に雑に理解すると、﹁単体テスト﹂とは個々のモジュールに対してテストを行い、﹁結合テスト﹂とは個々のモジュールを組み合わせてテストを行うことである。 問題は、﹁個々のモジュール﹂や﹁モジュールを組み合わせて﹂といった解釈が人・チーム・組織によりバラバラで、テストのことを議論する際、いまいち何を指しているのかわからないということである。 例えば、自分の身の回りではJUnitで回すテストのことを単体テストと呼ぶ人もいたし、スマートフォンのアプリ開発ではアプリの1画面が仕様どおりに正しく動作するかどうかを検証する作業のことを単体テストと呼ぶ人もいた。結合テストに関してはさらに解釈の幅が様々で、外部システムとの連携の動作チェックを結合テストと呼ぶ人もいれば、APIのレスポンスが正しく仕様どおりに返ってきているかをテストするJUnitのコードなどを指す人もいる。これらの解釈が間違っているということではないが、 明らかに定義がぶれているし矛盾しているものも多くある。 おそらくプロジェクト管理としてのテスト工程の話が中途半端に混ざった結果、よくわからないことになっているような気がするが、いずれにせよ、上記の定義は主観的だし、最終的には宗教に近いものになってしまっているのが現状だと思う。 ちなみに、﹁単体テスト﹂、﹁結合テスト﹂だけに言及しているが、定義が定まりきらない全てのソフトウェアテストの用語に当てはまり、例えば﹁E2Eテスト﹂という呼び方にも同様の問題があるとおもう。Test Sizesによる分類
Google Testing Blog *3の記事にソフトウェアテストの分類について紹介されていた。 Googleにおいてどのようにtestが分類されているかの話で︵2010年の記事なのでもしかしたら現在は異なっているかもしれないが︶、主観的な観点を廃し、計測可能な指標で分類している。Test Sizes
分類の指標は以下の通り。Feature | Small | Medium | Large |
---|---|---|---|
Network access | No | localhost only | Yes |
Database | No | Yes | Yes |
File system access | No | Yes | Yes |
Use external systems | No | Discouraged | Yes |
Multiple threads | No | Yes | Yes |
Sleep statements | No | Yes | Yes |
System properties | No | Yes | Yes |
Time limit (seconds) | 60 | 300 | 900+ |
表を見れば一目瞭然だが、
Small
はI/Oなどは全てモックやStub化し、 Medium
はlocalhostへのアクセス、 Large
は本番に近い環境を用意して行うものというイメージである。
例えばRailsだと、DBにアクセスするテストが基本は多くなると思う。そういうテストは Medium
に分類される。逆に、DBアクセスはmock/stub化しているようなテストは Small
に分類される。また、 puppeteer
などで実際に画面操作を行うようなテストは Large
に分類される。Testとは呼べないかもしれないが、 Lint
もこの分類に合わせると Smal
l
に分類されると思う。
twadaさんの有名なプレゼン 組織にテストを書く文化を根付かせる戦略と戦術 *4 にもこのことは紹介されている︵57p-58p︶。この中では﹁自分たちでSMLを定義し、調整する﹂と述べられているが、僕たちのチームではもとのブログそのままの定義で使うようにしている。次回の記事でこの実例については紹介したい。