テスト
======

テストはソフトウェア開発の重要な部分です。
気付いているか否かにかかわらず、私たちは継続的にテストをしています。
例えば、PHP でクラスを書くとき、私たちはステップごとにデバッグしたり、または単純に `echo` 文や `die` 文を使ったりして、実装が最初の計画通りに動作することを検証します。
ウェブ・アプリケーションの場合は、何らかのテスト・データをフォームに入力して、ページが期待通りにユーザと相互作用をすることを確認します。

テストを実行するプロセスを自動化して、何かを検証する必要があるときは、いつでも、
それを代行してくれるコードを呼び出すだけでよいようにすることが出来ます。
結果が計画したものと合致することを検証するコードが *テスト* と呼ばれ、それを作成して更に実行するプロセスが *テスト自動化* として知られています。
このテストの章の主題は、このテストの自動化です。


## テストとともに開発する

テスト駆動開発 (TDD) とビヘイビア駆動開発 (BDD) のソフトウェア開発手法においては、実際のコードを書く前に、
コードの断片または全体の機能の振る舞いを一連のシナリオまたはテストとして記述します。
そして、その後で初めて、テストに合格するように実装を作成して、
意図された振る舞いが達成されていることを検証します。

一つの機能を開発するプロセスは以下のようになります。

- 実装されるべき機能を記述するテストを作成する。
- 新しいテストを走らせて、失敗することを確認する。まだ実装がないので、これは予期された結果です。
- 新しいテストに合格するための単純なコードを書く。
- 全てのテストを走らせて、全てが合格することを確認する。
- コードを改良して、それでも全てのテストが OK であることを確認する。

完了すれば、別の機能または改良のために、このプロセスを再び繰り返します。
既存の機能が変更される場合は、テストも変更されなければなりません。

> Tip: 多数の小さくて単純なイテレーションを繰り返すために時間を取られていると感じる場合は、テスト・シナリオのカバー範囲を広くして、テストを再度実行するまでの作業量を増やしてみてください。
> デバッグばかりやっている場合は、逆に範囲を狭めてみてください。

全ての実装作業の前にテストを作成する理由は、そうすれば、その後で、
達成したい事柄に集中して「どのようにするか」に没頭することが出来るからです。
通常、そのようにすることは、良い抽象化、機能修正時の容易なテスト保守、また、結合度の低いコンポーネントにつながります。

ですから、このような手法の長所を要約すると次のようになります。

- 一時に一つの事柄に集中できるため、計画と実装がより良いものになる。
- より多くの機能をより詳細にテストでカバーできる。つまり、テストが OK なら何も問題がないと期待できる。

通常は、長い期間で見れば、かなり時間を節約する効果があります。

## いつ、どうやって、テストするか

上記で説明したテスト・ファーストの手法は長期間にわたる比較的複雑なプロジェクトには合理的なものですが、簡単なプロジェクトでは、やりすぎとなるおそれもあります。
この手法が適切であることを示す指標がいくつかあります。

- プロジェクトは既に大きくて複雑である。
- プロジェクトの要求仕様が複雑になってきている。プロジェクトが継続的に大きくなっている。
- プロジェクトが長期にわたる予定である。
- 失敗のコストが高すぎる。

既存の実装の振る舞いをカバーするテストを作成することは、何も悪いことではありません。

- プロジェクトはレガシーなものであるが、段階的に刷新される予定である。
- 従事すべきプロジェクトを得たが、それにはテストがなかった。

どんな形式の自動化テストもやりすぎになる、という場合もあるでしょう。

- プロジェクトは単純で、この先も、複雑になる心配はない。
- これ以上かかわることはない一度限りのプロジェクトである。

ただ、このような場合であっても、時間に余裕があれば、テストを自動化することは良いことです。

## 参考

- Test Driven Development: By Example / Kent Beck. ISBN: 0321146530.
