ユニットテストを書く前にコードを書くことの欠点は何ですか?


33

最初に単体テストを作成してからコードの作成を開始することをお勧めします。しかし、私にとっては、逆の方がはるかに快適だと感じています-実際にコードを書いた後、より明確になったと感じているので、コードを書いてからユニットテストを書いてください。コードを作成してからテストを作成すると、テスト可能なデザインの作成に専念しても、コードを少し変更してテスト可能にする必要がある場合があります。一方、テストを作成してからコードを作成すると、コードが形成されるときにテストが頻繁に変更されます。

テストの作成を開始してからコーディングに進むための多くの推奨事項がありますが、逆にコードを作成してから単体テストを行う場合のデメリットは何ですか?


7
特定のプラクティスが「ベストプラクティス」である理由を採用する前に尋ねる+1
TaylorOtwell

回答:


37

赤が答えです。赤は、TDDの赤緑リファクタリングサイクルから得られるものであり、これはテストラストでは得られません。最初に、失敗したテストを記述します。失敗するのを見てください。それはあなたの赤であり、それは重要です。それは言う:私はこの要件があり、私のコードがそれを満たしていないこと知っています。したがって、ステップ2(緑)に進むと、コードがその要件を満たしていることが、ほぼ確実にわかります。要件を満たすようにコードベースを変更したことを知っています。

コードに基づいて開発された要件(テスト)は、コードに基づいて、そのような確実性、信頼性を奪います。


+1-優れたポイントとポイント獲得!ご意見ありがとうございます!
k25

7
テスト!=要件。テストとコードの両方が要件から派生している必要があります。
バートヴァンインゲンシェナウ

2
@Bart van Ingen Schenau:TDDの強さは、まさにARE要件です。さらに、これらは実行可能な要件です。
ムーヴィシエル

1
@Bart:ユニットテストは多くの場合(高レベルの)顧客の要求に対して詳細すぎるのですが、特に一度書かれた決定的な要件である自動受け入れテストなどのより高いレベルのテストも考慮する場合、その考えは間違いなく保持されます。それが「アジャイル受け入れテスト」の本質です。
マーティンウィックマン

3
TDDはテストではなく、仕様に関するものです。TDDアプローチで構築されたテストは、どの製品を作成するかについて合意するための、開発者と顧客間のコミュニケーション手段です。
ムービシエル

18

コードを作成してからテストを作成する場合、コードが仕様を満たしていることを確認するテストを作成するのではなく、コードを渡すためにテストを作成するというintoに陥るのは非常に簡単です。

とはいえ、それが間違いなく物事を行う唯一の方法ではなく、ソフトウェアを開発する「最良の」方法はありません。テストケースの開発に多くの先行作業を行った場合、提案されたアーキテクチャに欠陥があるかどうかはかなり後までわかりません。努力。


はい、あなたは最初の点については正しいですが、私はいつもそうしないようにしています。テストが失敗した場合、私は常にコードに行き、正しいことを確認してから、テストが正しいかどうかを確認し、間違っている方を修正します。あなたの意見をありがとう、私はこれを心に留めておく..最初のポイントと最後のポイントのために私から+1
...-k25

2
しかし、テストに合格したらどうなりますか?実際に対象のコードを実行していないため、テストに合格する可能性があります。テストは最初は失敗することになっているため、実際にはTDDでは起こりえません。失敗する場合は、修正するまで手順2に進まないでください。そのため、最後のテストには、最初のテストには存在しない障害モードがあります。
カールマナスター

@Carl Manaster-はい、有効なポイントがあります。コードを記述した後、要件を完全に認識しているため、ユニットテストケースは(理想的には)適切です。テストケースに合格した場合、コードは正しいと言い、テストが失敗した場合は、私が言ったことに従います。しかし、私はあなたがそこに有効なポイントを持っていることに100%同意します。
k25

@ k25:ポイントは、テストケースに合格しても、コードが正しいかどうかわからないということです。テストケースが間違っている可能性があります。
アノン。

@アノン。-はい、あなたは正しいです、私はこのケースも考慮に入れます。
k25

12

実際、頭字語の他の2文字については忘れていますが、TDDはテストに関するものです。ここで読むことができるもの:TまたはTDDのないTDDはTestingについてではありません

問題は、TDDと緊密に結びついている他の多くのことを学んだことです。最初にテストを行うかどうかは関係ありません。重要なのは、ソフトウェア設計について考えることです

ユニットテストを「正しい方法」で書くことができるように、つまり、それらが分離され、迅速かつ自動化されるようにするために、コードをより簡単にする方法についてコードを再検討する必要があることに気付くでしょうテストする。

個人的に、そのようなことが書かれていることを知らずに、固い原則を自分で学びました。これは、単体テストを書くことでクラスを書き直さなくてはならないため、テストが複雑になりすぎないためです。それは次のようなものにつながりました:

  • 意味をなさないか、プライベートメソッドに常駐していた機能を別のクラスに移動して、個別にテストできるようにしました。(単一責任の原則)。
  • 大きな継承構造を避け、代わりに構成を使用して実装を拡張する必要がありました(オープンクローズ原則で顕著)。
  • 私は継承について賢くなければなりませんでした。共有できる共通のコードを見て、スタブメソッドを使用するたびに抽象クラスを使用しました(Liskov Substitution Principle)。
  • クラスを個別にテストできるように、インターフェイスと抽象クラスを作成する必要がありました。誤ってモックオブジェクトを作成することになります。(インターフェース分離の原則)
  • 私は多くのインターフェースと抽象クラスを書いたので、共通型を使用するために変数とパラメーターを宣言し始めました(依存関係の反転の原理)。

常にテストファーストを行うわけではありませんが、テストを少しだけ簡単にするために、あなたが従うようになった適切なオブジェクト指向の原則とプラクティスに従うことがあります。今、私はそれ自身のためにコードを書いているわけではありません。簡単にテストできるように、またはさらに重要なこととして、コードを作成しました。簡単にメンテナンスできます


1
ソフトウェア設計について考えるとき、SOLIDの+1は自然に発生します。
オコド

+1(実際、+ 10を与えたかったのですが、できません)。まさに私の考え-あなたのポイントのリストは非常に良かった。それが私がこの質問をした一つの理由です。コードを書いた後、ユニットテストを書き始めたとき、クラスがもっと多くなったと感じました。しかし、私はあなたの意見をありがとう、両方の長所/短所を見たかったです!
k25

10

他の答えはすべて良いですが、触れられなかった点が1つあります。最初にテストを作成すると、テストが確実に作成されます。作業用コードを作成したら、テストをスキップしてUIで検証するだけの魅力があります。コードを書く前に常にテストに失敗するという規律がある場合、このトラップを回避できます。


4

最初にテストを書くと、そのデザインが「石にキャスト」される前に、デザインについて考えるもう1つの機会が得られます。

たとえば、特定のパラメーターセットを取得するメソッドが必要だと考えるかもしれません。また、最初にコードを記述した場合は、そのように記述して、テストを指定されたパラメーターに適合させます。しかし、最初にテストを作成する場合、「ちょっと待ってください。メインラインコードでこのパラメーターを使用したくないので、APIを変更する必要があるかもしれません。」


最初のポイントに+1。しかし、パラメータレベルに到達していない場合、設計が他の人と議論され、受け入れられたらどうなるでしょうか?
k25

@ k25-設計どおりに使用するのが難しい場合は、さらに考える必要があります。時々-非常にまれに-それはただ難しい仕事です。しかし、多くの場合、より単純なタスクに減らすことができます。リンクはありませんが、数年前にGoslingまたはGoetzがAPI設計に関するインタビューを行いました。
アノン

確かに、ポインターのおかげで、私は確かにそれらを見ていきます
...-k25

2

テストの作成を開始してからコーディングに進むための多くの推奨事項があるように、

これには本当に正当な理由があります。

「正しいと思うことをする」と言うと、人々は最も愚かでクレイジーなことをします。

「最初にテストを書く」と言うと、少なくとも人々は正しいことをしようとするかもしれません。

私が他の方法でそれを行う場合の欠点は何ですか?コードを書いてからユニットテストしますか?

通常、お粗末なテストとテスト可能にするために作り直さなければならないデザイン。

ただし、それは「通常」のみです。一部の人々は、設計とテストを並行して進化させます。一部の人々は、テスト可能なコードを配置し、手直しなしでテストを記述します。

「テストファースト」ルールは、まったく手がかりのない人々を指導および指導するために特にあります。

同様に、通りを横断する前に「両方の方法」を見るように常に言われます。ただし、実際にはそうではありません。そして、それは問題ではありません。私は右ハンドルの国に住んでいて、横断し始めたときだけ左を見る必要があります。

左ハンドルの国を訪れたとき、左を見るだけで殺される可能性がありました。

ルールは、理由のために非常に強く述べられています。

あなたがすることはあなた自身の問題です。


2

最初にテストを書くことのポイントは、考えさせることです

  • コードをテストする方法
  • コードがテスト可能であるために提示しなければならないインターフェース

シンプルなことをしている場合、テストはシンプルでインターフェイスが明らかなので、最初にどちらを書くかは重要ではありません(テストファーストの習慣を身に付けるのは良いことですが)。

しかし、TDDは単体テストだけでなく受け入れテストにまで拡大し、インターフェイスは自明ではなくなります。


1

最初にテストを作成しない場合は、テスト駆動開発(TDD)を実行していません。利点は多数あり、何度も練習するまで信じられないことがよくあります。以下は、従来の開発よりもTDDを行うことで得られた利点です。

  1. テストのセーフティネット-知らないうちに何かを壊すことを恐れずに大きな変更を加えることができます
  2. オーガニックデザイン-私が最終​​的に設計するデザインは通常、最初からやったデザインとは異なり、常に改善されています
  3. 生産性-小さな目標に向かって作業し(この1つのテストに合格)、それを実現する(すべてのテストに合格する)ことは私にとって非常にうまく機能し、モチベーションを保ちます。ペアで追加すると、私の生産性が最高に達します。

書籍:ベック、K。サンプルによるテスト駆動開発

良い例:http : //jamesshore.com/Blog/Lets-Play/


+1-素敵なポイント(特に1番目)とリンクをありがとう!
k25

0

テストを作成するとき、どのようにしてテストが失敗状態を検出するかを知ることができますか?答えは「テストをテストする」です。その方法は、最初にテストを記述し、失敗し、テスト対象のユニットが正常にコーディングされた場合にのみ合格することを確認することです(他の回答のいずれかに記載されている赤/緑/リファクタリングサイクル)。

最初にコードを作成してからテストを行うと、テストで正直な失敗が示されるかどうかの問題が残ります。

テストは仕様を表していることに注意してください。コードが「形を整える」ときにテストを修正する必要がある場合は、仕様が変更されていることを示唆しています。それは良いことかもしれませんし、そうでないかもしれません。問題の理解が当初は正しくなかった可能性があります。一方、ユニットが達成すべきことではなく、ユニットがどのように仕事をしているかを「どのように」テストしているかを意味する場合があります。

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