テストカバレッジはコード品質の適切な尺度ですか?


20

80%のテストカバレッジ(すべてのテストに合格)を持つコードがある場合、テストカバレッジのないコードよりも品質が高いと言ってもいいでしょうか?

それとも、それがより保守可能であると言うのは公平ですか?


2
100%のカバレッジは、十分にテストされているという意味ではありません。ただし、0%はまったくテストされていないことを意味します。
mouviciel

1
技術的にはありません。事実上、はい。多くのソフトウェアエンジニアやテスターは、コードカバレッジが約80%に達すると、ユニットテストが適切であるタイプの欠陥が横ばいになり始めることを多くの経験から学びました。これがパレートの原則です。基本的に、テストの品質に関係なく、コードの80%をカバーするポイントに到達したら、おそらく潜在的な問題のほとんどをかなり徹底的に引き起こすコードの20%をテストしたことになります。これは絶対的なものではなく、従来の知恵です。生活がテストに依存している場合は、より徹底する必要があります。
カルフール14

@JoeRouncevilleよくわかりません...本当に有用なものを何もテストしなくても、高いテスト範囲を達成できます。カバレッジは、テストが意味があるかどうかではなく、テストスイートがコードのどの部分に触れているかを示すだけです。
アンドレス

1
@AndresF。それが私が「技術的にいいえ、事実上はい」と言った理由です。人々は(一般的に)ばかではありません。彼らは(通常)簡単なケースだけをテストしません。そのため、経験に基づいて、多くの店は約80%のカバレッジを停止し、人々は馬鹿ではないと(かなり安全に)仮定しています。
カルフール14

回答:


24

厳密な意味では、テストスイートの品質が確立されるまで、主張することは公平ではありません。テストのほとんどが相互に些細な、または繰り返しの場合、テストの100%に合格しても意味がありません。

問題は、プロジェクトの歴史において、これらのテストのいずれかがバグを発見したかどうかです。テストの目的は、バグを見つけることです。そして、そうしなかった場合、テストとして失敗しました。コード品質を改善する代わりに、彼らはあなたに誤ったセキュリティ感覚を与えているだけかもしれません。

テスト設計を改善するには、(1)ホワイトボックス手法、(2)ブラックボックス手法、および(3)突然変異テストを使用できます。

(1)以下は、テスト設計に適用するための優れたホワイトボックス技術です。ホワイトボックステストは、特定のソースコードを考慮して構築されます。ホワイトボックステストの1つの重要な側面は、コードカバレッジです。

  • すべての関数が呼び出されていますか?[機能範囲]
  • すべてのステートメントが実行されますか?[ステートメントカバレッジ-機能カバレッジとステートメントカバレッジはどちらも非常に基本的ですが、何もないよりはましです]
  • すべての決定(ifまたはなどwhile)に対して、それを強制的に真にするテストと、強制的に偽にするテストがありますか?[決定範囲]
  • 結合(使用&&)または選言(使用||)であるすべての条件に対して、各部分式にtrue / falseのテストがありますか?[条件カバレッジ]
  • ループカバレッジ:0回、1回、2回の繰り返しを強制するテストはありますか?
  • breakループからのそれぞれがカバーされていますか?

(2)要件が利用可能な場合にブラックボックス技術が使用されますが、コード自体は使用できません。これらは、高品質のテストにつながる可能性があります。

  • ブラックボックステストは複数のテスト目標をカバーしていますか?テストを「ファット」にする必要があります。機能Xをテストするだけでなく、YとZもテストします。異なる機能の相互作用は、バグを見つけるのに最適な方法です。
  • 「脂肪」テストが望ましくない唯一のケースは、エラー状態をテストする場合です。たとえば、無効なユーザー入力のテスト。複数の無効な入力テストの目標(たとえば、無効な郵便番号と住所)を達成しようとした場合、1つのケースが他のケースをマスクしている可能性があります。
  • 入力タイプを検討し、入力タイプの「等価クラス」を形成します。たとえば、三角形が正三角形かどうかを確認するためにコードをテストする場合、辺(1、1、1)の三角形を使用するテストでは、テストデータ(2、2、2)および(3、3、3)が見つかります。他のクラスの入力について考えて時間を費やすことをお勧めします。たとえば、プログラムが税金を処理する場合、各税金区分のテストが必要になります。[これは等価分割と呼ばれます。]
  • 特殊なケースは、しばしば欠陥に関連しています。また、テストデータには、同等タスクの端の上、上、下などの境界値が必要です。たとえば、並べ替えアルゴリズムのテストでは、空の配列、単一の要素配列、2つの要素を持つ配列、そして非常に大きな配列でテストする必要があります。入力だけでなく、出力についても境界ケースを考慮する必要があります。[これは呼び出し境界値分析です。]
  • 別のテクニックは「エラー推測」です。あなたのプログラムを壊すことができる特別な組み合わせを試してみると感じますか?それから試してみてください!要確認:プログラムの有効性を確認するのではなく、バグを見つけることが目標です。一部の人々は、エラー推測のコツを持っています。

(3)最後に、ホワイトボックスのカバレッジとブラックボックスのテクニックを適用するための素晴らしいテストがすでにたくさんあると仮定します。他に何ができますか?テストテストします。使用できるテクニックの1つに、突然変異テストがあります。

突然変異テストでは、バグを作成することを期待して、プログラム(のコピー)に変更を加えます。突然変異は次のとおりです。

ある変数の参照を別の変数に変更します。abs()関数を挿入します。小なりから大なりに変更します。ステートメントを削除します。変数を定数で置き換えます。オーバーライドメソッドを削除します。スーパーメソッドへの参照を削除します。引数の順序を変更する

プログラムのさまざまな場所に数十個のミュータントを作成します[テストするためには、プログラムをコンパイルする必要があります]。テストでこれらのバグが見つからない場合は、プログラムの変異バージョンでバグを見つけることができるテストを作成する必要があります。テストでバグが見つかったら、ミュータントを殺して別のミュータントを試すことができます。


補遺:この影響について言及するのを忘れました:バグは集中する傾向があります。つまり、1つのモジュールで見つかったバグが多いほど、バグが見つかる可能性が高くなります。そのため、失敗するテストがある場合(つまり、テストは成功です。目的はバグを見つけることです)、バグを修正するだけでなく、モジュールのテストをさらに記述して、上記のテクニック。

安定した速度でバグを見つけている限り、テスト作業を継続する必要があります。発見された新しいバグの発生率が低下している場合にのみ、開発のその段階で十分なテスト作業を行ったと確信できます。


7

ある定義では、重大な変更がテストによってキャッチされる可能性が高いため、保守性が向上します。

ただし、コードが単体テストに合格するという事実は、それが本質的に高品質であることを意味するものではありません。コードは不適切なコメントと不適切なデータ構造で不適切にフォーマットされている可能性がありますが、それでもテストに合格できます。

どのコードを保守および拡張したいかを知っています。


7

テストをまったく行わないコードは、非常に高品質で、読みやすく、美しく、効率的(または完全なジャンク)になる可能性があります。

良いテストでカバーされたコードの80%はおそらく許容できる品質であり、おそらく比較的保守可能であると言っても過言ではありません。しかし、実際にはほとんど保証されません。


3

もっとリファクタリングできると思います。コードが多くのテストでカバーされている場合、リファクタリングは非常に簡単になります。

それをより保守しやすいと呼ぶのは公平でしょう。


2

保守可能な部分については同意します。マイケル・フェザーズは最近、「テスタビリティと優れたデザインの間の深い相乗効果」と呼ばれる彼の素晴らしい講演のビデオを投稿し、このトピックについて議論しています。講演では、関係は一方向である、つまり、適切に設計されたコードはテスト可能であるが、テスト可能なコードは必ずしも適切に設計されていない、と彼は言います。

ビデオストリーミングはビデオでは素晴らしいものではないため、完全に視聴したい場合はダウンロードする価値があるかもしれません。


-2

「条件カバレッジ」に関連して、私はしばらくこの質問をしてきました。では、atollic.comの「なぜコードカバレッジ分析を行うのですか?」

より技術的には、コードカバレッジ分析は、テストケースでカバーされていないプログラム内の領域を検出し、プログラムのテストされていない部分をカバーする追加のテストを作成できるようにします。したがって、コードカバレッジは、コード自体の品質ではなく、テスト手順の品質を理解するのに役立つことを理解することが重要です。

これはここで非常に関連があるようです。特定のレベル(コードまたはその他)のカバレッジを達成することができるテストケースセットがある場合、かなり網羅的な入力値のセットでテスト対象のコードを呼び出す可能性が非常に高くなります。これにより、テスト中のコードについてはあまりわかりません(コードが爆発したり、検出可能な障害を生成しない限り)が、テストケースセットに自信持てます

興味深いNecker Cubeのビュー変更では、テストコードはテスト中のコードによってテストされています。


-3

プログラムが意図したとおりに動作することを保証し、変更が意図しない効果をもたらさないことを保証する多くの方法があります。

テストは1つです。データの突然変異を避けることも別の方法です。型システムも同様です。または正式な検証。

したがって、テストは一般的に良いことですが、テストの特定の割合はそれほど意味がないかもしれません。私はむしろ、十分にテストされたPHPライブラリよりも、テストなしでHaskellで書かれたものに依存します。


これはあなたの意見だけですか、何らかの形でバックアップできますか?
ブヨ

2
テストは、プログラムが意図したとおりに動作することを保証する方法ではありません。
アンドレスF. 14

1
その後、テストとは何かを疑問に思うようになりました
アンドレア14

@gnatこれはもちろん私の意見です。それでも、それは言うことを言います。Haskellは、コンパイラが非常に厳密で、入力の整形式、型、副作用、データの変異について多くの保証を提供する言語の例として取り上げました。私は、インタープリターが非常に寛容で、仕様さえも持たない言語の例としてPHPを取り上げました。テストがない場合でも、通常、タイプおよびエフェクトシステムからのすべての保証が存在することにより、ある程度の信頼性が得られます。テストで、1は非常に包括的なスイート持っている必要がありますことを補償するために
アンドレア・

私が書いたとき、私は多分少し急いでいた-私は電話でいた-しかし、私はまだポイントがあると思う。私は、PHP上のbashにしたくないが、私は比較にHaskellは、信頼性のはるかに大きい度を与えるということは客観的声明であることを考える
アンドレア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.