API とコア機能を作成しながら単体テストを作成します。でも私は、TDD と BDD を食べて、寝て、呼吸するクールなファンになりたいです。TDD/BDD を正しく開始するための最良の方法は何ですか? 書籍、リソース、フレームワーク、ベスト プラクティスはありますか?
私の環境は、いくつかの外部 Web サービスおよびデータベースと統合された、Grails フロントエンドを備えた Java バックエンドです。
API とコア機能を作成しながら単体テストを作成します。でも私は、TDD と BDD を食べて、寝て、呼吸するクールなファンになりたいです。TDD/BDD を正しく開始するための最良の方法は何ですか? 書籍、リソース、フレームワーク、ベスト プラクティスはありますか?
私の環境は、いくつかの外部 Web サービスおよびデータベースと統合された、Grails フロントエンドを備えた Java バックエンドです。
始めるのに良い場所はブログを読むことです。次に、ブログを書いている人々の本を購入します。私が強くお勧めするもの:
「ボブおじさん」マーチンとオブジェクトメンターの連中:http: //blog.objectmentor.com/
PSはボブズの本のクリーンコードを取得します:
http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
私の友人のティム・オッティンガー(元オブジェクトメンターの男) http://agileinaflash.blogspot.com/ http://agileotter.blogspot.com/
ジェットブレインズの連中: http ://www.jbrains.ca/permalink/285
他の誰もがあなたにTDDについての意見を伝えたいだけで、ジェダイ忍者になるためのあなたの探求を助けたくないので、これを拡張する必要性を感じました。TDDのマイケルジョーダンはケントベックです。彼は本当にその本を書いた:
http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530
彼はまた次のブログを書いています:
http://www.threeriversinstitute.org/blog/?p=29
TDDの他の「有名な」サポーターは次のとおりです。
すべてがフォローするのに最適な人々です。また、Agile2010やSoftwareCraftsmanship(今年はシカゴで同時に開催された)などのいくつかの会議に参加することを検討する必要があります。
「練習 X は決して悪いことではありません。うまくいかない場合は、正しく行っていないということです」と人々が言うのは好きではありません。申し訳ありませんが、それは他の熱心すぎる宗教的教義と同じ感覚を持っています. 私はそれを買いません。
時間とお金が許す限りの最善の解決策を目標にすべきだという人々の意見に、私は同意します。
TDD に反対する人は誰でも、品質を無視していると自動的に非難されるべきではありません。(「では、いつ妻を殴るのをやめたのですか?」) 実際、ソフトウェアにはバグがあり、それらをすべて排除するコストは、利益と比較検討する必要があります。
ものづくりにおいても同じことが言えます。厳密な公差と鏡面仕上げが保証されない場合があるため、表面の寸法と仕上げの公差はすべて同じではありません。
はい、クラスを書く前に単体テストを書きます。テストが設計に及ぼす影響を見てきた。コードカバレッジを測定して監視しています。私のカバレッジが受け入れられないことがわかった場合は、さらにテストを作成します。リファクタリングのための単体テストのセーフティネットの利点を理解しています。メリットを直接体験したので、一人で作業している場合でも、これらのプラクティスに従います。わかった。
しかし、「食べて、寝て、呼吸するユニットテストとTDD」について私を悩ませ始めたチームメイトに疑問を投げかけます。
私のマネージャーは、私を昇進させる唯一の方法は、チームを TDD/BDD にすることだと言っています。
これがあなたを嫌な人のように聞こえるかもしれないと思ったことはありませんか?あなたのしつこいことがチームの他のメンバーを疎外していることに気づきましたか?
この反応は私の評判ポイントを少し失うかもしれませんが、言わなければなりませんでした。
より良いアプローチは、自分で実践し、他の人にそのメリットを見てもらうことだと思います. 例によってリードします。口で言うよりもはるかに説得力があります。
Grails にはテスト生成機能が組み込まれています。Grails を使用するチームで作業している場合、さらにどれだけの販売が必要ですか?
TDD / BDDを実行している人を見つけて、プログラムをペアリングします。
ベスト プラクティス IMHO: プロセスだからという理由だけでなく、実際的なことを行います。アプリケーションを書くことの目的は何なのかを忘れないでください。ビジネスの世界では、それはテストを書くことではありません。誤解しないでほしいのですが、彼らにはそれぞれの居場所がありますが、それが目標であってはなりません。
メトリックは、IMHO、ここからそこに到達するための最良の方法です。コードがどの程度カバーされているかを追跡し、コミットごとにコードの複雑さのデルタを保持し、コードの変更を監視するテストランナーを使用し、対応するテストを常に再実行します。すべてのツールがうまく機能するように、テストの長さが数行を超えないようにしてください。また、月に 1 回、休みを取ってミューテーション テスターでコードを実行することをお勧めします。その日は、テストの作成のみに専念する必要があります。まだ適切なTDDを行っていない場合、これらすべてが苦痛をもたらします。痛みから学べば、すぐに正しくできるようになります。
そして、テストの目的を見失うことはありません: 望ましい動作を説明するため。それらは実行可能な仕様です。(これが、私がCucumberを気に入っている理由でもあります。これで、PHB にテストを書いてもらうことができます!まあ、それほど良くはないかもしれませんが、近いです!)
私は数年間 TDD を行ってきましたが、最近は設計と開発を推進する BDD の方法をより詳しく調べ始めています。私が BDD を始めるのに役立つリソースは、何よりもまず Dan North のブログ (BDD の「創設者」) でした。BDDの紹介をご覧ください。また、behaviour-driven.orgには「公式の」BDD Wiki があり、読む価値のある優れた投稿がいくつかあります。
BDD を使い始めたときに本当に難しいと感じた (そして今でも少し難しいと感じている) ことの 1 つは、これらのシナリオを定式化して BDD に適したものにする方法です。Scott Bellware は BDD (または、彼が好んで使用する Context-Specification) に精通した人物であり、Code Magazine の彼の記事Behavior-Driven Developmentは、BDD の考え方とユーザー ストーリーの作成方法を理解するのに大いに役立ちました。
また、Rob Coneryによる TekPub スクリーンキャストBehavior-driven Design with Specflowもお勧めします。BDD と、C# で BDD を実行するのに非常に適したツール (SpecFlow) の優れた紹介です。
TDD のリソースに関しては、ここには既に多くの優れた推奨事項があります。しかし、私が本当にお勧めできる本をいくつか指摘したいだけです。
単体テストを開始するには、それを正しく行う方法を読み、最後にチームに TDD の方法を教えて参加させます。私の経験では、チーム全体で単体テストを行うことほど重要なことはありません。
また、適切なビルド プロセスも必要です。コードをビルドしてテストを実行するビルド サーバーを使用します。TeamCity を使用することをお勧めします (制限付きで無料)。
適切な単体テストを正しく行う方法を学ぶのは難しい部分です。その一部は (単体テストを続ける限り) 自分で学び、残りはインターネットを検索して学ぶことができます。
開発の一環として単体テストを作成しないと、目標を達成したことがわかります。
アジャイルとは、特定の方法で完全に完売していないことを意味することを忘れないでください。TDD の利点に見合わない作業をしている場合 (Swing インターフェースでの試行錯誤の編集など) は、TDD を使用しないでください。
ナイキから引用するには:JUSTDOIT。
2番目のアドバイス-他人のインターフェースに頼らないでください。常に、各クラスのレベルで、存在したいインターフェイスに書き込みます。必要に応じて、実際の実装へのアダプタを書き込みます。
また、メソッドの戻り値を避け、関数呼び出しではなくメッセージパッシングの観点からコードを考えると便利だと思います。
YMMV。
TDD がテストに関するものではないことを本当に表明した人は誰もいないと思います。TDD とは、動作を変更する小さな変更を行う前に、期待される動作を表現することです。これにより、デザインが大幅に改善され、これまで経験したことのない方法で焦点を合わせることができます。将来のリファクタリングを保護するテストと 90% のカバレッジを無料で取得できます。
それを学ぶために、私は提案します(他の人が言ったことを要約し、私自身のものを追加します):
光が見えるようになる前に、ボウリングの型を自分で約20回(1回約30分)練習しました。ここでボブおじさんの説明を分析することから始めました 。解決策や議論など、codingdojo.org サイトには多数のカタがあります。それらを試してみてください!
1 年前、私は TDD を行う方法をほとんど知りませんでした (しかし、本当にやりたかった (どれだけ苛立たしいことか))、BDD について聞いたことがありませんでした. 私はJavaではなく.Net開発環境にいましたが、「F5 - 実行」ボタンをマクロに置き換えて、機能/シナリオまたは仕様に応じてCucumber (BDD)またはMBUnit (TDD)を実行しました。可能であれば、デバッガーはありません。デバッガーを使用する場合は、jar に $1 (冗談 (一種))。
そのプロセスはとても素晴らしいものです。私たちがさらに使用しているフレームワークは、幸運にも出会い、そこから情報を吸収してきた The Oracle によるもので、彼/私たちが使用しているフレームワークは MavenThought です。
すべては BDD から始まります。私たちの BDD は、鉄のルビーの上にキュウリを乗せたものです。
特徴:
シナリオ: ....
私が何かをするとしたら... 私が何か他のことをすると... 素晴らしいことが起こります...
シナリオ: ...
それ自体は単体テストではありませんが、シナリオごとに機能を駆動し、次に単体 (テスト) 仕様を駆動します。つまり、シナリオから開始し、シナリオで完了する必要がある各ステップで、TDD を駆動します。 .
また、私たちが使用してきた TDD は、ある意味では一種の BDD です。SUT (テスト対象のシステム) が必要とする動作を調べ、仕様 (クラス「テスト」ファイル) ごとに 1 つの動作が指定されているためです。
例:
1 つの動作の仕様を次に示します。テスト対象のシステムが作成されるとき。
プロパティが変更されたときの別の動作の仕様 (C# When_blah_happens クラス ファイル) がもう 1 つありますが、それは別のファイルに分けられています。
using MavenThought.Commons.Testing;
using SharpTestsEx;
namespace Price.Displacement.Module.Designer.Tests.Model.Observers
{
/// <summary>
/// Specification when diffuser observer is created
/// </summary>
[ConstructorSpecification]
public class When_diffuser_observer_is_created
: DiffuserObserverSpecification
{
/// <summary>
/// Checks the diffuser injection
/// </summary>
[It]
public void Should_return_the_injected_diffuser()
{
Sut.Diffuser.Should().Be.SameInstanceAs(this.ConcreteDiffuser);
}
}
}
これはおそらく SUT の最も単純な動作です。この場合、作成時に Diffuser プロパティが注入された拡散器と同じである必要があるためです。この場合、ディフューザーはコア/ドメイン オブジェクトであり、インターフェイスのプロパティ通知がないため、モックの代わりにコンクリート ディフューザーを使用する必要がありました。95% の確率で、実際のものを注入する代わりに、Dep() のようなすべての依存関係を参照します。
多くの場合、複数の [It] Should_do_xyz() があり、場合によっては、最大 10 行のスタブなど、かなりの設定が必要になることもあります。これは、その仕様に GivenThat() または AndGivenThatAfterCreated() がない非常に単純な例です。
各仕様のセットアップでは、通常、仕様のいくつかのメソッドをオーバーライドするだけで済みます。
GivenThat() ==> これは、SUT が作成される前に発生します。
CreatSut() ==> StructureMap を使用して sut の自動モック作成を行い、90% の時間でこれをオーバーライドする必要はありませんが、コンストラクターで Concrete を注入する場合は、これをオーバーライドする必要があります。
AndGivenThatAfterCreated() => これは、SUT が作成された後に発生します。
WhenIRun() => [ConstructorSpecification] でない限り、これを使用して、SUT に指定している動作である 1 行のコードを実行します。
また、同じ SUT の 2 つ以上の仕様に共通の動作がある場合は、それを基本仕様に移動します。
仕様を実行するために私がしなければならないことは、その名前を強調表示することです。たとえば、「When_diffuser_observer_is_created」を強調表示して F5 を押します。私の場合、F5 は、Cucumber の場合は test:feature[tag]、または test:class[SUT] のいずれかの Rake タスクを実行します。デバッガーを実行するたびに、コードが作成されないため、デバッガーを実行するのは理にかなっています (ああ、1 ドル (冗談) の費用がかかります)。
これは、TDD で動作を指定し、非常に単純な SUT と単純な仕様を持つ、非常にクリーンな方法です。カウボーイ コーダーになりたいと思って、ハードな依存関係などでくだらない SUT を書こうとすると、TDD を実行しようとする苦痛を感じ、うんざりしたり、あきらめたり、弾丸を噛んだりして正しく実行したりします。
これが実際の SUT です。少し工夫して、PostSharp を使用して、ディフューザーで変更されたプロパティ通知を追加します。したがって、Post.Cast<>. 繰り返しになりますが、モックではなくコンクリートを注入したのはそのためです。とにかく、別の仕様で定義されている欠落している動作を見ることができるように、ディフューザーで何かが変更されたときです。
using System.ComponentModel;
using MavenThought.Commons.Events;
using PostSharp;
using Price.Displacement.Core.Products;
using Price.Displacement.Domain;
namespace Price.Displacement.Desktop.Module.Designer.Model.Observers
{
/// <summary>
/// Implementation of current observer for the selected product
/// </summary>
public class DiffuserObserver : AbstractNotifyPropertyChanged, IDiffuserObserver
{
/// <summary>
/// gets the diffuser
/// </summary>
public IDiffuser Diffuser { get; private set; }
/// <summary>
/// Initialize with a diffuser
/// </summary>
/// <param name="diffuser">The diffuser to observe</param>
public void Initialize(IDiffuser diffuser)
{
this.Diffuser = diffuser;
this.NotifyInterface().PropertyChanged += (x, e) => this.OnPropertyChanged(e.PropertyName);
}
/// <summary>
/// Gets the notify interface to use
/// </summary>
/// <returns>The instance of notify property changed interface</returns>
protected INotifyPropertyChanged NotifyInterface()
{
return Post.Cast<Diffuser, INotifyPropertyChanged>((Diffuser)Diffuser);
}
}
}
結論として、この BDD / TDD スタイルの開発は揺るぎません。1年かかりましたが、私は生き方として完全に改宗しています。私は自分でこれを学んだことはなかったでしょう。The Oracle http://orthocoders.com/からすべてをピックアップしました。
赤または青の錠剤、選択はあなた次第です。