TDDで最初からテスト合格に対処する方法


8

私の個人的なプロジェクトでTDDを実践しようとしています。新しいテストを追加した後、既存の実装に基づいて最初から合格する場合の状況にどのように対処するのでしょうか。

一方では、新しいテストは、設計の追加のドキュメントと、想定外の偶発的な違反からの保護を提供します。

一方、コードを変更せずにテストに合格した場合は、実際に何をテストするかが「疑わしい」ものです。

基本的に、すでに実装された動作を主張するテストの正確さを確認するために何ができるでしょうか?


5
私のお気に入りのアプローチは、突然変異検査で、私はテストが失敗開始するかどうかテストされたコードとチェックを変更
ブヨ

2
@gnat-重複があると思いますが、同じ質問だとは思いません。ここで私はTDDについて具体的に尋ねていますが、「そのような状況で自分自身を見つけている場合、TDDを間違っているのは...」が有効な答えになると信じています。
AGrzes、

5
既存の(そして正しく機能している)実装に対するテストを作成するときにTDDをまだ実行していないため、問題ではありません
gnat

2
「それに遭遇したとき、あなたはどうしますか?」カバレッジツールで新しいテスト(これのみ)を実行し、予想されるパスが実行されることを確認します。ロールバックは、プロジェクトをトレーニングのために行う場合の唯一のオプションです。ところで、Coderetreatグローバルデーは TDDを実践する絶好の機会です...
ティモシー

2
@ Solomonoff'sSecret個人的には、私が見たことのないテストが失敗することはありません。
RubberDuck

回答:


13

書き込んだ瞬間からテストに合格することは、TDDプロセスに問題がある可能性がありますが、それ自体が間違っているという意味ではありません。

あなたのテストは偶然に合格するかもしれません。

ATMを使用して出金の費用を返すメソッドがあるとします。ここで、カードの所有者が60歳以上の場合、コストは0であるという新しいルールを追加するように求められます。したがって、失敗することを想定してテストします。

assertTrue(ATM.withdrawalCost(clientOver60) == 0)

あなたはこれが失敗することを期待するかもしれません。しかし、クライアントはたまたまVIPのクライアントであり、無料で引き出すことができます。これで、withdrawalCostメソッドに戻って変更して失敗させることができますが、それはあまり意味がありません。新しいテストを記述して、コードが間違っていることを示します。

assertTrue(ATM.withdrawalCost(nonVIPclientOver60) == 0)

これで失敗しました。パスするまでコードを実行し、完了するまで繰り返します。

それでは違いはないので、テストを消去する必要がありますか?番号!これは、ATM withdrawalCostメソッドの予想される機能を説明しています。それを消去して、いつの日かVIPクライアントの0の引き出し費用が変わっても、最初のアサートは真のままであるはずです。

そうは言っても、適切なTDDを実現するために、テストの前にコーディングを行って、合格するとわかっているものをテストすることはできません。私はあなたが尋ねているケースをこれとは考えていません。

fail-code-passサイクルは、「テストが何であるかを知っているため、すでにコーディングしてあるので、失敗するこの3つのテストとパスする2つのテストを書く」という開発を回避することを意図していると思います。そうでないと感じる人もいるかもしれません。彼らの理由を聞いてください、それらも有効かもしれません。


10

最初から直接合格するテストは、通常、実際のテストに必要なものよりも一般的な方法で何かを実装したときに発生します。これはごく普通のことです。ユニットテストでは、特定の関数の入力値の数が限られた数しか提供されません。多くの場合、現在のテストケース用に特別に設計された実装は、より一般的なソリューションよりも複雑になります。その場合、テストケースでのみ機能し、それ以外では失敗するようにコードを人工的に設計するのは、煩雑でエラーが発生しやすくなります。

たとえば、特定の配列からいくつかの値の最小値を返す関数が必要だとします。1つまたは2つの値のみを含む配列を使用したテストによって駆動される実装を作成しました。しかし、さまざまな要素(おそらく最初の2つの要素のみ)で比較を行うことによって複雑な方法でこれを実装する代わりに、言語エコシステムの標準ライブラリから配列の最小化関数を呼び出し、実装を1つのライナーにします。 。5つの要素の配列を持つテストを追加することにした場合、テストはおそらく最初から成功します。

しかし、テスト自体のバグのために、テストが「グリーン」でないことをどのようにして知るのですか これに取り組む簡単で簡単な方法は、テスト対象を一時的に変更してテストを失敗させることです。たとえばif (array.size()==5) return 123、関数に意図的に行を追加することができます。これで5要素テストは失敗するので、

  • テストが実行されます
  • テストのAssert呼び出しが実行されます
  • テストのAssert呼び出しは正しいことを検証します

テストにある程度の自信を与えるはずです。テストの失敗を確認したら、変更を元に戻します。テストに再び合格するはずです。

または、テストの予想結果を変更することもできます。たとえば、合格したテストに次のようなアサーションが含まれているとします。

 int result = Subject.UnderTest(...);
 Assert.AreEqual(1,result);

次に、テストを編集して、「1」を「2」に置き換えることができます。テストが(期待どおりに)失敗すると、正常に機能していることがわかり、交換を取り消して、テストが緑色になるかどうかを確認できます。そのような種類の置換によってテストにバグが発生するリスクは非常に小さいため、これはおそらくほとんどの実際のケースでは受け入れられます。

別の、おそらく議論の余地のある方法は、テストにブレークポイントを設定し、デバッガーを使用してそれをステップ実行することです。これにより、テストコードが実際に実行されるという確信が得られ、段階的な検査によってテストのパスを検証できるようになります。ただし、失敗したテストのコードパスのエラーを見落とさないように、細心の注意を払う必要があります。複雑なテストの場合は、両方を実行することを検討してください。テストを人為的に失敗さ、デバッガーを使用して検査することができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.