私のプロジェクトは、単体テストを可能にするほど十分に分離されていると思います。しかし、単体テストを価値のあるものにするために、プロジェクトは、正確に、クラスと機能の面でどれだけ大きくする必要がありますか?
私たちは皆、間違いを犯し、完璧な人はいませんが、小さなプロジェクトのエラーをステップスルーで処理するための自分はまともなプログラマだと思います。または、プロジェクトのサイズに関係なく、単体テストは非常に必要ですか?
私のプロジェクトは、単体テストを可能にするほど十分に分離されていると思います。しかし、単体テストを価値のあるものにするために、プロジェクトは、正確に、クラスと機能の面でどれだけ大きくする必要がありますか?
私たちは皆、間違いを犯し、完璧な人はいませんが、小さなプロジェクトのエラーをステップスルーで処理するための自分はまともなプログラマだと思います。または、プロジェクトのサイズに関係なく、単体テストは非常に必要ですか?
回答:
私の経験では、単体テストの必要性を検討するには、1つのクラスと1つの関数で十分でした。
class Simple {
boolean reallySimple() {
return true; // how do we make sure it doesn't change to false?
}
}
class SimpleTest {
void assertReallySimple() {
// ensure reallySimple return value isn't changed unexpectedly
UnitTestFramework.assertTrue(new Simple().reallySimple());
}
}
「すべてを単体テストする必要があります」というアイデアを購入したことはありませんが、確かにそこにいる人はいます(gnatの答えを参照してください!)。
私に関する限り、単体テストの主な利点は次のとおりです。
基本的に、これらの要因に対するテストを作成および維持するのにかかる時間を検討する必要があります。
テスト1を書く価値があるようにするには、通常1で十分です。私の経験では、コードの95%以上が遅かれ早かれ変更されます。
簡単です。一度実行した後にプログラムを破棄する場合、単体テストは必要ありません。
これが過度に思える場合は、代替案の意味を検討してください。単体テストで支払うことができないサイズがある場合、「まだ魔法のサイズに達しているのか、テストを書き始めるべきなのか」と判断し続ける必要があります。現在、プログラマは未来を予測することで悪名が高く、自分のスキルを判断することで悪名が高い。あなたにとって非常に明瞭に見えるコードは、たとえあなたにとっても、1か月も待たなければ理解できなくなります。あなたは絶対にしているプロジェクトは、積極的に特定が再び使用されることはありません、あなたは単にあなたが前に、何か解決方法をルックアップする場合がありますリモート機会に周り続けることだろう再度要求することを、変更要求を受信します。
したがって、テストが役立つかどうかを誤判断する可能性が非常に高く、テストが必要になった時点で、テストする正確なセマンティクスが実際に何であるかはすでに100%確実ではありません。些細な一回限りのプログラムを除くすべてが単体テストから利益を得ると信じているため、二度と実行されないテストに費やす労力のコストは、テストされておらず理解されていないコードを拡張するリスクに対して無視できると考えています。
しばらく前、私は素晴らしい記事を見つけました:ユニットテストが開発を高速化する理由。質問に答えるのに役立ちます。
...コードベース...に相当な単体テストが提供された場合 「すべてのテストが成功した場合、コードが実行すべきことを保証します」と言うセットであり、テストが失敗した場合、動作がどこで壊れているかを正確に示します。これは素晴らしいことです。コードがまだすべきことを実行しているなら、迷わずに必要なものを追加するようにコードを変更できます。これはソフトウェアエンジニアとしての素晴らしい世界です。もっと速く進むことができることに気づいた...
私には「信仰」があります。
これはおそらく、単体テストがエンタープライズコンテキストでの開発を高速化する最も重要な理由です。
すべてのテストに合格すれば、すべてが正常に機能することを信頼できます。テストが失敗した場合、問題が発生した場所を正確に指摘します...
... 高いユニットテストカバレッジと優れたユニットテストが必要です。これらの条件が順守されると、新しい機能を追加するための努力がアプリケーションのサイズにほとんど依存せず、長期的には開発がスピードアップするという状況に陥ります。
Michael Feathersは、彼の著書の1つで、コードの変更を扱う2つの方法を紹介しました。
コードベースの大きさは関係ありません。
Kent BeckによるStack Overflowの質問への回答によると、ユニットテストはどのくらい深くなっていますか?、間違っている傾向があるコードをテストする必要があります。
コンストラクターで間違った変数を設定するなど、通常、ある種の間違いをしない場合は、テストしません。
ユニットテストは、時間を節約して改善するために実装されています。
プログラムの比較的複雑な部分の単体テストを作成する必要があります。
単体テストを今書いても将来の時間を節約できないと確信している場合は、スキップできます。しかし、あなたは決して知らず、個人的には、ユニットテストを書くのではなく、手動ですべてのテストを行うほうが(時間、お金、神経の面で)安い場合を考えることはできません。
「これを単体テストする必要があります」は、通常、次の質問に答えることで答えることができます。「この機能が適切に機能することは重要ですか。
もちろん、それはそれよりもはるかに複雑ですが、それは開始するための良い方法です。最終的には、別の関数で使用されているためにコードが既にテストされているかどうか、または別の関数で時間を費やす方がよいかどうかなども考慮します。
テストせずにコードを記述する場合を除き、常にテストのコストが発生します。
単体テストを使用する場合と使用しない場合の違いは、テストを記述するコストと実行するコストを手動でテストするコストと比較した場合の違いです。
単体テストの作成コストが2分で、単体テストの実行コストが実質的に0であるが、コードの手動テストのコストが1分である場合、テストを2回実行した場合でも中断します。
長年、私は自分のコードの単体テストを書くのに十分な時間がないという誤解を受けていました。私がテストを書いたとき、それらは肥大化した、重いものであり、それが必要だとわかったときにのみユニットテストを書くべきだと考えるように促しました。
最近、テスト駆動開発を使用するように勧められましたが、完全な啓示であることがわかりました。私は今、ユニットテストを書かない時間がないと確信しています。
私の経験では、テストを念頭に置いて開発することで、よりクリーンなインターフェース、より焦点を絞ったクラスとモジュール、そして一般的にテスト可能なコードがよりソリッドになります。
ユニットテストのないレガシーコードを使用し、手動で何かをテストする必要があるたびに、「このコードにすでにユニットテストが含まれていると、これはずっと速くなる」と考え続けます。結合テストの高いコードに単体テスト機能を追加しようとするたびに、「分離された方法で記述されていれば、これは非常に簡単になる」と考え続けます。
TL; DRバージョン:
テストを記述するコストと、必要な回数だけ実行するコストが、必要な回数だけ手動でテストするコストよりも低い可能性が高い場合は、テストを記述します。
ただし、TDDを使用する場合は、テストを作成するコストが上達するにつれて低下する可能性が高く、コードがまったく些細でない限り、予想よりも頻繁にテストを実行することになります。
リグレッションが発生するのを確認したらすぐにテストするか、編集に何らかの原因で気付かないことを恐れます。
恐れるKindleは、適切なサイズに成長させてください。テストを早めるほど良いでしょう。
注:プロジェクトでの役割によっては、単体テストだけで作成したいテストではない場合があります。
過去の主流のテスト慣行が悪いため、誰もがユニットテストに取りつかれています。しかし、以前にテストしたことがない場合は、一般にテストに集中する必要があります。単体テストだけでは世界の問題を解決することはできません。
私は、プロジェクトのサイズではなく、テストを使用すべきかどうかを決定するプロジェクトのタイプだと考えています。
概念実証に取り組んでいる場合、またはコーディングから学習することが目標である他のプロジェクトに取り組んでいる場合、テストは必要ありません。プロジェクトを使用することを目的としている場合、場合によっては実稼働環境に送信する場合でも、テストする必要があります。
Robert C. Martinの "Clean Code"からの引用: "書くのが簡単なら、テストするのは簡単だ"ので、短くてつまらないプログラムのテストをスキップする言い訳はありません。
それは本当にサイズの問題ではありません-それはあなたがそれで何をするかです(そしてそれは何歳ですか)。テクノロジーがどのように機能するかを学び、それを捨てることを計画している場合(これをスクラムのスパイクと呼びます)、多くのテストを行わずにコーディングします。さらに開発することを計画している場合(ただうんざりしている場合でも)、コードの周りにテストを書く必要があります。TDDは、テスト手法になる前の設計手法です。実行の詳細に縛られる前に、コードに何をさせたいかを明確に把握しておく必要があります。私もしないだろう大量のレガシーコードに関する広範なユニットテストを作成することをお勧めします。複雑な部分(サイクロマティックの複雑さ/スパゲッティコードの感覚が高い部分)と頻繁に失敗する部分(多くの場合同じもの)を特定するようにしてください。他の人が示唆しているように、私はTDDに関するケント・ベックの本を読み、間違いなくマイケル・フェザーの本を読みました。彼らがあまりカバーしていないのは、コードに関するユニットテストを書くことの政治的側面です。多くの開発者はコードをテスト可能にするためにコードを変更する必要がないことを嫌い、多くの開発者はコードをまったくテストする必要性を感じていません。それは私たちが職業として取り組むべきものです。他のすべてのエンジニアリング分野は、彼らの仕事が仕様を満たしていることを(多くの場合数学的に)証明する必要があります。同じことをする必要があります。
クラスまたは機能の制限でプロジェクトをバインドし、ユニットテストに適しているかどうかを判断するのは間違っている可能性があります。アプリケーションの単体テストには多くの利点がありますが、アプリケーションを維持したり、分散環境で作業したりする必要があるときに、本当の美しさが始まります。そのため、ここで選択します。コードの小さな変更でさえ、災害を引き起こす可能性があります。
「ユニットテスト」を推奨するだけでなく、コードカバレッジを確認して、コードの最大値がユニットテストでカバーされるようにすることもお勧めします。コードカバレッジのしきい値は95%を下回ってはならず、目標は約100%でなければなりません。コードカバレッジを追跡し、レポートを生成するツールを利用できます。
Visual Studioはカバレッジデータを提供します-http://msdn.microsoft.com/en-us/library/ms182496(v=vs.80).aspx
また、NCoverまたはdotCoverを使用できます。