テスト駆動開発を行う方法


15

アプリケーション開発の経験はたった2年です。この2年間で、開発に対する私のアプローチは次のようになりました。

  1. 要件を分析する
  2. Identity Coreコンポーネント/オブジェクト、必要な機能、動作、プロセス、およびそれらの制約
  3. クラスの作成、クラス間の関係、オブジェクトの動作と状態の制約
  4. 機能を作成し、要件に従って動作上の制約を使用して処理する
  5. アプリケーションを手動でテストする
  6. 要件の変更によりコンポーネント/機能が変更された場合、アプリケーションを手動でテストします

最近、TDDを紹介し、開発されたコードが存在する強力な理由があり、展開後の問題の多くが軽減されるため、これは開発を行うのに非常に良い方法であると感じました。

しかし、私の問題は、最初にテストを作成できないことです。むしろ、実際にコンポーネントを作成する前に、コンポーネントを特定し、テストを作成しています。私の質問は

  1. 私はそれをやっていますか?そうでない場合は、正確に変更する必要があります
  2. 書いたテストで十分かどうかを確認する方法はありますか?
  3. 1 + 1 = 2に相当する可能性のある非常に単純な機能のテストを記述するのは良い習慣ですか、それとも単なるやりすぎですか?
  4. 機能を変更し、それに応じて要件が変更されたかどうかをテストするのは良いですか?

2
「コンポーネントを特定し、実際にコンポーネントを作成する前にそれらのテストを作成しています。」:これは正しいと思います。まず、システムの大まかなアーキテクチャを特定し、コーディングを開始します。コーディング(TDD)中に、個々のコンポーネントの詳細を計算し、場合によっては修正できるアーキテクチャの問題を発見します。しかし、事前の分析なしにコーディングを開始しないでください。
ジョルジオ14年

また、TDD 実行せずに自動化された単体/統合テスト検討することもできます。この2つはしばしば混同されますが、同じものではありません。
アンドレスF.

回答:


19

私はそれをやっていますか?そうでない場合は、正確に変更する必要があります

それはちょうどその簡単な説明から言うのは難しいのですが、私はありません、あなたがしている、と思われるではない右のそれをやって。注:あなたがしていることは機能しない、または何らかの形で悪いと言っているわけではありませんが、TDDをしているわけではありません。中央の「D」は「駆動」を意味し、テストはすべて、開発プロセス、コード、設計、アーキテクチャ、すべてを駆動します

テストは、何を書くべきか、いつ書くべきか、次に書くべきもの、いつ書くのをやめるかを教えてくれます。彼らはデザインとアーキテクチャを教えてくれます。(設計とアーキテクチャは、リファクタリングを通じてコードから生まれます。)TDDはテストに関するものではありません。最初にテストを書くことすら必要ではありません。TDDはテストにあなたを駆り立てさせることです。

実際にコードを書き留めるのか、完全に肉付けするのかは問題ではありません。頭の中にコードのスケルトンを書き、そのコードのテストを書きます。それはTDDではありません。

その習慣を手放すのは難しいです。本当に、本当に難しい。経験豊富なプログラマーにとっては特に難しいようです。

Keith Braithwaiteは、TDD As As You Meant Itと呼ぶエクササイズを作成しました。これは一連のルールで構成されており(ボブ・マーティンおじさんのTDDの3つのルールに基づいていますが、より厳密です)、厳密に従う必要があり、TDDをより厳密に適用するように設計されています。ペアプログラミング(ペアがルールを破っていないことを確認できるようにする)とインストラクターが最適です。

ルールは次のとおりです。

  1. 解決策の方向を指していると思われる、できる限り小さいテストを1つだけ正確に記述します
  2. 失敗するのを見てください。コンパイルの失敗は失敗としてカウントされます
  3. testメソッドでできる限り少ない実装コードを記述して、(1)からテストをパスします。
  4. 重複を除去するためにリファクタリングし、そうでなければ設計を改善するために必要に応じて。これらの動きの使用については厳しくしてください:
    1. 新しいメソッドが必要です。リファクタリングの時間まで待機してから、次のいずれかを実行して、新しい(テスト以外の)メソッドを作成します。
      • 推奨:テストクラスで新しいメソッドを作成するために、(3)に従って作成された実装コードでメソッドを抽出する、または
      • 必要な場合:(3)に従って実装コードを既存の実装メソッドに移動する
    2. 新しいクラスが必要です。リファクタリング時間まで待機してから、テスト以外のクラスを作成して、Moveメソッドの宛先を提供し、他の理由はありません
    3. Moveメソッドを実行することにより、実装クラスにメソッドを設定します。他の方法は使用しません。

通常、これは、「デザインがどうあるべきかを頭の中で想像し、そのデザインを強制するためのテストを書いて、書く前に既に構想したデザインを実装する」というよくある「擬似TDD法」とは非常に異なるデザインにつながりますテスト」。

疑似TDDを使用Boardした三目並べゲームのようなものを実装する場合、通常、3 x 3のIntegersの配列を持つクラスを含む非常によく似たデザインになります。そして、プログラマの少なくとも一部は、「必要になることを知っている」または「テストを書くために何かを必要とする」ため、テストなしでこのクラスを実際に作成します。ただし、その同じグループにTDDを適用するように強制すると、多くの場合、非常にさまざまな非常に異なるデザインになり、多くの場合、リモートに類似したものも使用しませんBoard

書いたテストで十分かどうかを確認する方法はありますか?

すべてのビジネス要件をカバーする場合。テストは、システム要件のエンコードです。

1 + 1 = 2に相当する可能性のある非常に単純な機能のテストを記述するのは良い習慣ですか、それとも単なるやりすぎですか?

繰り返しになりますが、機能をテストすることはありません。テスト用の機能を作成します。テストに合格するための機能が簡単であることが判明した場合、それは素晴らしいことです!システム要件を満たしただけで、そのために一生懸命働く必要さえありませんでした!

機能を変更し、それに応じて要件が変更されたかどうかをテストするのは良いですか?

いいえ。その逆です。要件が変更された場合、その要件に対応するテストを変更し、失敗するのを確認してから、コードを変更して合格させます。テストは常に最初に行われます。

これをするのは難しいです。ある種の「筋肉の記憶」を築き、締め切りが迫り、プレッシャーにさらされている場合、それについて考える必要さえないためには、数十、おそらく数百時間の慎重な練習が必要です。 、そしてこれを行うことは、最も速くて最も自然な作業方法になります。


1
確かに非常に明確な答えです!実用的な観点から、TDDを実践するとき、柔軟で強力なテストフレームワークは非常に楽しいです。TDDには依存しませんが、アプリケーションをデバッグするには、テストを自動的に実行する機能が非常に役立ちます。TDDを開始するには、非対話型プログラム(UNIXスタイル)がおそらく最も簡単です。これは、プログラムの終了ステータスと出力を予想と比較することでユースケースをテストできるためです。このアプローチの具体例は、OCaml用のGasolineライブラリにあります。
マイケルルバルビエグリューネ

4
「同じグループにTDDをあたかも自分の意のままに適用するように強制すると、多くの場合、非常に多様な非常に異なるデザインになり、多くの場合、ボードに似たものを採用しません」 。それが良いことであるかどうかはまったくわかりませんし、実装が新しい人にとって非常に直感に反するように聞こえるので、保守の観点からは悪いことさえあります。この実装の多様性が良いことなのか、少なくとも悪くないのかを説明してもらえますか?
ジム・クレイ

3
+1答えは、TDDを正しく説明しているという点で優れています。ただし、TDDが欠陥のある方法論である理由も示しています。特にアルゴリズムの問​​題に直面した場合は、慎重な検討と明示的な設計が必要です。ドメイン知識を持たないふりをしてTDDを「ブラインドで」(TDDが規定するように)行うと、不必要な困難と行き止まりにつながります。悪名高い数独ソルバーの大失敗をご覧ください(短いバージョン:TDDはドメインの知識を打ち負かすことはできません)。
アンドレスF.

1
チックタックつま先のための「擬似TDD」を行うときに、彼らが作成することによって開始:@AndresFは:実際には、ブログの記事は、あなたがそれを意味している場合には、TDD Asを行うときにキースが作った経験をエコーするようだリンクBoardAとクラスをintsの3x3配列(またはそのようなもの)。一方、TDDAYYMIを強制する場合、ドメインの知識を取得するためのミニDSLを作成することがよくあります。もちろん、それは単なる逸話です。統計的および科学的に健全な研究はいいでしょうが、このような研究でよくあることですが、それらは小さすぎるか高価すぎるかのいずれかです。
ヨルグWミットタグ

@JörgWMittag私があなたを誤解した場合、私を修正しますが、あなたはロン・ジェフリーズが「疑似TDD」をしていたと言っていますか?それは「真のスコットランド人ではない」誤fallの一形態ではないでしょうか?(より科学的な研究の必要性についてはあなたに同意します;私がリンクしたブログは、TDD使用の特定のインスタンスの壮大な失敗についてのカラフルな逸話です。この方法とその申し立てられた利点について真の分析を行うことができます)。
アンドレスF.

5

開発アプローチを「トップダウンのみ」のプロセスとして説明します。より高い抽象化レベルから始めて、詳細にどんどん進みます。TDDは、少なくとも人気のある形式では、「ボトムアップ」技術です。そして、ほとんどが「トップダウン」で作業している人にとって、「ボトムアップ」で作業することは実際には非常に珍しいことです。

それでは、開発プロセスにより多くの「TDD」をどのように取り入れることができますか?最初に、実際の開発プロセスは、上で説明したように必ずしも「トップダウン」ではないことを前提としています。ステップ2の後、おそらく他のコンポーネントから独立したいくつかのコンポーネントを識別しているでしょう。最初にこれらのコンポーネントを実装することを決定する場合があります。これらのコンポーネントのパブリックAPIの詳細は、おそらく要件だけではなく、設計の決定にも従います。これがTDDを開始できるポイントです。コンポーネントをどのように使用するのか、実際にAPIをどのように使用するのかを想像してください。そして、このようなAPIの使用法をテスト形式でコーディングし始めるとき、TDDから始めたところです。

第二に、最初に他の存在しないコンポーネントに依存するコンポーネントから始めて、より多くの「トップダウン」でコーディングする場合でもTDDを実行できます。学ぶ必要があるのは、これらの他の依存関係を最初に「模擬」する方法です。これにより、下位コンポーネントに進む前に、上位コンポーネントを作成してテストできます。トップダウン方式でTDDを実行する非常に詳細な例は、Ralf Westphalのこのブログ投稿にあります。


3

私はそれをやっていますか?そうでない場合は、正確に変更する必要があります

あなたは元気です。

書いたテストで十分かどうかを確認する方法はありますか?

はい、テスト/コードカバレッジツールを使用します。マーティンファウラーは、テストカバレッジに関するいくつかの良いアドバイスを提供しています。

1 + 1 = 2に相当する可能性のある非常に単純な機能のテストを記述するのは良い習慣ですか、それとも単なるやりすぎですか?

一般に、いくつかの入力が与えられたときに何らかの結果が得られると予想される関数、メソッド、コンポーネントなどは、単体テストの適切な候補です。ただし、(エンジニアリング)ライフのほとんどの場合と同様に、トレードオフを考慮する必要があります。ユニットテストを記述することで労力が相殺され、長期的にはより安定したコードベースが得られますか?一般的に、最初に重要/重要な機能のテストコードを記述することを選択します。後でコードのテストされていない部分に関連するバグがある場合は、さらにテストを追加してください。

機能を変更し、それに応じて要件が変更されたかどうかをテストするのは良いですか?

自動テストを行うことの良い点は、変更が以前のアサーションに違反するかどうかをすぐに確認できることです。要件が変更されたためにこれが予想される場合、はい、テストコードを変更しても構いません(実際、純粋なTDDでは、要件に従ってテストを最初に変更し、新しい要件を満たすまでコードを採用します)。


コードカバレッジは非常に信頼できる尺度ではない場合があります。カバレッジの%を強制すると、通常、多くの不要なテスト(すべてのパラメーターnullチェックなどのテスト-価値をほとんど付加しないテストのためのテスト)が発生し、開発時間が無駄になりますが、コードのテストは困難ですパスはまったくテストされない可能性があります。
ポール14年

3

最初にテストを書くことは、ソフトウェアを書くためのまったく異なるアプローチです。テストは、適切なコード機能検証(すべて合格)のツールであるだけでなく、設計を定義する力でもあります。テストカバレッジは有用なメトリックですが、それ自体が目標であってはなりません。TDDの目標は、コードカバレッジの良い割合を達成することではなく、コードを記述する前にテストの可能性について考えることです。

最初にテストの作成に問題がある場合は、TDDの経験がある人とペアプログラミングのセッションを行うことを強くお勧めします。そうすることで、アプローチ全体についての「考え方」を実際に体験できます。

もう1つの良いことは、TDDを使用してソフトウェアを開発しているオンラインビデオを視聴することです。私がかつてTDDを紹介していたのは、James ShoreのLet's Play TDDでした。見てみると、緊急設計の仕組み、テストの作成中にどのような質問を自問すべきか、新しいクラスとメソッドがどのように作成され、リファクタリングされ、反復されるかがわかります。

書いたテストで十分かどうかを確認する方法はありますか?

これは間違った質問だと思います。TDDを行うとき、ソフトウェアを記述する方法としてTDDと緊急設計を選択しました。追加する必要がある新しい機能が常にテストで始まる場合、それは常にそこにあります。

1 + 1 = 2に相当する可能性のある非常に単純な機能のテストを記述するのは良い習慣ですか、それとも単なるやりすぎですか?

明らかにそれは依存します、あなたの判断を使用してください。メソッドがパブリックAPIの一部ではない場合、パラメーターnullチェックのテストを記述しない方がよいのですが、そうでない場合、Add(a、b)メソッドが実際にa + bを返すことを確認しないのはなぜですか?

機能を変更し、それに応じて要件が変更されたかどうかをテストするのは良いですか?

繰り返しますが、コードに新しい機能を変更または追加するとき、新しいテストを追加するか、要件が変更されたときに既存のテストを変更するかに関係なく、テストから始めます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.