最近は大流行している。 「みんな」がオススメ。それ自体が疑わしいものです。
テストファースト(テスト駆動型)開発を行うときに見つけたいくつかの欠点は何ですか?私は知識の豊富な開業医からの個人的な経験を探しています-私はインターネット上のどこかで100人の志望者の架空の考えを読むことができます。
TDDを嫌うのではなく、ソフトウェア開発プロセスを改善するのが私の仕事であり、人々が遭遇する問題について学ぶことができるほど、プロセスを改善する可能性が高まるためです。
かなりの数がありますが、利点farは欠点よりも重要です。
急な学習曲線があります。
多くの開発者は、最初からテストファーストプログラミングで効率的になることを期待しているようです。残念ながら、以前と同じ速度で経験を積み、プログラムを作成するには、かなりの時間がかかります。あなたはそれを回避することはできません。
より具体的に言うと、間違いを犯しがちです。非常に簡単に(非常に善意で)、保守が難しい、または間違ったものをテストする一連のテスト全体を作成してしまう可能性があります。ここで例を示すことは困難です。これらの種類の問題は、単に経験を積んで解決する必要があります。懸念を分離し、テストしやすいように設計する良い感覚が必要です。ここでの私の最高のアドバイスは、TDDを本当によく知っている人とペアプログラミングを行うことです。
前もってコーディングを行います。
テストファーストとは、テストをスキップできないことを意味し(これは良いことです)、最終的にはより多くのコードを前もって作成することになります。これはより多くの時間を意味します。繰り返しますが、それを回避することはできません。保守、拡張が容易で、一般にバグが少ないコードを使用することで報酬を得ることができますが、時間がかかります。
マネージャーへの販売は難しい場合があります。
ソフトウェアマネージャーは通常、タイムラインのみに関係しています。テストファーストプログラミングに切り替えて、機能を完了するのに1週間ではなく2週間かかっている場合、彼らはそれを気に入らないでしょう。これは間違いなく戦う価値のある戦いであり、多くのマネージャーはそれを手に入れるのに十分な悟りを開いていますが、それは難しい売りになる可能性があります。
他の開発者への販売は難しい場合があります。
学習曲線が急であるため、すべての開発者がテストファーストプログラミングを好むわけではありません。実際、most開発者は最初はそれが気に入らないと思います。ペアプログラミングのようなことをして、彼らがスピードを上げるのを助けることができますが、それは難しい売りです。
結局、利点は欠点を上回りますが、欠点を無視するだけでは役に立ちません。最初から適切に何を扱っているかを知ることは、すべてではないにしても、いくつかの欠点を交渉するのに役立ちます。
テストファーストは、次のようなコードを記述していることを前提としています。
プロジェクトがこれらの要件を満たしていない場合、問題が発生します。 TDDのプロモーターは、他の製品に対する適切な回答がなく、製品を再設計してそれらのラインにうまく収まるように提案します。それが不可能または望ましくない状況があります。
実際には、テストファーストテストがプログラムの正しい機能について何かを実際に証明していると考える人々との大きな問題もあります。多くの場合これは真実ではありませんが、それが真実である場合でさえ、正確さの完全な全体像からはほど遠いです。人々は何百ものテストに合格しており、TDDの前は数百のテストケースしか行っていなかったため、テストを少なくしても安全だと考えています。私の経験ではTDDは、開発者が誤ったセキュリティを持っているため、さらに多くの統合テストが必要であり、大きな編集者を実行するためにすべてのテストを変更する痛みは、開発者を興味深い回避策に導く可能性があることを意味します。
例:
私の個人的な最良の例は、asp.netのセキュリティコードを記述するときです。それらがマシン設定から敵対的な環境で実行することを意図している場合、それらは強制され、署名され、封印されます、そしてそれらはIIS godオブジェクトに対して実行されているため、非常にモックすることは非常に困難ですパフォーマンスとメモリ使用量の制約を追加すると、残りの領域でプレースホルダーオブジェクトを使用する柔軟性がすぐに失われます。
抽象化が最適化されず、リソース制限が低いため、あらゆる種類のマイクロコントローラーまたはその他の低リソース環境コードでは、真にOOスタイルのデザインを行うことができない場合があります。同じことが言えます。多くの場合、高性能ルーチンも同様です。
私が見た最大の欠点は、TDD自体ではなく、開業医にあります。彼らは独断的で熱心なアプローチを取る(where whereすべてがテストされる必要がある。時々(多くの場合そうです)、それは必要ありません。また、実用的でない場合もあります(つまり、組織をTDDに導入するなど)。
優れたエンジニアは、トレードオフを見つけ、テストファーストを適用するタイミング/場所/方法の適切なバランスを適用します。また、実際のコードではなく(2〜3倍以上)テストの開発にずっと多くの時間を費やしていることに気付いた場合、問題が発生します。
言い換えれば、TDD(またはそのことについてはソフトウェア開発のあらゆるもの)を実用的かつ合理的にすることです。
2009年8月上旬にTDDを開始し、会社全体で2009年9月/ 10月にTDDに切り替えることを確信しました。現在、開発チーム全体が完全に変換されており、テストされていないコードをリポジトリにコミットすることは悪いことと見なされてスローされます。それは私たちにとって素晴らしい働きをしており、カウボーイコーディングに戻ることは想像できません。
ただし、かなり注目すべき2つの問題があります。
テストスイートを保守する必要があります
TDDに真剣に取り組んでいると、テストのlotsを書くことになります。さらに、テストのright粒度が何であるかを理解するには、ある程度の時間と経験が必要です(やり過ぎは、やりすぎと同じくらい悪いです)。これらのテストもcodeであり、ビットロートの影響を受けやすくなっています。つまり、他のすべてと同様にそれらを維持する必要があります。依存するライブラリをアップグレードするときに更新し、時々リファクタリングします...コードに大きな変更を加えると、多くのテストが突然古くなったり、明らかに間違っている。運が良ければそれらを削除することもできますが、多くの場合、有用なビットを抽出して新しいアーキテクチャに適合させることになります。
テストの抽象化は時々リークします
私たちは、非常に優れたテストフレームワークを持つDjangoを使用しています。ただし、現実と少し矛盾する仮定を行う場合もあります。たとえば、一部のミドルウェアはテストを中断する場合があります。または、一部のテストでは、キャッシングバックエンドについて想定しています。また、「SQLite3ではなく」「実際の」dbを使用している場合、テスト用にdbを準備するにはかなりの時間がかかります。確かに、ローカルで行うテストにはSQLite3とメモリ内データベースを使用できます(使用すべきです)が、一部のコードは使用するデータベースによって動作が異なるだけです。現実的な設定で実行される継続的インテグレーションサーバーの設定は必須です。
(一部の人々は、データベースなどのすべてのものをモックする必要があるとか、テストが「純粋」ではないということを教えてくれますが、それはイデオロギーの話にすぎません。テストスイートは無価値になります。)
つまり、私が説明した問題は、TDDにかなり進んでいる場合にのみ顕著になります... TDDを開始したばかりの場合(または小規模なプロジェクトで作業している場合)、テストのリファクタリングは問題になりません。
私にとって、TDDのように、テストを広範囲に適用しようとするたびに、テストには深い心理的問題があります。ただし、セーフティネットを提供するテストがない場合は、コードを慎重にコーディングします。結果は常にテストよりも優れています。
多分それは私だけです。しかし、あらゆる種類のセーフティベルとホイッスルを備えた車は、クラッシュする傾向があることも読んだことがあります(安全機能があることをドライバーが知っているため)。 TDDは一部の個人と互換性がない場合があります。
テストファーストが本当に邪魔になる状況の1つは、適切な実装を作成する前に、アイデアをすばやく試してみて、それが機能するかどうかを確認したい場合です。
私のアプローチは通常:
ステップ2にたどり着けないことがあります。
この場合、TDDを使用すると、メリットよりデメリットが多くなることがわかりました。
そのため、新しいアイデアを探る必要がある場合は、TDDを使用せず、新しいコードがどこかに到達したと感じたときにのみユニットテストを導入します。
注:TDDにはさまざまな種類があります。ユニット、BDD、ATDD、またはその他のバリアントに関係なく、多くの困難が残っています
副作用
それがモックであれ、フィクスチャであれ、機能テストであれ、外部の状態やシステムへの依存は、多くの場合、テストの最も複雑な原因、テスト方法の混乱、およびそれを誤解する最大のリスクの原因です。私が見たいくつかの問題:
コーディングに対するアプローチを変更する必要がありますが、大幅な変更になる場合もあります。
コーディング方法は人によって大きく異なります。 TDDでは、特定の動作をアサートするテストから開始して、テストに合格するように実装する必要があります。私は、プログラマーでTDDを助長しないプログラマーを見てきました。開発アプローチの変更に慣れ始めてから約2か月かかりました。
テストで気にすべきこととテストで気にしないことを理解するには時間がかかります。
すべてのチームは、テストのどこに線を引くかを明確に決定する必要があります。彼らがテストしてほしいと彼らが評価するもの、そして彼らはそうではないもの。多くの場合、良いテストの書き方や、実際にテストに関心を持っていることを学ぶのは大変なプロセスです。その間、スタイルとアプローチの両方に一貫性ができるまで、コードは流動的な状態を続けます。
ユニットテスト固有:大規模なリファクタリング
数万のユニットテストを含む重要なコードベースの大規模または基本的なリファクタリングは、すべてのテストを更新するために莫大なコストを発生させます。これは、リファクタリングを行うことに関連するコストのために、それが正しいことである場合でも、リファクタリングを行わないことに対する反発として現れることがよくあります。
私の例えは、Scalextricトラックの障壁です。あなたがそれらを身に着ければ、あなたははるかに慎重になります。
人々はまた、彼らのテストについて少しスペースの落とし穴を感じる-彼らはうまく動くので、彼らはコードが完全にテストされていると信じているが、それはテストプロセスの始まりに過ぎない。
私の考えでは、TDDはBDDへの足がかりです。実行される一連のテストは、テストが何を行うかを知らずに開発者をサポートするのに役立ちません。 BDDを使用すると、テストの出力は英語で行われ、テストが文書化され、システムの理解が深まります。