私はジュニアソフトウェア開発者であり、自分自身をより良くするために業界の慣行のいくつかを研究しています。私は単体テストを簡単に見てきましたが、大量の単体テストを作成する余分な時間によってコードがどのように改善されるかわかりません。
物事を見通しに入れるには:
私が最も得ていないのは、単体テストで価格計算関数(曜日や祝日などに依存する可能性があるため、その関数に20〜40行を想定)があるかどうかをどのように判断できるかです。正しい?すべてのコードを記述し、デバッグセッションに参加して、最終的にすべてのコードをテストする方が早いのではないでしょうか。
フォームベースの例をいただければ幸いです(MSDNビデオから見た例はすべてMVCであり、時間の無駄ですIMHO)。
私が最も得られないのは、ユニットテストで価格計算関数(曜日や祝日などに依存する可能性があるため、その関数を20〜40行と想定できる)かどうかをどのように判断できるかです。正しい?すべてのコードを記述し、最終的にすべてのコードをテストするためにデバッグセッションを開始する方が速くはありませんか?
これを例にしましょう。座ってその(それを呼びましょう)30行のメソッドを作成する場合は、すべての可能性を考え、メソッドに書き込み、デバッグして、すべての可能性を考慮に入れようとします。曜日をチェックして銀行休業日に行き、バグを見つけた場合は、メソッドを変更する必要があります。これで、正しく機能するように簡単に変更できます。銀行休業日ではありますが、週末ではありません-すでに週末をチェックして機能しているため、再テストを忘れる可能性があります。これは、バグがアプローチによって製品に忍び寄るシナリオの1つにすぎません。
もう1つの問題は、過度の注意を払わなければ、実際には発生しない条件のコードを簡単に追加できることです。不要なコードはプロジェクトに複雑さを加え、複雑さはデバッグやその他のメンテナンスタスクを困難にします。
TDDはこれらの問題からどのようにあなたを保護しますか?まず、最も単純なケースと、それを渡す最も単純なコードを記述します。デフォルトの価格が7ドルだとします。便利なので、このJava風に書きますが、このアプローチはどの言語でも機能します。
_public void testDefaultPrice() throws Exception {
assertEquals(7, subject.getPrice());
}
public int getPrice() {
return 7;
}
_
簡単ですよね?不完全ですが、私たちが行った限りでは正しいです。
ここで、週末の価格は9ドルである必要があると言います。しかし、そこに着く前に、週末を構成する日を知る必要があります。
_public void testWeekend() throws Exception {
assertTrue(Schedule.isWeekend(Weekday.Sunday));
}
public boolean isWeekend(Weekday.Day day) {
return true;
}
_
これまでのところとても良い-そしてまだ非常に不完全です。
_public void testWeekend() throws Exception {
assertTrue(Schedule.isWeekend(Weekday.Sunday));
assertTrue(Schedule.isWeekend(Weekday.Saturday));
assertFalse(Schedule.isWeekend(Weekday.Monday));
}
public boolean isWeekend(Weekday.Day day) {
return day == Weekday.Sunday || day == Weekday.Saturday;
}
_
メソッドを正確に実行したことを確信するために必要な数のアサーションを追加します。
ここで、元のクラスに戻ります。
_public void testDefaultPrice() throws Exception {
assertEquals(7, subject.getPrice());
}
public void testWeekendPrice() throws Exception {
subject.setWeekday(Weekday.Sunday);
assertEquals(9, subject.getPrice());
}
public int getPrice() {
if (Schedule.isWeekend(day))
return 9;
return 7;
}
_
そして、それは行きます。また、ここでコードのdesignをテストドライブしている方法と、そのおかげでどれだけ優れているかに注意してください。あなたのアプローチでは、ほとんどのプログラマーは週末のテストコードをgetPrice()
の本体に組み込んでいたでしょうが、それは間違った場所です。多くのコードは、1日が週末かどうかを知りたい場合があります。このようにして、十分にテストされた単一の場所にそれを置くことができます。これにより、再利用が促進され、保守性が向上します。
「デバッグセッションに参加して、最終的にすべてのコードをテストしますか?」 かもしれないもっと速く...
初めて。
戻って何かを変更する必要がある場合は、別のセッションを行う必要があります。それから2週間後、彼らは他の何かを変更したいと考えており、別のセッションを行う必要があります。
最初の変更後、場合によっては最初の開発の直後でも、累積テスト時間は、初期の単体テストを記述し、その特定の変更のすべての変更でそれらを拡張するのにかかった時間をはるかに超えています。ユニットテストは、複雑な(複雑ではない!)コードを変更する自信を与え、現在の機能をどれも壊していないことを知ることができます。
私見では、特にあなただけがあなたのプロジェクトに取り組んでいるので、あなたの立場でのユニットテストの価値を評価することは本当に難しいです。
テストの利点とテクニックの詳細については、本を試してみます。
あなたが尋ねたのは良いことです:)では、なぜTDDなのですか?次の質問に答えて、TDDの理由を理解できるかどうか試してみてください。
この時までに、私はあなたが写真を手に入れることを望みます。そうでない場合は、次のようになります。テストコードは、特定のロジックが配置されている理由を見つけるために、すぐに参照できる補足として機能します。これはあなたの生産性を助け、時間のかかる骨の折れるデバッグセッションよりも楽しい経験になります。
これらすべてとは別に、TDDを実践する理由は次のとおりです。
...私の計算価格関数(曜日や銀行休業日などに依存する可能性があるため、その関数には20〜40行を想定します)
コードの不安定な性質(価格設定ルールは頻繁に変更される可能性があります-テストも同様です)を考えると、テストを安価にしたいのですが、テストを完全にスキップしないでください。
複数の条件文(if-then-else
)はいつでもtrueになる可能性があります。テストに焦点を当ててくださいルールの組み合わせの予期しない結果。
目的は、プログラムがばかげた答えに到達するのを防ぐことです。各価格設定ルールは単独で判断すると正しい場合がありますが、それらの組み合わせにより、禁止されていた場所で割引を2回適用したり、割引を過充電にしたりするなど、予期しない結果が生じることがあります。
私がそれにアプローチする方法は次のとおりです。