テストをテストするには

プログラムを変更する際、その変更によって、正常だった機能が壊れることがあります。それを発見するために、テストと呼ばれる、別のプログラムを書きます。もし、プログラムが壊れても、テストがそれを発見できない場合、そのテストは機能していないことになります。

しかし、テストがきちんと動作しているかどうかを確認するには、どうすればよいのでしょうか。テストのテストを書けば、今度は、テストのテストのテストが必要になります。そんな問題を解決してくれるのが、テスト駆動開発(英:test-driven development; TDD)です。

以下が、TDDの大まかな流れです。

  1. 機能を実装する前に、その機能をテストするコードを書く。
    • まだ機能を実装していないため、テストは失敗するはずです。この時点でテストが成功するようなら、テストが正常に動作していないことになります。
    • 「失敗」には、コンパイルの失敗も含みます。つまり、まだ存在しないクラスやメソッドを使用しても構いません。
  2. テストを成功させる、必要最低限のコードを書く。
    • それ以上のコードを書く必要がある場合は、そのコードに対する、新しいテストを書きます。
  3. 書いたコードをきれいにする。

この流れに沿うことによって、テスト自体の利点に追加して、以下の利点も得られます。

  • 機能を実装することでのみ、テストが成功するため、その機能が壊れたときは、テストも失敗することを保証できる。つまり、テストのテストを行うことができる。
  • 機能を実装する前に、必ずテストを書くため、全ての機能がテストされることを保証できる。
  • どのようにテストを書くか、という観点から開発を始めるため、テストをしやすいコードが生産される。
  • テストを成功させる、必要最低限のコードしか書かないため、無駄なく最短距離で機能を実装することができる。
  • テストに信頼がおけるため、プログラムを壊す心配をせずに、コードをきれいに保つことができる。

TDDは、ソフトウェアの特徴を活かした開発方法です。

ハードウェアで同じことをすると、「石橋を叩きながら建設する」という状況になります。建設前から石橋を叩き続け、石橋が壊れなくなったら、石橋の完成とする、という開発方法です。ハードウェアをこのような方法で開発しようとすると、石橋を叩き壊され続けるため、いつまでたっても石橋は完成しません。テストは、石橋が完成してからするしかないのです。

ソフトウェアでは、テストで叩いたからといって、コードが壊されるわけではありません。コードを変更して、新しいプログラムを建設し、もう一度テストする、という作業も簡単にできます。そのため、いくら叩いても、着実に完成に近づけます。

ソフトウェア開発では、テストをテストするために、実装より先に、失敗するテストをかきます。これを、テスト駆動開発(TDD)と言います。TDDによって、テストのテストを行い、全ての機能をテストし、テストをしやすいコードが形成され、最短距離で機能を実装し、コードをきれいに保つことができます。

Shogo Wada

楽しさと実用性の両立が好き。プログラマー。