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