TDDを行うときにすべてのテストを一度に書いてみませんか?


55

TDDの赤-緑-リファクタリングサイクルは十分に確立され、受け入れられています。失敗した単体テストを1つ作成し、できるだけ単純に合格させます。クラスに対して失敗する多数の単体テストを記述し、それらすべてを一度に合格させることに対するこのアプローチの利点は何ですか。

テストスイートは、リファクタリング段階で誤ったコードを記述したり、ミスを犯したりすることからあなたを保護します。クラス(またはモジュール)のすべてのテストを「ブレインダンプ」の形式として最初に記述して、予想されるすべての動作を一度に書き留めることが簡単な場合があります。


20
あなたのために最適なことをしてください(実験の後)。盲目的にドグマに従うことは決して良いことではありません。
マイケルボルグワード

6
私が書いていることをあえて全て一度にすべてのアプリのコードを書くように一度くらいのテストを。
マイケルハーレン

1
@MichaelHarenクラス(または機能モジュール)のすべてのテスト、混乱のためごめんなさい
RichK

3
「ブレインダンプ」の問題に対処する:いくつかの異なる特定の入力テストの必要性を認識したときに、テスト/コーディングにポイントがあり、気が散る前にその実現の明快さを利用したい傾向があります。コーディングの詳細。私は通常、個別のリスト(例:Mylyn)を維持するか、テストするために覚えておきたいテストクラスのコメントのリスト(例:// nullケースをテストする)で管理します。ただし、一度に1つのテストのみをコーディングし、代わりに体系的にリストを作成します。
サムゴールドバーグ

1
なぜ誰もこれに言及していない理由はわかりませんが、すべてのテストを一度に書くことはできません。事前にすべてのテストを記述することは、BDUFを行うこととまったく同じです。そして、歴史はBDUFについて何を教えてくれましたか?それはほとんど機能しません。
ソンゴ

回答:


50

テスト駆動設計とは、コードではなく、APIを正しくすることです。

最も単純な失敗テストを最初に書くことの利点は、API(本質的にはオンザフライで設計している)を可能な限り単純にすることです。前もって。

将来の使用(次に作成するテスト)は、より複雑なケースに対処する次善の設計ではなく、最初の単純な設計から行われます。


素晴らしい点!コードのテストに没頭することもあるため、最初のテストを作成する前に、APIとドメインモデルの重要性を無視することもあります。
maple_shaft

テスト駆動開発の意図に実際に対処するための+1 。
ジョシュアドレイク

76

1つのテストを書くとき、1つのことに集中します。
多くのテストでは、多くのタスクに注意を向けるので、良いアイデアではありません。


8
誰がこれに反対票を投じますか?
CaffGeek

6
@Chad私は反対票ではありませんでしたが、この答えは明白なものを見逃していると思います。テスト駆動開発とは、テストを使用してコードの設計を推進することです。テストだけでなく、デザインを進化させるために、テストを個別に作成します。それがテスト成果物のみである場合、これは良い答えですが、いくつかの重要な情報が欠落しています。
ジョシュアドレイク

7
私はこれを支持しませんでしたが、私はそれについて考えました。複雑な質問に対する答えはあまりにも短いです。
マークウェストン

2
一度に1つのことに集中するために+1すると、マルチタスク機能が過大評価されます。
cctan

これはおそらく最も簡単な答えです。
DNA

27

単体テストを記述する際の困難の1つは、コードを記述していることであり、それ自体が潜在的にエラーになりやすいことです。また、実装コードを作成する際のリファクタリング作業の結果として、後でテストを変更する必要が生じる可能性もあります。TDDを使用すると、テストに少し夢中になり、実装がプロジェクトの過程で成熟するにつれて、本質的に「テストされていない」多くのテストコードを書き直す必要があることに気付く可能性があります。この種の問題を回避する1つの方法は、一度に1つのことを行うことに集中することです。これにより、テストに対する変更の影響を最小限に抑えることができます。

もちろん、これはテストコードの記述方法に大きく依存します。個々のメソッドごとに単体テストを書いていますか、それとも機能/要件/動作に焦点を当てたテストを書いていますか?別のアプローチとしては、適切なフレームワークでビヘイビアドリブンアプローチを使用し、あたかも仕様であるかのようにテストを書くことに焦点を合わせることができます。これは、BDD方式を採用するか、TDDをより正式に使用したい場合はBDDテストを採用することを意味します。あるいは、完全にTDDパラダイムに固執する一方で、テストの記述方法を変更して、個別にテストメソッドに完全に焦点を当てるのではなく、実装する要件機能の仕様を満たす手段として、より一般的に動作をテストします。

特定のアプローチに関係なく、上記で説明したすべてのケースでは、テストファーストアプローチを使用しているため、単純に脳を素敵なテストスイートにダウンロードするのは魅力的かもしれませんが、絶対に必要以上のことをする誘惑。新しいテストスイートを開始しようとするたびに、YAGNIを自分自身に繰り返し始め、時にはコードのコメントにそれをスローして、すぐに重要なことに集中し続けることを思い出させ、私が実装しようとしている機能の要件。Red-Green-Refactorに固執すると、これを確実に実行できます。


テストコードの記述方法の違いを指摘していただけたことを嬉しく思います。単一の関数またはメソッドへの入力の現実的な可能性をすべて網羅する単一のマスターユニットテストを作成したい人もいます。その他のユニットテストでは、よりBDDアプローチを採用しています。テストのスイート全体を作成することが重要かどうかを判断する際に、この区別は重要です。素晴らしい洞察力!
maple_shaft

17

これを行うことで、TDD のプロセスを見逃すと思います。最初にすべてのテストを記述するだけでは、TDDを使用した開発プロセスを実際に行うことはありません。どのテストが必要かを前もって推測しているだけです。これは、コードの開発時に一度に1つずつ実行する場合、最終的に作成するテストとは非常に異なるテストのセットになります。(あなたのプログラムが本質的に些細なものにならない限り。)


1
ほとんどのビジネスおよびエンタープライズアプリケーションは本質的に技術的にささいなものであり、ほとんどのアプリケーションがビジネスおよびエンタープライズであると見なしているため、ほとんどのアプリケーションも本質的にささいなものです。
maple_shaft

5
@maple_shaft-テクノロジーは些細なことかもしれませんが、ビジネスルールはそうではありません。さまざまな要件を持ち、シンプルでエレガントな、それほどではない、ミニマリズムのデザインについて一部のBSを聞くことを拒否する5人のマネージャー向けのアプリを作成してみてください。
ジェフ

5
@JeffO 1)BSではありません。2)エレガントなミニマリストデザインには、優れたソフトウェア開発スキルが必要です。3)無駄な時間を1週間に5分も持たない5人の異なるマネージャーの要件を緩和し、それでもミニマルなデザインを実現するには、優秀なソフトウェア開発者が必要です。 プロのヒント:ソフトウェア開発は単なるコーディングスキルではなく、交渉、会話、所有権の取得です。あなたはアルファ犬にならなければならないし、時々かむ。
maple_shaft

1
私が正しく理解している場合、この答えは質問を懇願しています。
コンラッドルドルフ

1
@maple_shaftジェフOがコメントで得ていたものだと思いますか?
-ZweiBlumen

10

「ブレインストーム」の最中に、考えられるすべてのテストを「書き込み」ますが、各テストは、テストを説明する1つのコメントとして書き込みます。

次に、1つのテストをコードに変換し、コンパイルして合格するように作業を行います。多くの場合、自分がしたと思ったすべてのテストが必要ではない、または別のテストが必要であると判断します。この情報は、テストをパスするためのコードの記述からのみ得られます。

問題は、テストするメソッドとクラスを作成するまで、コードでテストを記述できないことです。そうしないと、一度に1つのテストで作業できるようになる多くのコンパイラエラーが発生します。

テストが「英語」で書かれているときに仕様フローのようなシステムを使用している場合、単一のテストを作成するのではなく、時間がある間に顧客に一連のテストに同意してもらうことができます。


1
はい、すべてのテストを最初にコーディングする際の問題を指摘する上記の回答に同意しますが、現在のメソッドがコードなしで一連のテスト記述としてどのように動作するかについての全体的な理解をダンプすることは非常に役立ちます。これらを書き留めるプロセスは、これから書き込もうとしているコードに何が必要かを完全に理解しているかどうか、そして私が考えていないエッジケースがあるかどうかを明らかにする傾向があります。最初のテストをコーディングする方がはるかに快適で、メソッドがどのように機能するかについての「概要」を概説した後、合格します。
マークウェストン

10

TDDの背後にある考え方は、迅速な反復です。

コードを作成する前に作成しなければならないテストが大量にある場合、コードを繰り返しリファクタリングすることは困難です。

コードを簡単にリファクタリングしないと、TDDの多くの利点が失われます。


5

TDDと私の(制限)の経験では、私がいることを伝えることができ、すべての私は、一度に1つのテストを書くの規律を破ってきた時は、物事がひどく行っています。陥りやすいトラップです。「ああ、その方法は取るに足らないものです」とあなたは思うので、「これら2つの関連するテストをノックアウトして、動き続けます。」まあ、何だと思う?見かけほど簡単なものはありません。このtrapに陥るたびに、私は簡単だと思っていたものをデバッグすることになりましたが、奇妙なコーナーケースがあることが判明しました。そして、私は一度にいくつかのテストを書き続けたので、バグの場所を突き止めるのは大変な仕事でした。

情報のブレーンダンプが必要な場合、多くのオプションがあります。

  • ホワイトボード
  • ユーザーストーリー
  • コメント
  • 古き良きペンと紙

このリストのどこにもコンパイラーがないことに注意してください。:-)


5

コードを記述する前に、コードがどのように見えるかを知っていることを前提としています。TDD / BDDは、QAプロセスと同じくらい設計/発見プロセスです。特定の機能について、その機能が満たされていることを確認する最も簡単なテストを作成します(機能の複雑さのためにいくつかのテストが必要になる場合があります)。最初に作成するテストには、動作中のコードがどのように見えるかを想定してロードされます。それをサポートするためにコードの最初の行を書く前にテストスイート全体を書くならば、あなたは未検証の仮定の大部分を作っています。代わりに、1つの仮定を記述して検証します。次に、次を書きます。次の仮定を検証するプロセスでは、以前の仮定を中断して、最初の仮定を変更して現実に一致させるか、現実を変更して最初の仮定を適用する必要があります。

科学的なノートの理論として書く各ユニットテストを考えてください。ノートに記入すると、理論を証明し、新しい理論を形成します。新しい理論を証明すると、以前の理論が反証されることがあるため、修正する必要があります。一度に20の理論を証明しようとするよりも、一度に1つの理論を証明する方が簡単です。


TDDは、コードを作成する前に、ほんの少しずつコードがどのように見えるかを知っていると想定しています。
マイケルショー

4

TDDは非常に反復的なアプローチであり、(私の経験では)実際の開発方法により適しています。通常、このプロセス中に私の実装は徐々に形作られ、各ステップはテストのためのさらなる質問、洞察、およびアイデアをもたらす可能性があります。これは、実際のタスクに集中するのに理想的であり、任意の時点で短期間の記憶に限られた数の物だけを保持する必要があるため、非常に効率的です。これにより、ミスの可能性が減少します。

あなたのアイデアは、基本的には、Big Test Up Frontのアプローチであり、IMHOの方が扱いが難しく、無駄が多くなる可能性があります。作業の途中でアプローチが良くないことに気付いた場合、APIに欠陥があり、最初からやり直すか、代わりにサードパーティのライブラリを使用する必要がありますか?それから、テストを前もって書くことに費やされた多くの仕事は無駄な努力になります。

それは、これがあなたのために働くなら、結構です。固定された詳細な技術仕様、密接に経験しているドメイン、および/またはかなり小さなタスクで作業している場合、必要なテストケースのほとんどまたはすべてを準備し、実装を明確にすることができると想像できます開始。それから、すべてのテストを一度に書くことから始めるのが理にかなっているかもしれません。長期的に見て生産性が向上するという経験があるなら、ルールブックについてあまり心配する必要はありません:-)


4

1つのことを考えるだけでなく、TDDの1つのパラダイムは、テストに合格するために可能な限り少ないコードを記述することです。一度に1つのテストを記述すると、そのテストに合格するのに十分なコードを記述するためのパスを簡単に確認できます。一連のテストに合格すると、小さなステップでコードに到達するのではなく、すべてを一度に合格させるために大きな飛躍をする必要があります。

コードを書いてすべてを「一度に」渡すように制限せずに、一度に1つのテストに合格するだけのコードを書くと、それでもうまくいくかもしれません。ただし、必要なだけより多くのコードを書くだけでなく、より多くの規律が必要になります。あなたがその道を開始すると、あなた自身がテストをすることができ、記述よりも多くのコードの書き込みに開いたままテストされていない、少なくともそれはテストで、おそらくそれを必要としないという意味で駆動されていないという意味では、 (または実行)テストによって。

コメント、ストーリー、機能仕様など、メソッドが行うべきことを完全に受け入れます。ただし、これらを一度に1つずつテストに変換するのを待ちます。

テストを一度に書くことで見逃すことができるもう1つのことは、テストに合格すると他のテストケースについて考えるよう促すことができる思考プロセスです。既存のテストのバンクがない場合、最後に合格したテストのコンテキストで次のテストケースを考える必要があります。私が言ったように、メソッドが何をすべきかについて良いアイデアを持っていることは非常に良いですが、多くの場合、アプリオリを考慮していなかったが、テスト。まだ持っていない新しいテストを書くことができるかどうかを明確に考えない限り、これらを見逃す危険性があります。


3

私は、(失敗した)テストを書いた開発者が、それらをパスさせるために必要なコードを実装する開発者とは異なるプロジェクトに取り組みましたが、本当に効果的であることがわかりました。

その場合、現在の反復に関連するテストのみが1回書き込まれます。したがって、このようなシナリオでは、あなたが提案することは完全に可能です。


2
  • その後、一度に多くのことに集中しようとします。
  • すべてのテストに合格するように実装している間、アプリケーションの作業バージョンはありません。たくさん実装しなければならない場合、長期にわたって動作するバージョンはありません。

2

Red-Green-Refactorサイクルは、TDDを初めて使用する開発者向けのチェックリストです。私はあなたがそれに従うべき時とあなたがそれを破ることができるときを知るまで、このチェックリストに従うことは良い考えだと思います(つまり、知るまでstackoverflowでこの質問をする必要はありません:)

10年近くTDDを行ったことがありますが、実稼働コードを書く前に、失敗したテストを何度も書くことはめったにありません。


1

外部の利害関係者が実行可能な仕様を持っているBDDについて説明しています。これは、事前に指定された仕様(たとえば、フォーマット仕様、産業標準、またはプログラマーがドメインの専門家ではない場合)がある場合に役立ちます。

通常のアプローチは、徐々に受け入れテストをカバーすることです。これは、プロジェクトマネージャーと顧客に見える進捗状況です。

通常、このテストはCucumber、FitnesseなどのBDDフレームワークで指定および実行されます。

ただし、これは単体テストと混同するものではありません。ユニットテストは、実装関連のアーティファクトであるテスト対象項目に重点を置いた、多くのAPI関連のエッジケース、初期化の問題など、実装の詳細に非常に近いものです。

赤緑リファクタリングには多くの利点があり、それらを前もってタイプすることで期待できる唯一の利点は損益分岐点です。


1

一度に1つのテスト:主な利点は、1つのことに集中することです。深さ優先の設計を考えてください。高速フィードバックループを使用して、深く深く集中できます。ただし、問題全体の範囲を見逃す可能性があります!それが、リファクタリングが(大規模な)登場する瞬間です。それがなければ、TDDは機能しません。

すべてのテスト:分析と設計により、問題の範囲がより明らかになる場合があります。幅優先設計を考えてください。より多くの角度から問題を分析し、経験から入力を追加します。それは本質的に難しいですが、「十分な」ことをすれば、リファクタリングを減らして興味深い利益をもたらすかもしれません。簡単に分析しすぎて、マークを完全に見逃してしまうことに注意してください!

要因は多数あるため、どちらか一方を好むことを一般的に推奨することは難しいと思います:経験(特に同じ問題に関する)、ドメインの知識とスキル、リファクタリングのためのコードの使いやすさ、問題の複雑さ...

通常のビジネスアプリケーションにさらに焦点を絞ると、通常、高速でほぼ試行錯誤のアプローチを採用したTDDが有効性の点で勝てます。


1

テストフレームワークでサポートされていると仮定すると、ブレインダンプするテストを実装する代わりに、後で実装する説明的な保留テストを作成することをお勧めします。たとえば、APIがfooとbarを実行し、bizは実行しない場合、次のコード(この例はrspecにあります)をテストスイートに追加し、それらを1つずつ攻撃します。あなたはすぐに考えを下げ、すべての問題に一つ一つ対処することができます。すべてのテストに合格すると、ブレインダンプ中に発生したすべての問題にいつ対処したかがわかります。

describe "Your API" do

  it "should foo" do
    pending "braindump from 4/2"
  end

  it "should bar" do
    pending "braindump from 4/2"
  end

  it "should not biz" do
    pending "braindump from 4/2"
  end

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