web-dev-qa-db-ja.com

ユニットテストのコードカバレッジ-100%カバレッジはありますか?

あなたのユニットテストは100%のコードカバレッジを構成していますか?はいまたはいいえ、その理由または理由。

45
core

いくつかの理由でいいえ:

  • 100%のカバレッジに到達することは、明らかではない利点のための90%または95%と比較して、本当に高価です。
  • カバレッジが100%であっても、コードはnot完璧です。この方法を見てみましょう(実際には、話しているカバレッジのタイプによって異なります-ブランチカバレッジラインカバレッジ...):


public static String foo(boolean someCondition) {
    String bar = null;
    if (someCondition) {
        bar = "blabla";
    }
    return bar.trim();
}

ユニットテスト:

assertEquals("blabla", foo(true));

テストは成功し、コードカバレッジは100%です。ただし、別のテストを追加する場合:

assertEquals("blabla", foo(false));

次に、NullPointerExceptionを取得します。また、最初のテストでは100%だったので、2つ目のテストを作成する必要はありませんでした。

一般的に、私はcriticalコードはほぼ100%でカバーする必要があると考えていますが、他のコードは85-90%でカバーできます。

58
Romain Linsolas

すべての90%カバレッジテスター:

そうすることの問題は、コードのテストが10%難しいことも、バグの90%を含む重要なコードであることです!これは、長年のTDDの後に経験的に得た結論です。

そして結局のところ、これはかなり簡単な結論です。この10%のコードのテストは難しい、テストが難しいためトリッキーなビジネス問題またはトリッキーな設計上の欠陥、あるいはその両方を反映しています。バグの多いコードにつながることが多いこれらの正確な理由。

だけでなく:

  • 時間の経過とともに100%未満に減少する100%対象コードは、多くの場合、バグまたは少なくとも欠陥を特定します。
  • コントラクトと組み合わせて使用​​される100%カバーされたコードは、バグのないコードの近くに住むための究極の武器です。 コードコントラクトと自動テストはほとんど同じです
  • 100%カバーされたコードでバグが発見された場合、修正は簡単です。バグの原因となっているコードはすでにテストでカバーされているので、バグ修正をカバーする新しいテストを書くのは難しくありません。

いいえ、完璧な単体テストと実際にプロジェクトを終了することの間には実際的なトレードオフがあるためです:)

22
Andrew Hare

重要なシステムで100%のコードカバレッジを取得することはめったに実用的ではありません。ユニットテストを作成するほとんどの開発者は、90年代半ばから中期に向けて撮影します。

Pex のような自動テストツールは、コードカバレッジを増やすのに役立ちます。見つけにくいEdgeケースを検索することで機能します。

15
Robert Harvey

はい、そうです。

それは、それがどれほど簡単に達成できるかについて、使用している言語とフレームワークに依存します。

Ruby on on Rails for my current project。Ruby is very) "を使用しています。 mockable "を使用すると、他の言語で行う必要のある過度に複雑なクラス構成や構造の設計を組み込まなくても、コードの大きなチャンクをスタブ/モックアウトできます。

とはいえ、100%lineカバレッジ(基本的にはrcovが提供するもの)しかありません。必要なブランチをすべてテストすることを考える必要があります。

これは、継続的インテグレーションビルドの一部として最初から組み込んだ場合にのみ可能であり、カバレッジが100%を下回った場合はビルドを中断-すぐに修正するよう開発者に促します。もちろん、他の数値をターゲットとして選択することもできますが、最初から始めた場合、90%から100%に到達するまでの努力に大きな違いはありません。

また、特定のしきい値を超えた場合にビルドを中断するその他のメトリックもいくつかあります(循環的複雑度、重複など)。これらはすべて一緒になり、お互いを強化するのに役立ちます。

繰り返しますが、厳密なレベルで作業を続けるには、最初からこのようなものを用意しておく必要があります。それを達成するか、ヒットできる目標を設定し、満足のいくレベルに到達するまで徐々に段階的に上げていきます。

これは付加価値をもたらしますか?最初は懐疑的でしたが、正直言ってそうです。コードを徹底的にテストしたことが主な理由(それは間違いなく利点ですが)ではなく、テストが簡単で、推論が容易な単純なコードを記述するという点でさらに重要です。 100%のテストカバレッジを持っているとわかっている場合は、過度に複雑なif/else/while/try/catchの怪物を書くのをやめ、単純な愚かさを維持します。

10
madlep

機会があったら、grepできるコードのすべてのブランチにステートメントを挿入し、ヒットした場合はそのレコードを挿入して、何らかのステートメントを実行して、ヒットしていないステートメントを確認します。 。これはちょっと面倒なので、私はいつもそれが得意ではありません。

MySQLをDBとして使用する、チャリティーオークションで使用する小さなUIアプリを作成しました。本当にオークションの途中で壊れてほしくないので、何か新しいことに挑戦しました。

VC6(C++ + MFC)にあったので、2つのマクロを定義しました。

#define TCOV ASSERT(FALSE)
#define _COV ASSERT(TRUE)

そしてふりかけた

TCOV;

コード全体、私が見つけることができるすべての個別のパス、およびすべてのルーチンで。次に、プログラムをデバッガーの下で実行し、TCOVに到達するたびに停止しました。明らかな問題がないかコードを調べ、それを_COVに編集してから続行します。コードはその場で再コンパイルされ、次のTCOVに進みます。このようにして、私はゆっくりと手間をかけて、十分にTCOVステートメントを削除し、「正常に」実行されるようにしました。

しばらくして、TCOVのコードをgrepしたところ、テストしていないコードがわかりました。次に、戻ってもう一度実行し、以前に試していないブランチをさらにテストするようにしました。コードにTCOVステートメントがなくなるまで、これを繰り返しました。

これには数時間かかりましたが、その過程でいくつかのバグを見つけて修正しました。徹底したテスト計画を立て、それに従う規律を私が持っていたはずはありません。すべてのブランチをカバーしたことを知っただけでなく、実行中に見てすべてのブランチを作成しました-非常に優れたコードレビュー。

したがって、カバレッジツールを使用するかどうかに関係なく、これは、他の方法でコードに潜むバグを根絶するためのより良い方法です。

9
Mike Dunlavey

私は個人的に、100%のテストカバレッジが複数のレベルで問題があると考えています。何よりもまず、作成した単体テストから目に見えるコスト削減効果が得られることを確認する必要があります。さらに、単体テストは他のコードと同様にCODEです。つまり、他のコードと同様に、正当性を検証して維持する必要があります。追加コードが正しいかどうかを検証し、それを維持し、ビジネスコードへの変更に応じてそれらのテストを有効に保つための追加の時間は、コストを追加します。 100%のテストカバレッジを達成し、コードをできる限り徹底的にテストすることを保証することは、称賛に値する努力ですが、それを達成することは、なんとしてもコストがかかります。

フリンジや非常にまれなケースをカバーするために実施されているエラーと妥当性のチェックをカバーすることはよくありますが、例外的なケースは、必ずしもカバーする必要がないコードの例です。 時間努力(そして最終的にはmoney)の量そのようなまれなフリンジケースのカバレッジを達成するために投資しなければならないことは、他のビジネスニーズに照らして、しばしば無駄です。プロパティはコードの一部であることが多く、特にC#3.0では、すべてではないにしてもほとんどのプロパティはまったく同じように動作し、非常に単純です(単一ステートメントの戻り値または設定値)。何千ものプロパティのユニットテストをラップする時間の割合は、その投資からより大きく、より価値のある具体的な利益を実現できる他の場所に投資するほうがよいでしょう。

単に100%のテストカバレッジを達成するだけでなく、「完全な」ユニットをセットアップしようとすると、同様の問題があります。フレームワークのモックは最近驚くほど進んでおり、ほとんどすべてのものをモックすることができます(お金を払っても構わないとしたら、TypeMockは実際にすべてのものをモックすることができますが、コストがかかります)。あなたのコードの一部はモック可能な方法で書かれていませんでした(これは実際には.NETフレームワーク自体の大部分の大きな問題です)。テストの適切な範囲を達成するために時間を費やすことは有用ですが、太陽の顔の下にあるすべてのものを模倣する時間、それを可能にする抽象化とインターフェースの層を追加する時間は、多くの場合、時間、労力、そして最終的にはお金の無駄です。

テストの最終的な目標は、コードカバレッジの究極を達成することではありません。最終的な目標は、ユニットテストの作成に費やされた単位時間あたりの最大値を達成し、その時間内で可能な限り多くをカバーすることです。これを達成するための最良の方法は、BDDアプローチを取ることです。懸念事項を指定し、コンテキストを定義して、予想される結果がbehavior開発中(動作...ユニットではありません。)

6
jrista

新しいプロジェクトでは、TDDを実践し、100%ラインカバレッジを維持しています。これは主にTDDを通じて自然に発生します。カバレッジギャップは通常、注目に値し、簡単に埋められます。私が使用しているカバレッジツールが提供されたブランチカバレッジまたは何か他のものを使用している場合は、それに注意を払います。

100%のカバレッジを維持するための私の最も強力な主張は、(もしカバレッジを気にする場合)100%未満のカバレッジを管理するよりも100%のカバレッジを維持する方がはるかに簡単ですです。カバレッジが100%でドロップした場合、その理由はすぐにわかり、簡単に修正できます。これは、ドロップが作業中のコードにあるためです。しかし、95%程度に収まると、カバレッジの回帰を見逃しやすく、既知のギャップをいつまでも再検討することになります。これが、現在のベストプラクティスで完全に合格するためにテストスイートを必要とする正確な理由です。それより少ないものは管理が難しく、簡単ではありません。

私の態度は、Rubyでしばらく働いたことがきっかけです。優れたテストフレームワークがあり、テストダブルが簡単です。100%カバレッジもPythonでは簡単です。従順性​​の低いツールがある環境での標準。

レガシープロジェクトでも同じ標準を使用したいのですが、大規模なアプリケーションを100%までの平凡なカバレッジで実現することは現実的ではありませんでした。私は95-99%に落ち着かなければなりませんでした。戻って古いコードをすべてカバーするのは常に大変な作業です。これは、コードベースを100%に保つのが簡単であるという私の主張に矛盾しません。最初からその標準を維持する方がはるかに簡単です。

5

いいえ、ほとんど価値のないあいまいなテストを書くのが難しいのではなく、ユーザーを支援する新機能を追加することに時間を費やしたからです。私は大きなもの、微妙なもの、そして壊れやすいものをユニットテストすると言います。

5
RichH

私は通常、単体テストを回帰防止の方法と同じように記述します。修正する必要があるとバグが報告された場合は、ユニットテストを作成して、それが将来再び表面化しないことを確認します。機能を維持するために(または複雑なパーツ間の相互作用のために)必要な機能のセクションに対していくつかのテストを作成する場合がありますが、通常はバグ修正で必要なことを通知します。

4
SqlRyan

私は通常93 ..---100%をカバーすることができましたが、100%を目指すことはもうありません。私は以前はそれを実行していましたが、それは実行可能ですが、通常は盲目的に明白なテストは必要ないため、特定のポイントを超えて努力する価値はありません。これの良い例は、次のコードの真の評価ブランチです:

public void method(boolean someBoolean) {
    if (someBoolean) {
        return;
    } else {
        /* do lots of stuff */ 
    }
}

ただし、達成することが重要なのは、クラスのfunctional部分を100%に近い範囲でカバーすることです。忍び寄るバグと未定義の動作の霧の沼、そしてもちろん金儲けのノミのサーカス。

4
Esko

Ted Newardブログ から。

この時点までに、ほとんどの開発者は、少なくともマゾヒスティックテストのミームの採用を検討していません。 NFJSの仲間であるStuart HallowayとJustin Gehtlandは、企業文化の基準として彼らのコードの100%テストカバレッジを高く設定するコンサルタント会社Relevanceを設立しました。

Neal Fordは、ThoughtWorksが同様の発言をしていると報告していますが、クライアントが時々、上記の目標を達成する方法に偶発的な障害を課すことは理解しています。それは野心的ですが、古代アメリカインディアンのことわざが述べているように、

矢印を太陽に向けると、地面に向けた場合よりも高く、遠くまで飛んでいきます。

4
cetnar

はい、ラインカバレッジが100%のプロジェクトがあります。同様の質問に対する私の回答をご覧ください 質問。

あなたは100%lineカバレッジを取得できますが、他の人がここで指摘しているようにSOおよびインターネット上の他の場所では、それはおそらく最小限にすぎません。パスとブランチのカバレッジを検討する場合、実行する必要のある作業はさらに多くあります。

もう1つの見方は、コードをシンプルにして、100%のラインカバレッジを簡単に取得できるようにすることです。

2
quamrana

testabilityを念頭に置いて記述された新しいコードについては、100%しかカバーしていません。適切なカプセル化を使用すると、各クラスと関数にfunctional単体テストを適用でき、同時に100%に近いカバレッジを実現できます。次に、いくつかのEdgeケースをカバーするテストを追加して、100%に到達するだけです。

カバレッジを得るためだけにテストを書くべきではありません。正確性/コンプライアンスをテストする機能テストを作成する必要があります。すべての根拠をカバーする優れた機能仕様と優れたソフトウェア設計により、無料で優れたカバレッジを取得できます。

2
Ates Goral

多くの場合、100%のステートメントカバレッジを取得する価値はありませんが、場合によっては価値がある価値があります。場合によっては、100%のステートメントカバレッジが要件をはるかに超えるlax要件です。

重要な質問は、「ソフトウェアに障害が発生した場合(誤った結果が生成された場合)はどうなるのか」です。ほとんどの場合、バグの影響は比較的少ないです。たとえば、数日以内にコードを修正し、何かを再実行する必要があるかもしれません。ただし、影響が「120秒で誰かが死ぬ可能性がある」である場合、それは大きな影響であり、単にlotより多くのテストカバレッジが必要です。 100%ステートメントカバレッジ。

Linux Foundationの コアインフラストラクチャイニシアチブのベストプラクティスバッジ を主導しています。私たちdoは100%ステートメントカバレッジを持っていますが、厳密に必要だったとは言えません。長い間、私たちは100%に非常に近かったので、それを最後の少しの割合で行うことにしました。ただし、エンジニアリング上の理由から、最後の数パーセントを正当化することはできませんでした。最後の数パーセントは、純粋に「仕上がりの誇り」として追加されました。カバレッジが100%であることから、非常に小さな心の余裕が生まれますが、実際には必要ありませんでした。通常のテストだけで90%を超えるステートメントカバレッジがあり、それは私たちの目的には問題ありませんでした。とは言っても、このソフトウェアは堅実でありたいと思っており、100%のステートメントカバレッジを持つことで、そこに到達することができました。今日、100%のステートメントカバレッジを取得するのも簡単です。

100%必要ない場合でも、カバレッジを測定すると便利です。テストが適切なカバレッジを持っていない場合、あなたは心配する必要があります。悪いテストスイートはステートメントのカバレッジが良い可能性がありますが、ステートメントカバレッジが良くない場合、定義によりテストスイートが悪いです。どれだけのトレードオフが必要ですか?完全にテストされていないソフトウェアからのリスク(確率と影響)は何ですか?定義により、エラーが発生する可能性が高くなります(テストしなかった!)。しかし、あなたとユーザーがそれらのリスク(確率と影響)に耐えられる場合は、問題ありません。影響の少ない多くのプロジェクトでは、80%から90%のステートメントカバレッジは大丈夫だと思います。

一方、ソフトウェアのエラーにより人々が死亡する可能性がある場合、100%のステートメントカバレッジでは十分ではありません。テストの品質をチェックするために、少なくともブランチカバレッジを追加します。 DO-178C (空中システムの場合)などの標準はこのアプローチを採用しています。障害が軽微である場合は大きな問題ではありませんが、障害が壊滅的である可能性がある場合は、より厳密なテストが必要です。たとえば、DO-178Cには、最も重要なソフトウェア(間違いを犯した場合にすぐに人を殺すことができるソフトウェア)に対して MC/DCカバレッジ が必要です。 MC/DCは、ステートメントカバレッジやブランチカバレッジよりもはるかに負荷がかかります。

2

少し前に、Kent BeckとDavid Saffが特にコードを記述してテストした JUnit実装のカバレッジ について少し分析しました。

結論から:

世界で最もテストされたプロジェクトの1つにラインカバレッジを適用すると、次のことがわかります。

  1. プルリクエストの影響を受けるコードのカバレッジを注意深く分析することは、しきい値に対するカバレッジ全体の傾向を監視するよりも有用です。

  2. 廃止されたコードのテスト基準を下げることは問題ないかもしれませんが、これが残りのコードに影響を与えないようにしてください。継続的インテグレーションサーバーでカバレッジしきい値を使用する場合は、廃止されたコードに対して異なる設定を検討してください。

  3. テストされていないコード行が2〜3行以上あるメソッドを使用する理由はありません。

  4. 通常の容疑者(単純なコード、デッドコード、悪天候など)は、カバーされていないコードの約5%に相当します。

要約すると、回線のカバレッジを監視する必要がありますか?すべての開発チームがそうしているわけではなく、JUnitプロジェクトでさえ、それが標準的なプラクティスであるとは思われません。ただし、JUnit開発者と同じくらい良くなりたい場合、ラインカバレッジが95%未満になる理由はありません。そして、カバレッジの監視は、それを検証するための簡単な最初のステップです。

0
avandeursen

ここには多くの良い情報があります。過去に100%のコードカバレッジを目指すときに見つけたいくつかの利点を追加したかっただけです。

  • コードの複雑さを軽減するのに役立ちます

テストケースを書くよりも行を削除する方が簡単なので、カバレッジ100%を目指すと、すべての行、すべての分岐、すべてのifステートメントを正当化する必要があり、多くの場合、必要なことを実行するはるかに簡単な方法を見つけることになります少ないテスト

  • 優れたテスト粒度を開発するのに役立ちます

実装のごく一部をテストする多数の小さなテストを作成することで、高いテストカバレッジを実現できます。これはトリッキーなロジックには役立ちますが、どんなに些細なことでも退屈で、処理が遅くなり、実際のメンテナンスの負担になり、コードのリファクタリングが難しくなります。一方、非常に高レベルのエンドツーエンドの動作テストで良好なテストカバレッジを達成することは非常に困難です。通常、テストする対象には複雑な方法で相互作用する多くのコンポーネントが含まれ、考えられるケースの順列が非常に急速に大きくなるためです。したがって、実用的で100%のテストカバレッジを目指したい場合は、いくつかの優れたテストで高レベルのカバレッジを達成できる、テストの細かさのレベルを見つける方法をすばやく学習します。これは、すべてのEdgeケースを合理的にカバーできるほど単純であるが、意味のある動作をテストできるほど複雑であるレベルでコンポーネントをテストすることで実現できます。そのようなテストは、バグを特定して修正するために、シンプルで意味のある、有用なものになります。これは優れたスキルであり、コードの品質と保守性が向上すると思います。

0
alzclarke