テスト駆動設計を採用すると何が失われますか?
ネガのみをリストします。否定的な形で書かれた利点をリストしないでください。
いくつかの欠点(特にプロジェクトの基盤を作成する場合は、利点がないと主張していませんが、最後に多くの時間を節約できます):
「実際の」TDD(読み取り:最初に赤、緑、リファクタリングステップでテストする)を実行する場合は、統合ポイントをテストするときにモック/スタブの使用も開始する必要があります。
モックの使用を開始したら、しばらくしてから、依存性注入(DI)および制御の反転(IoC)コンテナーの使用を開始します。そのためには、すべてにインターフェースを使用する必要があります(それ自体に多くの落とし穴があります)。
一日の終わりには、単に「昔ながらの方法」で行う場合よりも多くのコードを書く必要があります。顧客クラスだけでなく、インターフェイス、モッククラス、IoC構成、およびいくつかのテストを記述する必要もあります。
また、テストコードも保守および管理する必要があります。テストは他のすべてのものと同じくらい読みやすいものでなければならず、良いコードを書くには時間がかかります。
多くの開発者は、これらすべての「正しい方法」を行う方法をよく理解していません。しかし、誰もがTDDがソフトウェアを開発する唯一の真の方法であると彼らに言うので、彼らは彼らができる限りベストを尽くすだけです。
思っているよりもずっと難しい。多くの場合、TDDで行われたプロジェクトは、誰も実際に理解していない多くのコードになります。ユニットテストは、しばしば間違ったこと、間違った方法をテストします。そして、優れたテストがどのように見えるべきかについては誰も同意していません。
これらのテストはすべて、システムの動作を「変更」(リファクタリングの反対)することを非常に難しくし、単純な変更は非常に困難で時間がかかります。
TDDの文献を読む場合、常に非常に優れた例がいくつかありますが、実際のアプリケーションでは多くの場合、ユーザーインターフェイスとデータベースが必要です。これはTDDが本当に難しくなる場所であり、ほとんどのソースは良い答えを提供していません。そして、もしそうなら、それは常により多くの抽象化を伴います:モックオブジェクト、インターフェースへのプログラミング、MVC/MVPパターンなど、これもまた多くの知識を必要とし、そして...あなたはさらにコードを書かなければなりません。
熱心なチームがなく、優れたテストの作成方法と優れたアーキテクチャに関するいくつかの知識がある少なくとも1人の経験豊富な開発者がいない場合は、TDDの道を進む前に2回考える必要があります。 。
多数のテストがある時点に到達したら、システムを変更するには、変更によって無効になったテストに応じて、テストの一部またはすべてを書き直す必要があります。これにより、比較的迅速な修正が非常に時間のかかる修正に変わる可能性があります。
また、実際の優れた設計原理よりもTDDに基づいて設計の決定を開始する場合があります。 TDDが要求する方法をテストすることは不可能な非常にシンプルで簡単なソリューションがあったかもしれませんが、実際にはミスを起こしやすいはるかに複雑なシステムがあります。
私にとって最大の問題は、「それに参加する」ためにかかる時間の大幅な損失だと思います。私はまだTDDでの旅の始まりにとても興味があります(興味があるなら私の冒険を更新するために私の blog を見てください)そして私は文字通り時間はじめに。
脳を「テストモード」にするのに長い時間がかかり、「テスト可能なコード」を書くこと自体がスキルです。
TBH、私は丁寧に Jason Cohenのコメント プライベートメソッドを公開することに反対しますが、それはそれが目的ではありません。 以前のように、新しい作業方法で公開メソッドを作成したことはありません。ただし、アーキテクチャの変更を伴い、コードのモジュールを「ホットプラグ」して、他のすべてをテストしやすくすることができます。これを行うために、コードの内部にアクセスしやすくするnotにする必要があります。それ以外の場合は、すべてが公開された正方形に戻りますが、カプセル化はどこにありますか?
(IMO)の概要:
PS:ポジティブへのリンクが必要な場合は、いくつかの質問をして回答しました。 profile をチェックしてください。
テスト駆動開発を実践してきた数年間で、最大の欠点は次のとおりです。
TDDはペアで行うのが最適です。 1つは、KNOWif/elseステートメントを記述する方法を実装するだけの衝動に抵抗するのは難しいことです。しかし、ペアで仕事を続けるのは、彼が仕事を続けるからです。悲しいことに、多くの企業/管理者は、これがリソースの適切な使用であるとは考えていません。同時に実行する必要がある2つの機能があるのに、なぜ1人の機能を書くために2人で支払うのですか?
一部の人々は、単体テストを書くことに忍耐を持っていません。仕事に誇りを持っている人もいます。または、複雑なメソッド/関数が画面の端から流れ出すのを見るのと同じように、 TDDは万人向けではありませんが、そうであることを願っています。コードを引き継ぐ貧しい人々にとっては、物の維持がずっと簡単になります。
理想的には、悪いコードを決定した場合にのみテストが中断します。つまり、システムは一方向に機能すると思っていたのに、機能しなかったことがわかりました。テストまたは(小さな)テストセットを壊すことにより、これは実際には良いニュースです。 exactly新しいコードがシステムに与える影響を知っています。ただし、テストの記述が不十分、密結合、さらに悪いことに生成された場合(咳VSテスト)、テストの維持は合唱団になる可能性があります。そして、十分なテストが作成している知覚価値よりも多くの作業を引き起こし始めた後、テストはスケジュールが圧縮されたときに削除される最初のものになります(例えば、時間を縮める)
理想的には、この方法論を順守すれば、コードはデフォルトで100%テストされることになります。通常、コードカバレッジは90%以上になります。これは通常、テンプレートスタイルのアーキテクチャがあり、ベースがテストされているときに発生します。テンプレートのカスタマイズをテストせず、コーナーをカットしようとします。また、私が以前に遭遇したことのない新しい障壁に遭遇したとき、それをテストする際の学習曲線があることを発見しました。私はコードのいくつかの行を古いskoolの方法で書くことを認めますが、私は本当にその100%を持っているのが好きです。 (私は学校で過大達成者だったと思います、er skool)。
ただし、そのため、TDDの利点は、アプリケーションをカバーするだけでなく、1つの変更がすべてを壊すほど脆弱ではないという優れたテストセットを達成できるという単純なアイデアのマイナスをはるかに上回ると思います。 1日目と同じようにプロジェクトの300日目に新機能を追加し続けることができます。これは、TDDをすべてのバグに満ちたコードの魔法の弾丸であると考えている人には起こりません。働かない、期間。
個人的には、TDDを使用すると、より簡単なコードを記述し、特定のコードソリューションが機能するかどうかの議論に費やす時間が少なくなり、基準によって満たされないコード行を変更する恐れがないことがわかりました。チーム。
TDDは習得するのが難しい分野であり、私は数年間それに取り組んできましたが、今でも新しいテスト手法を常に学んでいます。前もって多大な時間を費やしていますが、長期的には、自動化された単体テストがない場合よりも、持続可能性は大幅に向上します。今、私のボスだけがこれを理解できれば。
最初のTDDプロジェクトには、時間と個人の自由という2つの大きな損失があります
あなたは時間を失います:
あなたは個人的な自由を失います:
お役に立てれば
TDDでは、これらのテストに合格するコードを記述する前に、クラスの動作を計画する必要があります。これはプラスとマイナスの両方です。
「バキューム」でコードを書く前にテストを書くのは難しいと思います。私の経験では、最初のテストを書いているときに忘れていたクラスを書いているときに必然的に何かを考えるたびに、テストをつまずく傾向があります。次に、クラスをリファクタリングするだけでなく、テストも行います。これを3〜4回繰り返してください。イライラすることがあります。
クラスのドラフトを最初に作成してから、一連の単体テストを作成(および維持)することを好みます。ドラフトを作成した後、TDDはうまく機能します。たとえば、バグが報告された場合、そのバグを悪用するテストを作成し、テストに合格するようにコードを修正します。
TDDではプロトタイピングが非常に困難になる可能性があります。ソリューションへの道がわからない場合、テストを前もって書くのは難しい場合があります(非常に広範なものを除く)。これは苦痛かもしれません。
正直なところ、大部分のプロジェクトの「コア開発」には、実際の欠点はないと思います。通常、コードがテストを必要としない(それは絶対にない)ので十分であると信じている人や、平易な人でもわざわざコードを書くことはできません。
さて、このストレッチは、テストをデバッグする必要があります。また、テストの作成にはある程度のコストがかかりますが、ほとんどの人は、時間を節約したデバッグと安定性の両方で、アプリケーションのライフタイムにわたって利益をもたらす先行投資であることに同意します。
しかし、私が個人的に抱えていた最大の問題は、実際にテストを書く規律を立てることです。チーム、特に確立されたチームでは、費やした時間が価値があることを彼らに納得させるのは難しい場合があります。
TDDのマイナス面は、通常、「アジャイル」方法論と密接に関連していることです。これは、システムの文書化にnoを重要視し、テストが特定の値を返すのではなく、特定の値を返すべき理由を理解することを意味しますその他は、開発者の頭の中にのみ存在します。
開発者がテストが特定の値を返し、他の値を返さないという理由を離れる、または忘れるとすぐに、あなたは台無しになります。 TDDが適切に文書化され、人間が読める(つまり、とがった髪のマネージャー)文書に囲まれている場合は問題ありません。
私がドキュメントについて話すとき、これはコードの宣伝ではありません。これは、管理者、弁護士、更新しなければならない貧しい樹液が参照できるユースケースや背景情報など、アプリケーションの外部に存在する公式文書です2011年のコード。
テストがあまり徹底的でない場合、テストに合格したというだけで、「すべてが機能している」という誤った感覚に陥ることがあります。理論的には、テストに合格した場合、コードは機能しています。しかし、初めてコードを完全に記述できれば、テストは必要ありません。ここでのモラルは、テストに頼るだけでなく、完全なものを呼び出す前に自分で健全性チェックを行うことを確認することです。
そのメモで、あなたの健全性チェックがテストされていないものを見つけた場合、戻ってそれのためのテストを書くことを確認してください。
TDDに夢中になる状況がいくつかあります。名前を付けるには:
テストケースの保守性:
大企業の場合、多くの場合、テストケースを自分で作成する必要はありません。または、少なくともそのほとんどは、入社時に他の誰かが作成したものです。アプリケーションの機能は時々変更され、HP Quality Centerなどのシステムを使用してそれらを追跡しなければ、すぐに夢中になります。
これはまた、新しいチームメンバーがテストケースで何が起こっているのかを把握するのにかなりの時間がかかることを意味します。次に、これはより多くのお金を必要とすることに変換できます。
テスト自動化の複雑さ:
テストケースの一部またはすべてをマシン実行可能なテストスクリプトに自動化する場合、これらのテストスクリプトが対応する手動テストケースとアプリケーションの変更に合わせて同期していることを確認する必要があります。
また、バグをキャッチするのに役立つコードのデバッグに時間を費やします。私の意見では、これらのバグのほとんどは、テストチームがアプリケーションの変更を自動化テストスクリプトに反映していないことに起因しています。ビジネスロジック、GUI、その他の内部機能の変更により、スクリプトの実行が停止したり、実行が不安定になったりする可能性があります。変化は非常に微妙であり、検出が難しい場合があります。テーブル1がテーブル2になったときに、テーブル1の情報に基づいて計算を行ったため、すべてのスクリプトが失敗を報告します(アプリケーションコードでテーブルオブジェクトの名前を交換したため)。
最大の問題は、適切な単体テストの書き方を知らない人々です。それらは互いに依存するテストを記述します(そして、Antでうまく動作しますが、Eclipseから実行すると、順序が異なるために突然失敗します)。特にテストを行わないテストを作成します。コードをデバッグし、結果を確認し、テストに変更して「test1」と呼びます。クラスとメソッドの範囲を広げました。ユニットテストを書く方が簡単だからです。単体テストのコードはひどく、すべての古典的なプログラミングの問題(重結合、500行の長さのメソッド、ハードコードされた値、コードの重複)を伴い、維持するのは大変です。奇妙な理由のために、人々は単体テストを「実際の」コードよりも劣るものとして扱い、その品質についてはまったく気にしません。 :-(
テストの作成に費やす多くの時間を失います。もちろん、バグをより早くキャッチすることで、プロジェクトの終わりまでにこれを保存できます。
すべてのコードをテストする前に、「完了」と言う能力を失います。
実行する前に数百または数千行のコードを書く機能を失います。
デバッグを通じて学習する機会を失います。
自信がないコードを出荷する柔軟性を失います。
モジュールを密に結合する自由が失われます。
低レベルの設計ドキュメントの作成をスキップするオプションを失います。
誰もが変更を恐れるコードに伴う安定性を失います。
「ハッカー」の称号を失います。
最大の欠点は、TDDを本当に適切に実行したい場合、成功するまでに多くの失敗を余儀なくされることです。いくつのソフトウェア会社が働いているか(KLOCあたりのドル)を考えると、最終的に解雇されます。コードがより速く、よりクリーンで、保守しやすく、バグが少ない場合でも。
KLOC(またはテストされていない場合でも、実装されている要件)で支払う企業で働いている場合は、TDD(またはコードレビュー、ペアプログラミング、または継続的統合など)から離れてください。
困難で予期せぬ要件に再び焦点を合わせるのは、プログラマーにとって常に悩みの種です。テスト駆動開発では、既知のありふれた要件に集中する必要があり、開発はすでに想像されているものに限定されます。
考えてみてください。特定のテストケースに合わせて設計することになる可能性が高いため、創造性を発揮せず、「ユーザーがX、Y、Zを実行できたらクールだ」と考え始めるでしょう。したがって、そのユーザーが潜在的なクールな要件X、Y、およびZに興奮し始めると、デザインは既に指定されたテストケースに厳密に焦点を合わせている可能性があり、調整が困難になります。
もちろん、これは両刃の剣です。ユーザーが想像できるすべての考えられるX、Y、Zの設計に時間を費やした場合、必然的に何も完了しません。何かを完了すると、コード(デザイン)で何をしているのかを(だれでも)誰も知ることができなくなります。
最初の開発時間についての答えを次に挙げます。また、テストの安全性なしに快適に作業する能力も失います。また、TDDナットバーとも呼ばれているため、数人の友人を失う可能性があります;)
遅いと考えられています。悲しみの観点からはそうではない長期的には、あなたは道を救いますが、間違いなく「コーディングではないテスト」に時間を費やしているので、より多くのコードを書くことになります。それは欠陥のある議論ですが、あなたは尋ねました!
XMLフィードやデータベースのような「ランダムな」データのテストを書くのは難しくて時間がかかります(それほど難しくありません)。最近、天気データフィードの操作に時間を費やしました。少なくともTDDの経験があまりないので、そのためのテストを書くのはかなり混乱しています。
プロジェクトに入るのに時間がかかり、プロジェクトでそれを始めるには時間がかかりますが...自動テストで非常に高速に発見された愚かなバグを見つけたとき、私は常にテスト駆動アプローチを行わなかったことを後悔しています。さらに、TDDはコードの品質を向上させます。
良い答えです。 TDDのダークサイドを回避する方法をいくつか追加します。
独自のランダム化されたセルフテストを行うアプリを作成しました。特定のテストを書く際の問題は、それらをたくさん書いたとしても、あなたが考えているケースだけをカバーすることです。ランダムテストジェネレーターは、考えもしなかった問題を見つけます。
多くの単体テストの概念は、複雑なデータ構造のように、無効な状態になる可能性のあるコンポーネントがあることを意味します。複雑なデータ構造から離れると、テストする必要がはるかに少なくなります。
アプリケーションが許可する範囲で、通知、イベント、および副作用の適切な順序に依存する設計には内気になります。それらは簡単にドロップまたはスクランブルされる可能性があるため、多くのテストが必要です。
複数の責任を持つ大規模なクラスを失うことになります。また、複数の責任を持つ大規模なメソッドを失う可能性があります。リファクタリングの能力を失う可能性がありますが、リファクタリングの必要性の一部も失われます。
ジェイソン・コーエンは次のように言った:TDDはあなたのコードのために特定の組織を必要とする。これはアーキテクチャ的に間違っている可能性があります。たとえば、プライベートメソッドはクラスの外部で呼び出すことはできないため、メソッドを非プライベートにしてテスト可能にする必要があります。
これは抽象化の欠落を示していると言えます。プライベートコードを実際にテストする必要がある場合は、おそらく別のクラスにある必要があります。
デイブ・マン
アプリケーションを別の方法で作成する必要があります。テスト可能なアプリケーションです。最初はこれがどれほど難しいか驚かれることでしょう。
一部の人々は、書く前に何を書くかについて考えるという概念を非常に難しいと感じています。モッキングなどの概念は、一部の人にとっても難しい場合があります。テスト用に設計されていない場合、レガシーアプリのTDDは非常に困難です。 TDDに対応していないフレームワークを取り巻くTDDも苦労する可能性があります。
TDDはスキルであるため、ジュニア開発者は最初は苦労する可能性があります(主に、この方法で作業するように教えられていないため)。
全体的には、人々が熟練するにつれて短所は解決され、あなたは「臭い」コードを抽象化し、より安定したシステムを手に入れることになります。
私のチームのアジャイル開発を教えた人は計画を信じていませんでした。
彼のモットーは、リファクタリング、リファクタリング、リファクタリングでした。リファクタリングは「事前に計画しない」ことを意味することを理解しました。
BDDの原則をTDDプロジェクトに適用すると、ここに挙げたいくつかの主要な欠点(混乱、誤解など)を軽減できます。 BDDに慣れていない場合は、ダンノースの紹介をお読みください。彼は、職場でTDDを適用することから生じた問題のいくつかに答えてコンセプトを思いつきました。 DanのBDDの紹介は こちら にあります。
BDDはこれらのネガの一部に対処し、ギャップストップとして機能するため、この提案のみを行います。フィードバックを収集する際に、このことを検討してください。
TDDでは、コードに特定の組織が必要です。これは非効率的または読みにくいかもしれません。または、アーキテクチャ的にも間違っています。たとえば、private
メソッドはクラス外では呼び出せないため、メソッドを非プライベートにしてテスト可能にする必要がありますが、これは間違っています。
コードが変更されると、テストも変更する必要があります。リファクタリングでは、これは多くの余分な作業になる可能性があります。
テストが常に最新であることを確認する必要があります。赤信号を無視し始めた瞬間は、テストが無意味になった瞬間です。
また、テストが包括的であることを確認する必要があります。または、大きなバグが発生した時点で、コードの記述に時間を費やすことを最終的に確信したむかつく管理タイプは、文句を言うでしょう。