私は間違っているかもしれませんが、TDDへの最良のアプローチは、ソリューション、赤、緑、リファクタリング(標準の式に「ソリューション」を追加)だと思います。
最初にソリューションをコーディングすることで、実際のテストを作成する際の効率が大幅に向上したと感じています。場合によっては、ソリューションがどうなるかを知るのが難しく、テストを書くのがはるかに難しいことがあります。どこから始めればよいかわからないときにテストを書くのは大変です。ソリューションをすばやくコーディングすることで、落とし穴を回避することもできると思います。 逆に、テストを書くことは、問題が合格したら解決されるという推測にすぎないようです。最初にコーディングすることで、適切な検証を確実に行うことができます。
だから私のアプローチは:
しかし、TDDの重要なポイントでさえ、何か欠けているかもしれません。おそらく、問題を初めて検討したことにより、完全なテストセットを作成する可能性が低くなります。そうしないと、デザインが異なるためです。
TDDが解決策を見つけるフェーズを逃したという事実につまずいたのは、あなたが最初ではありません。これは、このトピックに関するRalf Westphalの一連の記事全体をまとめた ドイツのブログ へのリンクです。ドイツ語を話せない場合は、Google翻訳をお試しください。少なくとも 真ん中のグラフィック を見て、 "TDD 2.0"がどのように見えるかをスケッチすることができます。
(Westphalの記事はWebでは利用できません、AFAIKですが、彼のアイデアの一部は彼の blog )で見つけることができます。
ソリューションをコーディングする
それは私見ではありません。 「解決策の発見」は、理想的には(完全)コーディングなしのフェーズです。 APIをコードで記述したり、概念的なコメントを自然言語で書き留めたり、高レベルの疑似コードを書き留めたりできますが、実装の詳細によって思考プロセスが妨げられることはありません。これは、TDDの通常の「ボトムアップ」プロセスとは対照的に、トップダウンアプローチです。
「最初にソリューションのコーディング」を開始すると、おそらくTDDをまったく実行しないことになります。ソリューションのすべての重要な側面がカバーされていることを確認するのに十分なテストを作成しないという高いリスクを冒すと、 「念のため」に実装しますが、それらは(まだ)必要はありません。また、APIのユーザーの観点からは、APIの要件についてはあまり考えていません。
これは実際には非常に古い知恵です。私が学校にいたとき(> 30年前)、私は互いにサポートし合うプログラミング手法として「ボトムアップ」と「トップダウン」という用語をすでに学びました。 「本によるTDD」は「ボトムアップ」の側面をカバーするだけであり、「トップダウン」の側面は、最初に(少なくとも少し)分析と設計を明示的に行うことによって導入されます。
つまり、最初にソリューションを開発するのは問題ありませんが、TDDを使用する場合は、テストの作成を開始する前にソリューションをコードに実装しないでください。
はい、それは悪い習慣です。
ソリューションフェーズのためではなく、コメントアウトと不自然なTDDが原因で終了したためです。
ソリューションをコーディングしている場合は、テストを追加するだけで完了です。
あなたが「私たちはTDDをやった」と言いたいからといって、練習で圧迫しようとしないでください。
機能することを実行し、「反復的なステップからソリューションが魔法のように表示されないため、TDDを実行しませんでした」と言います。
新しい方法論の名前を選択して*、それについて本を書きます。ステップ3:利益!
* STDDではない
- ソリューションをコーディングする
- ソリューションにコメントし、標準の式(Green、Red、Refactor)に従ってください
実際には、TDDの一般的なパターンからそれほど遠くはありません。ステップ#1は スパイクソリューション に類似しています。ジェームズショアはこのようにスパイクを導入します
さらに情報が必要な場合は、小規模で孤立した実験を行います。
TDDでは、スパイクは破棄され、新しい実装はゼロから設計されます。
逆に言えば、テストを書くことは、問題が合格したら解決されるという推測にすぎないようです。
まったくそうではありません。正しい答えを製品コードにハックするだけで、テストに合格することがよくあります。この時点で問題が "解決"されたとは誰も考えません。テストが調整され、特定の障害が検出されるだけです。
実際に問題を解決することは、通常、緑色のバーの下で発生します。
何をしているのかとTDDの違いを理解するには、 テストとチェック の違いを確認すると役立ちます。説明するプロセスでは、作成したコードに調整済みチェックを追加していますが、実際にはテストしていませんデザイン。
TDDは意図的に反対の方向に進みます。テストを作成し、APIの使用方法に注意を払って設計します。次に、API設計によって制約されるソリューションを作成します。
既定のソリューションに準拠するチェックを作成することは、legacyコードを管理するために使用する手法の1つです。異なる制約のセットの下で動作しているため、異なる手法を使用しています。
しかし、何か新しいものを作成するときに、自発的にレガシー制約を追加することは、逆に思えます。
テストと実装コードの両方が要件からフローする必要があります。 TDDの背後にある主なアイデアの1つは、コードの他のすべてのコンシューマーと同じ方法で入力を提供し、出力を取得する必要があるため、インターフェースを前もって考える(そして単純に保つ)ことを強いられることです。しかし、思慮深く、要件が適切に具体化されている場合は、alwaysを片方に記述できるようにしてください。
作成しているソフトウェアがわからない場合は、まずそれを要件として確立する必要があります。その場合、テストを実装に密結合しないように注意する必要があります。システムが壊れやすくなり、更新が困難になります。あなたがそれを非常に多くのように提案していることはこれをもたらすでしょう、または少なくともテストの最後の方法論とまったく同じように、それだけで物事を途中で難しくします。
ただし、要件主導のテストが失敗するケースは確かにあります。要件は時々変化しますが、適応以外にできることはほとんどありません。 (そして、それらには欠陥があり、あなたは繰り返します。)しかし、特定の実装のみが変更された場合、interfaceは変更されません。つまり、これらのインターフェースのテストは引き続き有効です。 TDDに従っている場合は、実装に固有のEdgeケースなどをカバーするために、テストを追加できます。
最初にソリューションをコーディングしてから、そのテストを作成する場合、それはBDDです。だから私はあなたがしようとしていることは悪い習慣ではなく、それは単にTDDではないと信じています。
TDDのアイデアはテストだけでなく、開発のガイドでもあるので、ユニットへの分割はテスト可能です。私はむしろあなたの「ソリューション」を「プロトタイプ」と呼びたいです。これはタスクをクリアするのに役立つかもしれませんが、一般的に本番環境に継承されるべきではありません。
逆に言えば、テストを書くことは、問題が合格したら解決されるという単なる推測にすぎないようです。最初にコーディングすることにより、適切な検証を確実に行うことができます。
私が理解している限り、解決策は「もっとテストする」かもしれません。または、すべてのケースがカバーされるように、アーキテクチャとテストを設計します。プロトタイプも同様に役立ちます。