2010-12-31 19 views
20

私はTDDの初心者ですから、練習するために、現在は小さなC#コンソールアプリケーションを開発しています。私は、アプリケーションをどのように(クラス単位で)構成できるのかを簡単にスケッチし始め、私が識別できるすべてのドメインクラスを1つずつ開発することから始めました(もちろん最初のテストです)。TDDの使用:「トップダウン」と「ボトムアップ」

最後に、アプリケーションを実行可能にするために、つまり必要なロジックを呼び出すMainメソッドに必要なコードを配置するために、クラスを統合する必要があります。しかし、私はどのように "テストファースト"のやり方でこの最後の統合ステップを行うことができないのか分かりません。

「トップダウン」アプローチを使用した場合、私はこれらの問題を抱えていないと思います。質問は、どうすればいいのですか?私はMain()メソッドをテストすることで開始する必要がありますか?

誰かが私にいくつかの指針を与えることができれば、それは非常に感謝します。

+0

合格するとアプリケーションが動作していることを確認し、問題が解決したことを示す上位レベルのテストケースがありますか?すべてが機能していることを証明するもの(もちろん、UIを維持する)。 (私はTDD初心者でもあります) –

+0

私は高レベルのテストケースを持っていませんし、それが欠けているかもしれません。質問だけです:このような高レベルのテストはどのように見えますか?アプリケーションは、コンソールにのみテキストを生成します。私はそこに書かれていることを主張するべきですか? – Chris

+0

"統合"とは、オブジェクトの配線が正しいことをテストすることを意味するのではなく、すべてのクラスが一緒に期待どおりに機能することを意味します。さて、ほとんどの人は、作業が終わったかどうかを示すテストケースをいくつか用意することをお勧めします。あなたが主な機能で持っているものは、マーカスが指摘したように、確かにテストです.1つの肯定的なテストです。主な方法は、テスト駆動型アプリケーションで書かれる最後のメソッドです。受け入れテストを見ることをお勧めします。この本はあなたにとって興味深いかもしれません:http://www.growing-object-oriented-software.com/ –

答えて

29

"トップダウン"はalready used in computing to describe an analysis techniqueです。私は、代わりに "外出先"という言葉を使用することをお勧めします。

Outside-inは、システムに複数のユーザーインターフェイスが存在することを認識しているBDDの用語です。ユーザーは他のシステムと同様に人になることができます。 BDDアプローチは、TDDアプローチに似ています。それはあなたを助けるかもしれないので、私はそれを簡単に説明します。

BDDでは、シナリオから始めます。通常、システムを使用するユーザーの簡単な例です。シナリオの回りの会話は、システムが何をに実際にしなければならないかを理解するのに役立ちます。ユーザーインターフェイスを作成し、必要に応じてそのユーザーインターフェイスに対してシナリオを自動化することができます。

私たちはユーザーインターフェイスを書くとき、できるだけ薄くします。ユーザーインターフェイスは、コントローラ、ビューモデルなどの別のクラスを使用します。そのために、APIを定義することができます。

この段階では、APIは空のクラスまたは(プログラム)インターフェイスのいずれかになります。次に、ユーザーインターフェイスでこのコントローラを使用する方法の例を記述し、コントローラがどのように価値を提供するかを示します。

この例では、コントローラの責任の範囲、リポジトリやサービスなどの他のクラスに責任を委任する方法も示しています。私たちは、mockを使用してその委任を表現することができます。次に、そのクラスを作成して、サンプル(単体テスト)を動作させます。私たちは、システムレベルのシナリオを実現するための例を書いています。

モックのインターフェイスが最初は推測されてから、クラスが書き込まれるにつれてより完全に浮かび上がるので、モックされたサンプルを再加工するのが一般的です。これは、インターフェイスやAPIの次のレイヤーを定義するのに役立ちます。これについては、さらにモックを必要とせず、最初のシナリオが終了するまで、さらに多くのサンプルを記述します。

さらに多くのシナリオについて説明しますので、クラス内で異なる動作を作成します。異なるシナリオとユーザーインターフェイスで同様の動作が必要な場合は、リファクタリングして複製を削除できます。

これを外部で行うことで、できるだけ多くの情報を得て、できるだけ早くそれらのAPIを再作成します。これはReal Options (never commit early unless you know whyの原則に適合します)。私たちは使用しないものは作成せず、API自体も使いやすさのために設計されています。コードは、プログラミング言語よりもドメイン言語を使用してより自然なスタイルで書かれ、より読みやすくなりがちです。コードは書かれているよりも約10倍も読み込まれるため、これは保守性にも役立ちます。

そのため、ボトムアップのインテリジェントな推測ではなく、外部からのアプローチを使用します。私の経験によれば、よりシンプルで、より強く分離され、より読みやすく、メンテナンス可能なコードになります。

+0

これはたくさんの助けになります、ありがとうございます!私のアプリケーションをテスト駆動するために、受け入れテストを重ねる必要があるようです。 – Chris

+1

「テスト」という言葉は、物事を固定すること、物事が壊れるのを止めること、物事が確実に働くことなどを考えさせる傾向があることがわかっています。代わりに、物事の仕組みの例を説明することを考えてみてください。他の人がコードの価値を理解し、行動がその価値をどのようにして安全に変えることができるかを理解できるようになります。それで私(そして他のBDDers)が代わりに "シナリオ"と "例"という言葉を使用するのです。希望は意味をなさない。コードが書き込まれると、テストになります。 – Lunivore

+2

これは素晴らしい答えです、ありがとうございました。非常に有益。 +1 – weberc2

0

コンソールアプリケーションもテストできます。私はそれは非常に難しい、この例を見てみた:

[TestMethod] 
public void ValidateConsoleOutput() 
{ 
    using (StringWriter sw = new StringWriter()) 
    { 
     Console.SetOut(sw); 
     ConsoleUser cu = new ConsoleUser(); 
     cu.DoWork(); 
     string expected = string.Format("Ploeh{0}", Environment.NewLine); 
     Assert.AreEqual<string>(expected, sw.ToString()); 
    } 
} 

あなたはfull post hereで見ることができます。

2

main()から移動した場合は、その関数をテストできませんか?

異なるcmd-argsで実行することができ、それらをテストしたい場合があるので、これを行うのが理にかなっています。

+0

はい、私はそれを行うことができました、そして、これはおそらく今のところ最も簡単なことです。しかし、最初は、アプリケーションをテスト駆動するためにいくつかのより高いレベルのテストを開始してはいけませんか?そのように感じますが、多分私はそれからあまりにも多くを作り出しています。 – Chris

+0

さて、入出力のコンソールへのファイルへの指定は片方向ですが、YMMVの方が回帰テストの方が効果的だと思います。 Mercurial DVCSプロジェクトは、スイート内でこれを正確に実行しますが、それはかなりうまく動作しますが、操作の結果を検査するかなりのコマンドがあります。 – Macke

0

"ボトムアップ"を使用すると、既に低レベルのクラス(テスト済み)があり、より高いレベルのテストで使用できるため、多くの作業を省くことができます。逆の場合、たくさんの(おそらく複雑な)モックアップを書く必要があります。また、「トップダウン」はしばしば想定通りには機能しません。いくつかの素晴らしいハイレベルモデルを試して実装してから、あなたの前提のいくつかが間違っていることを理解しています(経験豊富なプログラマー)。もちろんパターンはここで助けますが、銀色の弾丸もありません。


すべてのテストカバレッジを取得するには、どの場合でもメインをテストする必要があります。私はすべての場合に努力する価値があるかどうかはわかりません。 Mainからすべてのロジックを別の関数に移動し(Marcus Lindblomが提案したように)、それをテストして、Mainに関数に引数を渡すようにしてください。


コンソール出力は、できるだけ簡単なテスト能力である、とあなたがTDDを使用する場合には、最終的な結果のw /任意の診断およびデバッグメッセージOだけを出力するために使用することができます。トップレベルの関数を使って結果を返し、テストしてそのままメインに出力してください。

0

私は「トップダウン」を勧めます(高レベルのテストと呼んでいます)。私はそのことについて書きました:

http://www.hardcoded.net/articles/high-level-testing.htm

そうです、あなたが直接あなたのコンソール出力をテストする必要があります。もちろん、コンソール出力を直接テストするのは簡単ですが、適切なヘルパーコードを作成すれば、次の "高レベル"テストの方がはるかに書きやすくなります。これを行うことで、無限の再考の可能性を実感できます。 「ボトムアップ」では、関係を変更することはテストを変更すること(多くの作業や危険)を意味するため、初期のクラス関係は非常に堅牢です。

0

MSDN magazine of Decemberには、「BDDサイクルが従来のテスト駆動開発(TDD)サイクルをどのようにユニットレベルの実装を駆動するフィーチャレベルのテストでラップするか」という興味深い部分がありました。詳細はテクノロジ固有のものかもしれませんが、あなたの質問に関連するアイデアやプロセスの概要が聞こえます。

0

メインは最後に非常にシンプルでなければなりません。私はそれがC#でどのように見えるか知りませんが、C++では、このようなものになります。

#include "something" 

int main(int argc, char *argv[]) 
{ 
    return TaskClass::Run(argc, argv); 
} 

パスがすでにクラスのコンストラクタにオブジェクトを作成しますが、ユニットにテストがモックオブジェクトを渡すことを。

TDDの詳細については、these screencastsをご覧ください。彼らは、アジャイル開発を行う方法を説明しますが、TDDのやり方や、C#の例も話しています。

関連する問題