単体テストコードが「匂う」場合、それは本当に重要ですか?


52

通常、コピーアンドペーストおよびその他のあらゆる悪い慣行を使用して、単体テストを一緒にスローします。通常、単体テストは非常に見苦しく、「コードのにおい」に満ちていますが、これは本当に重要ですか?「本当の」コードが「良い」ものである限り、それは重要なことです。さらに、ユニットテストでは通常、スタブ機能などのさまざまな「臭いハック」が必要です。

不十分に設計された(「臭い」)単体テストについて、どの程度心配する必要がありますか?


8
常にコピーしているコードを修正するのはどれほど難しいでしょうか?
-JeffO

7
テストでのコードのにおいは、コードの残りの部分に隠れたにおいの指標になりやすい-なぜ「実際の」コードではないかのようにテストにアプローチするのか?
ホルスコル

回答:


75

単体テストの匂いは重要ですか?はい、間違いなく。しかし、それらは異なるコードから単体テストは、異なる目的を果たすと、その設計を知らせる緊張の異なるセットを持っているので、においがします。コードの臭いの多くはテストには当てはまりません。私のTDDの考え方を考えると、私は実際にはユニットテストの匂いがあることを主張するだろうより多くのコードがテストを満足させるだけの存在であるため、コードは匂いよりも重要。

一般的な単体テストの匂いは次のとおりです。

  • 脆弱性:一見些細な、または無関係なコードの変更であっても、テストは頻繁に予期せず失敗しますか?
  • ステートリーク:テストの実行順序に応じて、テストの失敗が異なりますか?
  • セットアップ/ティアダウンブロート:セットアップ/ティアダウンブロックは長く、長く成長していますか?彼らは何らかのビジネスロジックを実行しますか?
  • 遅いランタイム:テストの実行に時間がかかりますか?個々の単体テストの実行に10分の1秒以上かかりますか?(はい、私は真剣です、1/10秒です。)
  • 摩擦:既存のテストは、新しいテストの作成を困難にしますか?リファクタリング中に頻繁にテストの失敗に苦しんでいますか?

匂いの重要性は、それらがデザインまたは他のより基本的な問題、すなわち「煙がある場所、火がある」の有用な指標であることです。テストの匂いだけでなく、その根本的な原因も探してください。

一方、ここに、単体テストのいくつかの良い習慣があります:

  • 迅速で焦点の合ったフィードバック:テストで障害をすばやく特定し、その原因に関する有用な情報を提供する必要があります。
  • テストコードの距離を最小限に抑える:テストとそれを実装するコードの間に明確で短いパスが必要です。長距離は、不必要に長いフィードバックループを作成します。
  • テストワン・シングでA時間:単体テストは一つだけをテストする必要があります。別のことをテストする必要がある場合は、別のテストを作成します。
  • バグはあなたが書くのを忘れたテストです:将来、より良い、より完全なテストを書くために、この失敗から何を学ぶことができますか?

2
「単体テストは異なる目的を果たし、設計に役立つさまざまな緊張を持っています」。たとえば、必ずしもDRYではなく、DAMPする必要があります。
ヨルグWミットタグ

3
@JörgAgreed、しかしDAMPは実際に何かを表しますか?:D
ラインヘンリヒス

5
@Rein:説明的で意味のあるフレーズ。また、完全に乾燥していません。codeshelter.wordpress.com/2011/04/07/…を
ロバートハーベイ

+1。また、DAMPの意味も知りませんでした。
エガルシア

2
@ironcode他のシステムとの統合を壊すことを恐れずに、1つのシステムで単独で作業できない場合、それは私との密結合のようなにおいがします。これはまさに、長い実行時間のようなテストの匂いを識別する目的です。つまり、密結合のような設計上の問題を通知します。応答は「ああ、そのテストの匂いは無効です」ではなく、「この匂いは私のデザインについて何を教えてくれますか?」システムの外部インターフェイスを指定する単体テストは、変更がコンシューマとの統合を中断するかどうかを判断するのに十分なはずです。
ラインヘンリヒズ

67

心配します。単体テストを作成して、コードが期待どおりに動作することを証明します。これらにより、自信を持って迅速にリファクタリングできます。テストが壊れやすく、理解しにくい場合、または保守が困難な場合、失敗したテストを無視するか、コードベースが進化するにつれてテストをオフにして、最初にテストを記述する利点の多くを無効にします。


17
+1失敗したテストを無視し始めた瞬間、それらは価値を追加しません。

19

数日前にユニットアートのアートを読み終えました。著者は、あなたがあなたの本番コードと同じくらいあなたのユニットテストに注意を払うことを提唱します。

筆記が不十分で保守不可能なテストを直接体験しました。私は自分のいくつかを書きました。テストが維持するのが難しい場合、それは維持されないことが実質的に保証されています。テストがテスト対象のコードと同期しなくなると、それらは嘘と偽りの巣になります。単体テストのポイントは、私たちが何も壊していないという自信を植え付けることです(つまり、信頼を作成します)。テストが信頼できない場合、それらは役に立たないよりも悪いです。


4
1あなただけの生産コードのように、テストを維持する必要が
ハミッシュ・スミス

このトピックに関するもう1つの非常に良い本は、Gerard Meszarosの「xUnitテストパターン-テストコードのリファクトリング」です。
adrianboimvaser

7

ユニットテストが実際に「ほとんどの」場合にコードをテストする限り。(可能なすべての結果を見つけるのが難しい場合があるため、ほとんどの場合は意図的に述べた)。「臭い」コードはあなたの個人的な好みだと思います。迷惑メールを掘り下げて何が何であるかを理解しようとするのではなく、数秒以内にコードを読み取って理解できる方法でコードを常に記述します。特に、かなりの時間を経て戻ってきたとき。

一番下の行-そのテスト、それは簡単だと思います。「臭い」コードと混同したくありません。


5
+1:単体テストコードを大騒ぎしないでください。最も難しい質問のいくつかは、プログラミングの変更が単体テストを壊さないように、単体テストコードをより「堅牢」にすることを中心に展開します。愚かさ。単体テストは脆弱になるように設計されています。テスト用に設計されたアプリケーションコードより堅牢性が低くても問題ありません。
-S.ロット

1
@ S.Lottは、私の答えでよりよく説明されている理由で、両方とも同意します。
ラインヘンリヒス

1
@Rein Henrichs:これらは質問で説明されているよりもはるかに深刻な臭いです。「コピー&ペースト」と「非常にい」は、テストが信頼できない場所を説明する匂いほど悪く聞こえません。
S.ロット

1
@ S.Lott正確に言えば、「ユニットテストの匂い」について話をするなら、その区別をすることが重要だと思います。ユニットテストのコードの匂いはしばしばそうではありません。それらは異なる目的のために書かれており、ある文脈で臭いを生じさせる緊張は他の文脈では非常に異なっています。
ラインヘンリッヒス

2
@ S.Lott btwこれは、ほとんど無視されているチャット機能を使用する絶好の機会のように思えます:)
Rein Henrichs

6

絶対に。一部の人々は、「テストはテストなしよりも優れている」と言います。私は強く同意しません-不適切に書かれたテストは開発時間を浪費し、そもそも「壊れた」テストを修正するのに何日も無駄になります。現時点では、負担ではなくテストを価値あるものにするために私が注力している2つのことは次のとおりです。

保守性

あなたは結果を(テストされなければならないが起こる)、ない方法(どのようにそれが起こります)。テストの設定は、実装から可能な限り分離する必要があります。絶対に必要なサービスコールなどの結果のみを設定します。

  • モックフレームワークを使用して、テストが外部のものに依存しないようにします
  • 可能な限り、モックよりもスタブを優先する(フレームワークでスタブを区別する場合)
  • テストにロジックはありません!ifs、switch、for-each、case、try-catchesなどは、テストコード自体にバグを導入する可能性があるため、すべて大きな問題ではありません。

読みやすさ

テストをもう少し繰り返してもかまいませんが、テストを読みやすくするのであれば、通常は運用コードで繰り返すことはできません。これと上記の保守性のバランスを取るだけです。テストの実行内容を明確にしてください!

  • テストの「アレンジ、アクト、アサート」スタイルを維持するようにしてください。これにより、シナリオのセットアップと期待が、実行されるアクションとアサートされる結果から分離されます。
  • テストごとに1つの論理アサーションを維持します(テストの名前に「and」が含まれる場合、複数のテストに分割する必要がある場合があります)

結論として、あなたは「臭い」テストに非常に関心を持っているべきです-それらはあなたの時間の無駄に終わってしまい、価値をもたらさない可能性があります。

あなたは言った:

単体テストでは、通常、スタブ機能などのさまざまな「臭いハック」が必要です。

モックフレームワークの使用など、ユニットテストのテクニックを読んで間違いなくできるように思えます。上記をはじめとする多くのことをカバーするThe Art of Unit Testingを強くお勧めします。筆記が不十分で保守が困難な「臭い」テストに長い間苦労した後、それは啓発的であることがわかりました。これは、私が今年行った最高の時間投資の1つです。


素晴らしい答え。私はたった1つの小さな口論しかありません。「テストごとに1つの論理アサーション」よりもはるかに重要なのは、テストごとに1つのアクションです。ポイントは、テストを配置するために必要なステップ数に関係なく、「テスト対象の量産コードアクション」が1つしかないことです。上記のアクションに複数の副作用が必要な場合、複数のアサーションがある可能性があります。
21:01に幻滅

5

あなたのための2つの質問:

  • あなたがテストしていると思うものをテストしていることを絶対に肯定していますか?
  • ユニットテストで他の誰かに見える場合は、コードがされるかを把握することができます行うことになって

ユニットテストには、最も一般的なセットアップコードと分解コードである反復タスクを処理する方法があります。基本的に、テストセットアップメソッドとテストティアダウンメソッドがあります。すべてのユニットテストフレームワークがこれをサポートしています。

単体テストは小さく、簡単に理解できるものでなければなりません。そうでなく、テストが失敗した場合、合理的に短期間でどのように問題を修正しますか。コードに戻る必要がある場合は、数か月先まで簡単に実行できます。


5

ゴミの臭いがするようになったら、取り出しましょう。テストコードは、運用コードと同じようにクリーンである必要があります。お母さんに見せてもらえますか?


3

ここでの他の回答に加えて。

単体テストの低品質コードは、単体テストスイートに限定されません。

単体テストで満たされる役割の1つはドキュメントです。

ユニットテストスイートは、APIがどのように使用されるかを調べるために探す場所の1つです。

APIの呼び出し元がユニットテストスイートの一部をコピーする可能性は低く、悪いテストスイートコードが他の場所のライブコードに感染することになります。


3

正当な質問としてこれにアプローチする方法を見つけるのに時間がかかったので、私はほとんど答えを提出しませんでした。

プログラマーが「ベストプラクティス」に従事する理由は、美的な理由のためではなく、「完璧な」コードが必要なためでもありません。時間を節約できるからです。

  • 優れたコードは読みやすく、理解しやすいため、時間を節約できます。
  • バグを修正する必要がある場合、バグを見つけやすくなりますので、時間を節約できます。
  • コードを拡張する場合、コードを拡張する方が簡単で高速なので、時間を節約できます。

(私の観点から)あなたの質問は、時間を節約するか、時間を無駄にするコードを書くべきですか?

その質問に対して、あなたの時間はどれほど重要ですか?

参考までに、スタブ、モック、およびモンキーパッチはすべて正当な用途があります。使用が適切でない場合にのみ「臭い」がします。


2

ユニットテストの堅牢性を高めすぎないように特に心がけています。堅牢であるという名目でエラー処理を開始する単体テストを見てきました。最終的には、キャッチしようとしているバグを飲み込むテストです。また、単体テストでは、機能させるためにかなり頻繁にファンキーなことを行う必要があります。リフレクションを使用したプライベートアクセサの全体的な考えを考えてみてください。実稼働コードでそれらの束を見た場合、10回のうち9回心配になります。テストするものについて考えるのにもっと時間をかける必要があると思います。 、コードの清潔さよりも。大規模なリファクタリングを行う場合は、とにかくテストをかなり頻繁に変更する必要がありますので、一緒にハックし、所有感を少し抑えて、時間の到来時に書き直したり、やり直したりする意欲を高めてください。


2

深刻な変更を行う場合、低レベルの重いカバレッジを使用する場合は、製品コードと同じくらいの時間をテストコードに費やすことになります。

テストのセットアップの複雑さによっては、コードがより複雑になる場合があります。(たとえば、httpcontext.current対偽物を正確に構築しようとする恐ろしい怪物)

製品が既存のインターフェイスにほとんど変更を加えることがほとんどなく、ユニットレベルの入力の設定が非常に簡単なものでない限り、実際の製品としてのテストの理解を心配しているのは少なくとも私です。


0

コードの匂いは、コードの問題であり、後のある時点で変更または理解する必要があります。

ですから、与えられた単体テストに「近づかなければならない」ときに、コードの匂いを修正する必要があると思いますが、それは前ではありません。

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