コードカバレッジをどこまでカバーしますか?[閉まっている]
-
05-07-2019 - |
質問
最近、コード カバレッジ ツール (特に Emma と EclEmma) を使い始めました。単体テストの完全性に関して表示されるビューと、単体テストがコードのどの領域に該当するかを確認できる機能がとても気に入っています。全然当たらない。私は現在、単体テストをあまり行わない組織で働いていますが、全員に単体テスト、コード カバレッジ、TDD への取り組みを本格的に推進し、できれば組織を変革するつもりです。
このテーマに関して私が確信を持てていない問題の 1 つは、コード カバレッジをどこまで取り上げるべきかということです。たとえば、次のようなクラスがあるとします。
//this class is meant as a pseudo-enum - I'm stuck on Java 1.4 for time being
public final class BillingUnit {
public final static BillingUnit MONTH = new BillingUnit("month");
public final static BillingUnit YEAR = new BillingUnit("year");
private String value;
private BillingUnit(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public boolean equals(Object obj) {
return value.equals(((BillingUnit) obj).getValue());
}
public int hashCode() {
return value.hashCode();
}
}
それを確認するためにいくつかの簡単な単体テストを作成しました。 equals()
正しく動作します。 getValue()
期待していたものが返ってくるなど。しかし、EclEmma の視覚的な性質のおかげで、 hashcode()
メソッドは「未テスト」を表す明るい赤色で表示されます。
わざわざテストする価値はあるのか hashCode()
, 、この例では、実装がどれほど単純であるかを考えると?コード カバレッジを % 向上させ、EclEmma がこれらの行に追加する目立つ赤いハイライトを取り除くために、このメソッドの単体テストを追加するような気がします。
もしかしたら私は神経質で OCD のような性格なのかもしれませんが、EclEmma のようなものを使用すると、何が未テストなのかが非常に簡単にわかります。プラグインはソース コードを赤で強調表示し、カバーされたコードは緑で強調表示します。本当にテストしたくなるのです。たとえそれがあまりメリットにならない場合でも、できる限り多くのクラスを 100% グリーンにするよう努めてください。
解決
コードカバレッジを使用して、テストのセットが不完全な可能性がある場所に関するヒントを提供します。たとえば、特定の機能のテストを作成し、その機能を満たすコードを開発しますが、実際には想定以上のコードを作成します-別のケースで例外をキャッチするかもしれませんテストが実行されないこと。カバレッジアナライザーを使用すると、テストが関連付けられていないコードを導入したことがわかります。十分なテストを書いていないことを知るのに役立ちます。
一方、カバレッジ分析は誤ったセキュリティにつながる可能性があります。すべてのコードを網羅しているからといって、十分なテストがあるわけではありません。コードが何をすべきかという観点からテストを検討し、それを確実に行うためのテストを作成する必要があります。できれば最初にテストを書いてください。コードが完全にカバーされているからといって、コードが意図したとおりに動作するわけではありません。
あなたの例では、コードを書く前に、hashCodeのテストを書いて、メソッドの機能が何をするかを定義していました。したがって、私はそれをカバーしています。だからといって、私が常に100%のカバレッジを持っているわけではありません。たとえば、単純なアクセサのテストを書くことにあまり熱心ではありません。他の人のコードをテストする必要性を感じないため、フレームワークから継承する親クラスのメソッドをテストすることもできません。
他のヒント
特定の種類のステートメントを無視することを選択できるライブラリを使用する価値があると思います。たとえば、次のものがたくさんある場合:
if(logger.isDebugEnabled()) {
logger.debug("something");
}
これらの種類のラインのカバレッジ計算をオフにできると便利です。 (おそらく)些細なゲッターとセッター(他のチェックや副作用なしで単純にメンバー変数を設定または返すもの)のカバレッジ計算をオフにすることも有効です。ただし、equalsとhashcodeをオーバーライドした場合は、テストする必要があると思います。重要な機能を追加したので、テストする必要があります。
明確にするために、上記の状況をカバレッジから除外すべきだと思う理由は、次のとおりです。
- その機能をテストしないことは問題ありません。すべてのステートメントがヒットすることを確認するためだけに、ロギングライブラリを各ロギングレベルに設定して、テストスイート全体を5回実行する必要はありません。
- 上記を行うと、カバレッジが逆に歪んでしまいます。ブランチの90%が
if(log.isDebugEnabled())
であり、他のブランチを除くすべてをテストすると、実際には90%のブランチカバレッジがあるように見えます(良い) 、0%の重要なブランチカバレッジがあります(悪い!!)。
コードカバレッジとテストカバレッジには違いがあります。コード カバレッジが 100% であるのではなく、コードが適切にテストされていることを確認するように努める必要があります。
次のコードを考えてみましょう。
public float reciprocal (float ex)
{
return (1.0 / ex) ;
}
値 1.0 で合格した 1 つのテストを実行した場合、すべてのパスで 100% のコード カバレッジ (分岐とステートメント) が得られます。コードには明らかに欠陥があります。
テスト カバレッジを測定することはさらに難しく、より優れた開発者およびテスターになることで得られます。
特に hashCode に関して、真正論者は、そのメソッドに対して個別の単体テストを行うべきだと言うでしょう。私は個人的に、それが少なくとも 1 つのユニット統合テストに含まれていることを確認し、各アクセサー/修飾子を直接テストしません。多くの場合、投資収益率が低すぎて、その努力が正当化されません。もちろん、これは正しいハッシュ コードを生成していることを確認する単体テストがあることを前提としています。
100%のコードカバレッジを有意味のテストで達成することは価値がない場合があります。また、前述のように、100%のコードカバレッジは、アプリケーションで考えられるすべての条件が満たされていることを必ずしも意味しませんテスト済み。
equals
、 hashCode
、およびその他の 契約ベース インターフェース( Comparable
および Serializable
、これらのテストを含めます。 equals / Comparable
と同様に、 equals / hashCode
コントラクトが正しく実装されていることが重要です。
JUnitアドオン、特に
を参照今はそれほど複雑ではないかもしれませんが、メソッドが変更された場合、期待どおりに動作していることを確認する簡単なチェックは後で非常に役立ちます。
チェックは非常に簡単に書けるはずなので、そうしないのはなぜですか?これは統計情報を助け、また、万が一破損した場合に備えて後で確認するのにも役立ちます。
また、TDDの場合、リファクタリング時に何も壊さないことを確認できる(またはそれに非常に近い)ため、100%のカバレッジが必要です。
古いJava1.4で仲間のプログラマが私のように立ち往生しました;)
私の前に述べたように回答、対象コードはテストされたコードではありません。そして、結論は次のとおりです。ある時点から、コードカバレッジを改善する唯一の方法は...コードを削除することです!
今、hashCodeに関して、期待されるソートされたメカニズムが尊重されていることを確認するためにユニットテストデザインでカバーされることは興味深いです(そしてもう1つの機能をカバーするためではありません)
他の場所で言ったように、低いコードカバレッジは問題ですが、高いコードカバレッジは、純粋な金を書いているという意味ではありません。
コードカバレッジに関心がない場合は、 equals()
および getValue()
のテストが必要になることをお勧めします- hashCode()
がどのように、どこで使用されているか(申し訳ありませんが、私はC#開発者です)、あなたはそれをテストしたいかもしれません。
最も重要な部分は、テストにより、正しいコードを記述したこと、およびコードが期待どおりに機能することを確信できることです。
この特定のケースでは、equalsメソッドをテストしているので、等しいオブジェクトが等しいハッシュコードを持っていることもテストできます。equalsがtrueを返すと予想されるすべてのケースに追加のテストを追加するだけです。
これはコードカバレッジを提供し、掘り出し物としては、hashCodeが実際にその契約を満たしているという自信をあなたに与えます:-)
StringのhashCodeメソッドを信頼できることは明らかであり、このクラスを変更することは決してないことを考えると、わずかに価値があるだけです。しかし、equalsメソッドがまったくテストできないほど疑わしい場合は、それとhashCodeの一貫性をテストするのに十分な疑いを持つ必要があります。そして、あなたは、あなたが将来あなたが前にしたことを台無しにしたくないという仮定を常に疑うべきです。たとえば、誰かがやって来て、ポインター等価性チェックを追加することで「最適化」することに決めた場合、修正されたコードを実行するためのテストの完全なセットがあるかもしれません。そうしないと、彼らはあなたがした同じ心配に時間を無駄にします-私はコードカバレッジを持っていなくても大丈夫ですか?