重要なのは、最初にすべてのテストを作成してからコードを作成することで、TDD を実行しようとしているということです。
問題は、「最初にすべてのテストを作成する」ことは、「いくつかの TDD を実行する」ことではないということです。テスト駆動開発は、「赤-緑-リファクタリング」サイクルの小さな繰り返しで構成されます。
- 単体テストをテスト スイートに追加して実行し、失敗することを確認します (赤)
- テスト対象のシステムに、すべてのテストに合格するのに十分なコードを追加します (緑)。
- すべてのテストをパスしたまま (リファクタリング) しながら、テスト対象のシステムの設計を改善します (通常は重複を削除します)。
事前に巨大なテスト スイート全体をコーディングすると、"グリーン" (すべてのテストがパスする) 状態に到達するために永遠に費やすことになります。
ただし、オブジェクトまたはメソッドが存在しないため、アプリはコンパイルされません。
これは、コンパイルされた言語の典型です。それ自体は TDD の問題ではありません。つまり、新しいテストが失敗するのを見るには、コンパイラを満足させるために現在取り組んでいる機能の最小限のスタブを作成する必要があるかもしれません。
たとえば、次のテストを (NUnit を使用して) 記述します。
[Test]
public void DefaultGreetingIsHelloWorld()
{
WorldGreeter target = new WorldGreeter();
string expected = "Hello, world!";
string actual = target.Greet();
Assert.AreEqual(expected, actual);
}
そして、アプリをコンパイルしてテストを失敗させるには、次のような多くのコードを記述する必要があります。
public class WorldGreeter
{
public string Greet()
{
return String.Empty;
}
}
ビルドするソリューションを取得し、1 つの失敗したテストを確認したら、最初のテストに合格するコードを追加できます。
public string Greet()
{
return "Hello, world!";
}
すべてのテストに合格したら、テスト対象のシステムを調べて、設計を改善するために何ができるかを確認できます。ただし、リファクタリングをいじる前に、「赤」と「緑」の両方の手順を実行することが、TDD 規律にとって不可欠です。
要点は、テストを開発するにつれて、重複などを確認できるようになり、コードを 1 行書く前にリファクタリングできるようになるということだと思いました。
Martin Fowler は、リファクタリングを「既存のコード本体を再構築し、外部の動作を変更せずに内部構造を変更するための訓練された手法」と定義しています(強調を追加)。コードを 1 行も書いていなければ、リファクタリングする必要はありません。
問題は、これを行う方法はありますか、それとも間違っていますか?
あなたがTDDをやろうとしているなら、そうです、私はあなたがこれを間違っているのではないかと心配しています. あなたがやっていることを実行する素晴らしいコードを提供できるかもしれませんが、それは TDD ではありません。それが問題かどうかは、あなたが自分で決めることです。