web-dev-qa-db-ja.com

テスト駆動開発で、複数の失敗したテストを記述せずに、それらをパスさせる正当な理由はありますか?

ボブおじさんのテスト駆動開発の3つのルール 次のように述べます。

  1. 単体テストに合格しない場合を除いて、製品コードを記述することはできません。
  2. 失敗するのに十分以上のユニットテストを書くことは許可されていません。コンパイルの失敗は失敗です。
  3. 失敗した1つの単体テストに合格するのに十分な数を超える量の製品コードを記述することはできません。

一部の人々は、2番目のルールは、失敗したテストを1つだけ追加する必要があることを意味すると主張しています(孤立した動作の例)。しかし、失敗するとすぐに個別の各テストの作業を停止する限り、テストスイートに複数の失敗したテストを追加できることを意味する可能性があると主張する人もいます。

私はあなたが自分自身を制限して単一の新しい失敗したテストを1つだけ書くことにどのような利点があるかを知り、それがパスするまでテストコードの記述を停止します。

7
aef

2つのテストを一度に記述し、最初のテストに合格するようにコードを実装し始めると、2番目のテストが失敗するため、テストスイート全体を実行して「グリーン」な結果を得ることができません。もちろん、単体テストフレームワークの詳細な出力を見て、予想どおりにテストが失敗したことを視覚的に確認できますが、特にユニットテストの数が増加し始めたときに、面倒でエラーが発生しやすくなる可能性があります。 。そして、たとえば、失敗したテストは壊れたビルドとしてカウントされるため、失敗したテストをチェックインする必要がないというルールがインストールされたCIシステムのようなものがある場合、これは、作成するのに十分なコードを実装するまでコードをチェックインできないことを意味しますすべてのテストに合格。

これは理想的なモデルであることに注意してください。数分ごとにコンパイル可能で完全にテストされたプログラムを提供し、可能な限り最小のステップで作業できるようにトレーニングするために作成されています。アイデアは、ステップが1つの「完全に機能する状態」から別のステップへと小さいほど、プロセスをよりよく制御できるということです。

もちろん、「実際のプログラミング」を行う場合、必要に応じて、テストと本番用コードの実装順序を自由に選択できます。大きなステップがニーズに適していると考えられる場合に適しています。それでも、この方法で作業する場合は、プロダクションコードの関連部分の作業を開始するまで、事前に作成したテストを明示的に無効にするかコメントアウトすることをお勧めします。

10
Doc Brown

一度に1つの失敗する単体テストに留まる理由は、フォーカスです。単一の失敗した単体テストがあると、何に取り組むべきかが正確にわかります。コードのどの部分について考えるかを知っている。あなたはすぐにあなたがどんな問題を解決しているのか知っています。 1つの問題の解決に取り組むときに、より多くのテストを作成できるようにすると、すぐに2つ(5つまたは10つ)の問題を解決することになり、その集中力の欠如では、実際には何も解決しません。

どうしても、テストがまだ失敗している場合でも、テストの追加の必要性を発見したら、それを書き留めてください。テストに合格した後、メモを確認し、まだ心の中で新鮮なうちに作業するものを1つ選びます。しかし、その失敗する追加テストを時期尚早に書くと、すべてのグリーンからさらに離れて、その状態から遠く離れたくない。

また、追加のテストの必要性を感じた場合は、その感じを参考にして、まず小さなテストを記述してください。

これはTDDの基本的な教義です。実際には、私たちの多くは時々それに違反し、その2番目に失敗したテストを書きます。しかし、私たちが最善を尽くしているとき、それは一度に1つの失敗したテストに過ぎず、フォーカスが理由です。

7
Carl Manaster

独自のプロジェクトを実行して、好きなだけ多くのテストを書くことができますが、実際のビジネスでの私の経験では、テストまたはリファクタリングは非機能的な要件であり、お客様は必要な時間だけ料金を支払う必要がありますテストを書きます。テストはプロジェクトのすべての問題に固有の部分ですが、やりすぎてはなりません。

1つの優れた統合テストと比較して、ソフトウェアの品質を保証する単体テストの数についても同じことが言えますか?モデルクラスをテストするアンクルボブの言葉について考えてみましょう。

  • (テスト)「メッセージを返す必要があります」:model = new NewsModel()
  • (テスト失敗)NewsModelは未定義
  • (インプリフィックステスト)_class NewsModel {}_
  • (テスト)model.getMessage()
  • (テスト失敗)_NewsModel::getMessage_は未定義
  • (インプリフィックステスト)public getMessage() {}
  • ...

1つの優れた統合テストでは誤動作が明らかになるはずであり、そのようにモデルテストを作成するのはボブおじさんの意図ではないので、私はその厳密な赤/緑/リファクタリングに同意しません。メッセージは、何時間ものテストで迷子になってはいけないというだけのことですが、優れたテストを作成し、少なくとも動作を二重にテストしないでください。

顧客のあらゆる要件をテストにまとめることができれば、実装がテストに合格すれば、優れたソフトウェアを出荷することになります。バグと同じこと:再現するテストを1つ記述し(赤)、修正して(緑)、少なくともリファクタリングします。

そして再びあなたの質問に戻ります:1つのテストのみが失敗した場合、他のすべてのコンポーネントが正しく動作していることを確認しながら、その誤動作を分離します。それを修正しようとしていて、2つのテストが失敗した場合、間違った方向に進んだ可能性があります。

0
Aitch