「テスト駆動開発」の版間の差分

削除された内容 追加された内容
Verba (会話 | 投稿記録)
編集の要約なし
タグ: モバイル編集 モバイルウェブ編集
Verba (会話 | 投稿記録)
編集の要約なし
タグ: モバイル編集 モバイルウェブ編集
5行目:
最も基本となる開発サイクルは以下のようになる。
*失敗するテストを書く
*できる限り早く、テストがパスすに通るような最小限のコード本体を書く
*コードの重複を除去する([[リファクタリング (プログラミング)|リファクタリング]])
テストの実行環境ツールである[[xUnit]]では、テストの失敗を赤いバー、成功を緑のバーで通知するため、上記のサイクルは Red/Green/Refactor と称される。
 
なお、テストの実行環境ツールである[[xUnit]]では、テストの失敗を赤いバー、成功を緑のバーで通知するため、上記のサイクルは Red/Green/Refactor と称される。
より実践的には、to-doリストの利用を組み合わせた以下の手順で開発を行う。
 
*まず、現時点で分かっている範囲でテストの必要性がある項目をリストとして列挙する。このリストは、テストの必要性がわかった時点で適宜項目を追加していく。
より実践的には、to-doリストの利用を組み合わせることにより、以下のような手順で開発を行うする
*このリストから1つ選ぶ。これは、実装できそうでかつ重要なものを選ぶ(テスト自体の記述が容易でも、Fake It(後述)でしかコード本体を記述できなさそうなものは後回しにする)。実装できそうなものがない場合は、列挙した項目の粒度が大きすぎることを意味する。その場合、それを実装するための前提となるような、より小さい粒度の項目を作成し、それをリストに加える。
 
*選択した項目についてテストを記述する。このテストは、現在の実装を用いると失敗するようなものを選ぶ。
*まず、現時点で分かっている範囲でテストする必要がある項目をリストとして列挙する。なお、このリストは、テストの必要性がわかった時点で適宜項目を追加していく。
*コンパイルに必要な最小限のコード(例えば、まだ存在しないクラス・メソッドを利用するテストを書いたなら、そのクラス・メソッドの宣言)の追加後、実際にテストを実行し失敗することを確認する。期せずしてテストがパスした場合は、意図しないことが起こっていることに注意する。テストが失敗するまでは、コード本体は触らない。
*このリストから1つ選ぶ。これは、実装できそうでかつ重要なものを選ぶ(テスト自体の記述が容易でも、Fake It(後述)でしかコード本体を記述できなさそうなものは後回しにする)。実装できそうなものがない場合は、列挙した項目の粒度が大きすぎることを意味する。その場合ため、そのテストを実装するための前提となるような、より小さい粒度の項目を作成し、それをリストに加える。
*できる限り早くテストの失敗を解消するようにコード本体を記述する。この段階では、テストをパスさせるためにどんなことをしても良い(定数を返す、コピー&ペースト、コードの重複等)。具体的には3つの方法が挙げられる。
*選択した項目についてテストを記述作成する。このテストは、現在の実装を用いると失敗するようなものを選ぶに記述する
*コンパイルに必要な最小限のコード(例えば、まだ存在しないクラス・メソッドを利用するテストを書い作成しなら場合であれば、そのクラス・メソッドの宣言)追加した後、実際にテストを実行し失敗することを確認する。期せずしてテストがパスしに通った場合は、意図しないことが起こっていることに注意する。し、テストが失敗するまでは、コード本体は触らを変更しない。
*できる限り早くテストの失敗を解消すに通るようにコード本体を記述する。この段階では、テストをパスさせるためにどんなことをしても良い(定数を返す、コピー&ペースト、コードの重複等)。具体的には、次の3つの方法が挙げられる。
 
**実装が自明な場合(1分程度で書ける場合)はそれを記述する(Obvious Implementation)。
**テストに要求される値そのものをハードコーディングする(Fake It;仮実装)。
**Fake Itの後に次の段階(リファクタリングの段階へ進めないような漠然としている場合は、さらに別のデータを用いたテストを追加し、その2つのテストの共通点を見出して助けとする(Triangulate;[[三角測量]])。
 
*テストが通ることを確保しつつ、コードそれ自体やコードとテストの間にある明示的・暗黙的な重複を取り除く(リファクタリング)。通常、リファクタリングとは、コードの意味を変えずにコードを再構築することをいう。なお、この「コードの意味」とは、テストが通ることを言う。また、リファクタリングここで取り除く重複は、形式的なもの重複だけでなく、意味的なもの重複も含まれる。例えば、Fake Itでハードコーディングしたものは、おおよそ実際にはどこからか得られるはずのパラメータを、別の値を用いて算出したものであるため、これを重複と見なす。そして、重複を取り除くことで、ロジックが抽出される。
*実装した項目をリストから削除する。このとき、作業中にテストする必要性があるとわかった項目に、実質的に振り変わるかもしれない。
 
テストコードは、最初から自明であるとは限らない。むしろ、コード本体と同様、最初は具象的なテスト(例えば、単なるフラグの確認)を行い、これによって知見を得た後にテストを書き直したほうがよい。また、テストコードから導かれるコード本体は、リファクタリングの過程によって、あるいはテストが成熟するに従って、最終的な目的とするコード本体のテスト用スタブに変わっていくかもしれない。早い段階でテストとコード本体を分離して管理するのはあまり意味がない。テストやコード本体が成熟していくにつれ、テストの記述が抽象的・間接的になり、リスクが導入される(例えば、フィールドを直接参照する代わりにgetterメソッドを使うなど)。しかし、テスト駆動開発のテストの目的は、開発者の正しさへの確信を裏づけするためであり、それが保たれているならば問題はない。
 
テスト駆動開発で用いられるテストは、品質のためのテストではない。したがって、コード本体とは独立してあらゆるケースを網羅するテスト、すなわち「テストそのものが価値を持つようなテスト」を目指しているわけではない。テスト駆動開発におけるテストとは、コード本体とテストを合わせて検討することで、開発者がその正しさに確信を得るようなものである。したがって、開発者の確信に少しも寄与しないテスト(また、ドキュメントとしてテストの読者に何かを伝えるために書かれていないもの)は、むしろ積極的に削除を検討する。