読んだ本
Amazon.co.jp: 単体テストの考え方/使い方 eBook : Vladimir Khorikov, 須田智之: 本
第2章 単体テストとは何か
この章で扱うこと
- 単体テストとは何か?
- 共有依存、プライベート依存、揮発性依存の違い
- 単体テストにおける2つの学派である古典学派とロンドン学派について
- 単体テスト、統合テスト、E2Eテストの違い
単体テストをどのように行うかという点について2つのが異なる学派が存在する。それは古典学派とロンドン学派と呼ばれている。
2.1 単体テストの定義
自動化されていて次の3つの性質をすべて備えるものが単体テストとなる。
- 単体(unit)と呼ばれる少量のコードを検証する
- 実行時間が短い
- 隔離された状態で実行される
3つ目の隔離に対する考え方が違いが原因で2つの学派に分かれている。
ロンドン学派はテスト対象システムから協力者オブジェクトを隔離するときは
テスト対象となるクラスが他のクラスに依存しているならその依存をすべてテスト・ダブルに書き換えなくてはならないという考えである。
テスト・ダブルを使うことの利点は、テストが失敗したときに、コードベースのどこで問題が起こったのかを明確にできることである。
使わない場合、テスト対象システムの依存をすべて準備しなくてはいけなくなる。
テスト対象システムを依存から隔離することで得られる小さな喜ばしい副次的な効果として1つのテストケースは1つのクラスしか検証しない、という指針をプロジェクト全体に普及させられるため、テスト・スイート全体がシンプルな構造になる
別の章でモックとスタブ、そしてそれらの違いについてみていく。現段階ではモックはテスト・ダブルの一種であることさえ知っていれば良い。
テスト・ダブルとモックは同じ意味で使っている開発者が多いが厳密にいえば異なるもの。
- テスト・ダブル⇒テストで使わるすべての種類の依存の偽りの依存の事であり、プロダクトで使われることはない
- モックはこのような偽りの依存の1種でしかない
古典学派では単体テストにおいて隔離する必要があるのはコードではなくテスト・ケースであり、各テスト・ケースをお互いに影響を与えることなく個別に実行できるようにしなくてはならい。
状態が共有されている場合他のテストケースに影響が出るようになってしまう。
このような共有される状態となるものにはデータベースやファイルシステムなどがあり、そのような依存のことを本書ではプロセス外依存と呼ぶ。
古典学派における単体テストの隔離とは、テスト対象となるクラスを共有依存から隔離することを意味する。
ここで注意してほしいのは共有依存とは単体テストのテスト・ケース間で共有される依存の事であり、テスト対象となるクラス間での共有ではないということ。
共有依存をテスト・ダブルに置き換えるもう1つの理由は、テストの実行速度を上げるため。
2.2 古典学派およびロンドン学派が考える単体テスト
古典学派とロンドン学派で隔離に対する違いがあることがわかった。
その考えの違いとはロンドン学派は、単体テストにおいてテスト対象システムをその協力者オブジェクトから隔離しなくてはならない、と考えているのに対し、古典学派は、単体テストのテスト・ケースを別のテスト・ケースから隔離しなくてはならない、と考えいているかことでした。
2つの学派は大きく分けて3つの視点において違いがある。
隔離対象 | 単体の意味 | テスト・ダブルの置き換え対象 | |
---|---|---|---|
ロンドン学派 | 単体 | 1つのクラス | 不変依存を除くすべての依存 |
古典学派 | テスト・ケース | 1つのクラス、もしくは、同じ目的を達成するためのクラスの1グループ | 共有依存 |
ロンドン学派はテスト・ダブルをほぼすべての依存に対して使うことが推奨しているが、依存の種類によってはテスト・ダブルに置き換えずにそのまま使うことを許す。もし依存が不偏であればその依存はテスト・ダブルに置き換える必要はない。
すべてのプロセス外依存が共有依存になるわけではない。
2.3 単体テストにおける古典学派とロンドン学派の違い
筆者としては古典学派のスタイルのほうが好んで使用している。古典学派のほうがより良質な単体テストを作成でき、単体テストの究極的な目標である、プロジェクトの持続的な成長を促すということを達成するのに向いているから。
ここでいうコードの粒度を細かくしようとするということは単体テストにおいてあまり有力ではない。
単体テストにおいて、各テスト・ケースがすべきことはそのテストに関わる人たちにテスト対象のコードが解決しようとしている物語を伝えることである。
協力オブジェクトをモックに置き換えるということは複数層に依存関係を築いている場合にテスト対象の複雑な依存関係を断ち切ることができるから。
古典学派のスタイルで書く場合はテスト対象となるシステムが呼び出している依存に不具合がある場合もテストが失敗になる。しかしこれは大きな問題ではない。単体テストを頻繁に行っていれば最後に修正しを施した箇所にテストを失敗させた原因があることになるため、どこでバグが発生したかをすぐに見つけ出せるから。
もし1つの問題が1つのテスト・ケースだけではなく多くのテストケースに影響を与えるのであれば、その問題のあったコードは多くのクラスに依存されるような重要な価値があることの証明になるからだ。
2.4 古典学派とロンドン学派における統合テスト
古典学派とロンドン学派では統合テストの定義も異なる。
ロンドン学派⇒実際の協力者オブジェクトを使って行うテストをすべて統合テストとみなす。
古典学派の観点で単体テストの定義を再定義すると以下のようになる。
- 1単位のふるまいを検証する
- 実行時間が短いこと
- 他のテストケースから隔離された状態で実行される
統合テストとは簡単に言えば
共有依存やプロセス外依存、さらには同じ組織の異なるチームによって開発されたコードが統合された状態で想定通りに機能することを検証するテストのことである。この統合テストに加えてE2Eテストという別の意味を持つテストも存在する。このE2Eテストは1種の統合テストとしてみることができ、統合テストと同じように対象のコードがプロセス外依存とともにどのように機能するのかを検証する。
E2EテストはUIテスト、GUIテスト、機能テストなどと呼ばれることもある。
E2Eテストは保守の観点において非常にコストがかかるテストであるため、E2Eテストを実施するのはすべての単体テストとすべての統合テストが成功するようになった後で行うようにする。