web-dev-qa-db-ja.com

ユニットテストは後でコメント化される傾向があるため、または統合テストの方が価値があるため、ユニットテストを記述しないのは理にかなっていますか。

私は同僚とユニット/統合テストについて話し合っており、彼は興味深いケースを作ったに対してユニットテストを書いている。私は大きなユニットテスト(主にJUnit)の提唱者ですが、興味深い点を指摘したので、他の人の意見を聞くのに興味があります。

彼のポイントを要約すると:

  • 主要なコードの変更(POJOの新しいセット、主要なアプリケーションのリファクタリングなど)が発生した場合、ユニットテストは書き直されるのではなくコメント化される傾向があります。
  • ユースケースをカバーする統合テストに時間をかけると、スコープの小さいテストの重要性が低くなります。

これについての考え?統合テストは少なくとも価値があるように聞こえますが、私はまだプロ単体テストです(一貫して改善されたコードを生成しているのを見ています)。

35
Jeff Levine

あまりにも頻繁に、ユニットテストが間違ったものをテストしているので、私はあなたの友達に寄り添う傾向があります。

単体テストは本質的に悪いわけではありません。ただし、多くの場合、入力/出力フローではなく実装の詳細をテストします。これが発生すると、完全に無意味なテストになります。私自身のルールは次のとおりです優れた単体テストは、何かを壊したことを教えてくれます;悪い単体テストは、単に何かを変更したことを教えてくれます。

私の頭の上の例は、数年前にWordPress=に押し込まれた1つのテストです。テストされている機能は、相互に呼び出されるフィルターを中心に展開し、テストはコールバックがその後、正しい順序で呼び出されます。ただし、(a)チェーンを実行してコールバックが予期した順序で呼び出されることを確認する代わりに、テストは、(b)最初から公開されていないはずの内部状態の読み取りに重点を置いています。内部を変更すると、(b)赤に変わりますが、(a)内部を変更すると、期待どおりの結果が得られない場合にのみ赤に変わります(b)は、私の見解では明らかに無意味なテストでした。

いくつかのメソッドを外部の世界に公開するクラスがある場合、私のビューでテストする正しいことは、後者のメソッドですonly内部ロジックもテストする場合、複雑なテスト方法を使用するか、何かを変更したいときはいつでも必ず壊れる大量のユニットテストを使用して、内部ロジックを外部に公開する可能性があります。

以上のことを踏まえると、あなたが提案しているように、あなたの友人が単体テスト自体について批判的であるとしたら、私は驚くでしょう。むしろ私は彼が実用的な人を集めると思います。つまり、記述された単体テストは実際にはほとんど無意味であることに気付きました。引用:「単体テストは、やり直されるのではなくコメントアウトされる傾向があります」。私にはそこに暗黙のメッセージがあります-彼らがやり直す必要がある傾向がある場合、それは彼らが吸う傾向があるためです。その場合、2番目の命題は次のようになります。開発者は、間違いを起こしにくいコード(つまり、統合テスト)を作成する時間を短縮できます。

そのため、1つが良くも悪くもありません。それは間違いを犯すのがはるかに簡単であり、実際には非常に頻繁に間違っていることです。

62

主要なコード変更が発生した場合、ユニットテストは書き直されるのではなくコメント化される傾向があります。

もちろん、既存のすべてのテストをコメントアウトすると、すべてのテストが「グリーン」になると考えるカウボーイコーダーの規律のない束で満たされます。単体テストの作り直しは、最初にそれらを書くのと同じ量の規律をとるので、ここで取り組む必要があるのは、チームの「完了の定義」です。

スコープが小さいテストの重要性が低くなる/まったく重要にならないユースケースをカバーする統合テストに時間を費やすほうがよいでしょう。

それは完全に間違っているわけでも、完全に正しいわけでもありません。有用な統合テストを作成するための作業は、作成しているソフトウェアの種類に大きく依存します。統合テストを単体テストとほとんど同じくらい簡単に作成できるソフトウェアを使用している場合、それらは高速で実行され、コードを適切にカバーできるため、同僚に意味があります。しかし、多くのシステムでは、これらの3つのポイントは統合テストでは簡単に満たすことができないので、単体テストにも力を入れるべきです。

38
Doc Brown

私はあなたの同僚の議論を受け入れることを知りません。

  1. ユニットテストがコメントアウトされている場合、それは誰かが怠惰だからです。それは単体テストのせいではありません。そして、怠惰を言い訳として使い始めると、少しの努力を必要とするほとんどすべての慣習に反対することができます。
  2. 正しく実行していれば、単体テストに長い時間をかける必要はありません。彼らはあなたがより重要な仕事をするのを止めません。壊れたコードを修正することが何よりも重要であることに私たち全員が同意する場合、単体テストは非常に重要です。ポスト条件をテストする簡単な方法です。それがなければ、ポスト条件の保証を満たしていることをどのようにして知っていますか?そうでない場合は、コードが壊れています。

単体テストに対する他のより説得力のある議論があります。まあ、厳密には彼らに反対しているわけではありません。 DHHの テストによる設計の損傷 から始めます。彼は楽しい作家なので、読んでください。私がそれから取ったこと:

単体テストに対応するために大きな設計変更を行うと、プロジェクトの他の目標を妨げる可能性があります。できれば、公平な人に、どちらのアプローチがより簡単かを尋ねます。テストしやすいコードを理解するのが難しい場合、単体テストから得たすべての利点を失う可能性があります。抽象化が多すぎると、認知的オーバーヘッドが発生し、速度が低下し、漏れやすい間違いが発生しやすくなります。それを割引しないでください。

微妙で哲学的なものにしたい場合は、多くの優れたリソースがあります。

13
Scant Roger

主要なコードの変更(POJOの新しいセット、主要なアプリケーションのリファクタリングなど)が発生した場合、ユニットテストは書き直されるのではなくコメント化される傾向があります。

しないでください。それをする人を見つけたら、彼らを殺して彼らが繁殖しないことを確認してください。私がCSIのテレビ番組を見てそれを見るときに鍵となるのは、誤解を招く多くのDNAサンプルを散乱させることです。このようにして、犯罪現場を非常に多くのノイズで汚染し、DNAテストのコストと時間のかかる性質を考えると、彼らがあなたにそれを突き止める確率は天文学的に低くなります。

6
user204677

ユニットテストは書き直されるのではなくコメントアウトされる傾向があります。

その時点で、コードレビュープロセスは「ユニットテストを修正してください」と表示し、これはもう問題ではありません:-)コードレビュープロセスが送信されたコードのこの種の大きな欠陥をキャッチしていない場合、それが問題です。

4
Philip Kendall

主要なコードの変更(POJOの新しいセット、主要なアプリケーションのリファクタリングなど)が発生した場合、ユニットテストは書き直されるのではなくコメント化される傾向があります。

私は常にリファクタリングと機能の変更を分けておくようにしています。両方を行う必要があるときは、通常、最初にリファクタリングをコミットします。

機能を変更せずにコードをリファクタリングする場合、既存の単体テストは、リファクタリングが誤って機能を破壊しないことを保証するのに役立つはずです。そのため、そのようなコミットでは、ユニットテストを無効にするか削除することを主要な警告サインと見なします。これを行う開発者は、コードをレビューするときにそうしないように指示する必要があります。

機能を変更しない変更でも、単体テストの欠陥が原因で単体テストが失敗する可能性があります。変更するコードを理解していれば、このような単体テストの失敗の原因は通常すぐにわかり、簡単に修正できます。

たとえば、関数が3つの引数をとる場合、関数の最初の2つの引数間の相互作用をカバーするユニットテストは、3番目の引数に有効な値を提供するように注意を払っていなかった可能性があります。単体テストのこの欠陥は、テストされたコードのリファクタリングによって明らかになる可能性がありますが、コードが何をすることになっているか、ユニットテストが何をテストしているかを理解していれば簡単に修正できます。

既存の機能を変更する場合、通常、いくつかの単体テストも変更する必要があります。この場合、ユニットテストは、コードが意図したとおりに機能を変更し、意図しない副作用がないことを確認するのに役立ちます。

バグを修正したり、新しい機能を追加したりする場合、通常は単体テストを追加する必要があります。それらについては、最初に単体テストをコミットし、後でバグ修正または新機能をコミットすると役立つ場合があります。これにより、新しいユニットテストが古いコードではパスせず、新しいコードではパスすることを簡単に確認できます。ただし、このアプローチには欠点がないわけではないため、新しい単体テストとコードの更新の両方を同時にコミットすることを支持する議論もあります。

ユースケースをカバーする統合テストに時間をかけると、スコープの小さいテストの重要性が低くなります。

これには真実の要素がいくつかあります。ソフトウェアスタックの上位層を対象とするテストでソフトウェアスタックの下位層のカバレッジを取得できる場合、コードをリファクタリングするときにテストがより役立つ場合があります。

ただし、単体テストと統合テストの正確な違いについては同意できないと思います。そして、開発者がユニットテストを呼び出し、別の開発者が統合テストを呼び出すテストケースがあっても、それが有用なテストケースであることに同意できる限り、心配する必要はありません。

3
kasperd

統合テストは、システムが想定どおりに動作するかどうかを確認するために行われます。これは常にビジネス価値があります。ユニットテストは常にそうするわけではありません。ユニットテストは、たとえば、デッドコードのテストです。

情報を提供しないテストはすべて無駄であるというテストの哲学があります。コードの一部が処理されていない場合、その単体テストは常に(またはほとんどの場合)緑になり、情報はほとんどまたはまったく提供されません。

すべてのテスト方法は不完全になります。何らかの指標で100%のカバレッジを得たとしても、入力データの可能なすべてのセットを通過するわけではありません。だから、単体テストは魔法だとは思わないでください。

ユニットテストを使用するとコードが改善されるという主張をよく見ました。私の意見では、ユニットテストがコードにもたらす改善は、コードに慣れていない人々に、コードを細かく因数分解された断片に分割することを強制することです。通常、コードを小さく因数分解された部分で設計することに慣れている場合は、それを強制するためのユニットテストが不要であることがわかります。

単体テストの程度とプログラムの規模によっては、膨大な量の単体テストが発生する可能性があります。その場合、大きな変更は難しくなります。大きな変更が原因で多数のユニットテストが失敗した場合は、変更を拒否したり、多くのテストを修正するために多くの作業を行ったり、テストを破棄したりできます。どの選択肢も理想的ではありません。

単体テストはツールボックスのツールです。彼らはあなたに仕えるためにあり、逆ではありません。少なくともあなたが入れたのと同じくらいそれらから逃げるようにしてください。

3
Michael Shaw

単体テストは、一部の支持者が主張している特効薬ではありません。しかし、一般的に、それらは非常に正のコスト/利益比を持っています。彼らはあなたのコードを「より良く」することはできません、おそらくよりモジュール化します。 「より良い」には、「テスト容易性」が示唆するよりもはるかに多くの要因があります。しかし、彼らはあなたが考えたすべてのケースと使用法でそれが機能することを保証し、そしてあなたのバグのほとんど(おそらくより些細なもの)を排除します。

単体テストの最大の利点は、コードをより柔軟にし、変更に対する耐性を持たせることです。機能をリファクタリングまたは追加でき、何も壊していないと確信できます。これだけでも、ほとんどのプロジェクトにとって価値があります。

あなたの友人によって作られたポイントを参照してください:

  1. POJOを追加するとユニットテストが失敗する場合は、おそらく非常にひどく書かれています。 POJOは通常、ドメインについて話すために使用している言語であり、解決している問題、それらを変更することは明らかに全体ビジネスロジックを意味し、おそらくプレゼンテーションコードを変更する必要があります。プログラムのこれらの部分が変更されないことを保証しているものを期待することはできません...

  2. ユニットテストが悪いと不平を言うのは、人々がそれらをコメントアウトしているため、シートベルトを着用していないのでシートベルトが悪いと不平を言うようなものです。テストコードをコメントアウトして何かを壊した場合、彼は上司と非常に深刻で不愉快な会話に終わるはずです...

  3. 統合テストは単体テストよりもはるかに優れています。質問なし。特にあなたが製品をテストしているなら。しかし、単体テストが提供するのと同じ価値、適用範囲、正確性の保証を提供する、優れた包括的な統合テストを作成することは、信じられないほど困難です。

3
AK_

単体テストに対する議論は1つしか考えられず、かなり弱いです。

ユニットテストは、後の段階でコードをリファクタリングまたは変更するときに、その価値の大部分を示します。機能を追加するために必要な時間を大幅に削減し、何も壊していないことを確認します。

ただし、そもそもテストの作成には(小さな)コストがかかります。

したがって、プロジェクトが十分に短く、継続的なメンテナンス/更新を必要としない場合は、テストを作成するコストがプロジェクトのメリットを上回る可能性があります。

2
Ewan