100%のコードカバレッジは夢物語ですか?


28

重いjquery / backbonejs Webアプリケーションで100%のコードカバレッジを期待することは可能ですか?javascript / jqueryで実際のコードカバレッジが92%から95%前後で推移する場合、100%のカバレッジが満たされないためにスプリントに失敗するのは妥当ですか?


7
「スプリントに失敗」は奇妙に不吉に聞こえます…
ドナルフェローズ

5
それは漸近線です。
ロバートハーベイ

12
完全にカバーしていても、いくつかのバグが見つからないので、その番号に依存してすべてを修正しないでください
ラチェットフリーク

11
何でも可能です。本当の問題は、100%のコードカバレッジの価値が時間とリソースのコストに見合うかどうかです。
JohnFx

5
100%(またはその他の数)の自動テストカバレッジが魔法のようにコードを改善するという根本的な仮定が夢のようなものであるのに、なぜこれを心配しているのですか?
メイソンウィーラー

回答:


30

それは非現実的であるのと同様に現実的です。

現実的
コードベース全体をカバーすることが示されている自動テストを行っている場合、100%のカバレッジを主張するのが妥当です。
また、プロジェクトの重要性にも依存します。より重要なほど、完全なコードカバレッジを期待/要求するのがより合理的です。
これは、小規模から中規模のプロジェクトで簡単に実行できます。

非現実的
あなたは0%のカバレッジで開始しています...
このプロジェクトは巨大であり、再現やトリガーが困難な多くのエラーパスがあります。
経営陣は、補償範囲を確保するためにコミット/投資することを嫌います。

カバレッジのないものからまともなものまで、さまざまなプロジェクトに取り組んできました。100%のプロジェクトは決してありませんが、100%に近いカバレッジを望んでいたことは確かです。
最終的には、チームが製品を出荷するのに快適であるために、既存のカバレッジが必要なケースを十分に満たしているかどうかが問題です。

失敗がプロジェクトに与える影響はわかりませんので、92%または95%で十分なのか、それとも100%が本当に必要なのかはわかりません。または、そのことについては、100%完全にあなたがそれを期待するすべてをテストします。


30
...そして、100%のコードカバレッジがあるからといって、100%のブランチカバレッジがあるわけではありません。そのため、100%のコードカバレッジであっても、多くが欠落する可能性があります。
ブライアンオークリー

3
プロジェクトサイズの場合は+1。より小さく、再利用可能な、テスト可能なコンポーネントに分解することで、95%をカバーすることができました。100%のカバレッジは必要ありません。統合テストは、単体テストのギャップをカバーする必要があります。
Apoorv Khurasia

5
@BryanOakley ...また、あなたのテストは無意味かもしれませんし、何もテストさえしないかもしれません
David_001

5
@BryanOakleyそして、100%の分岐カバレッジでも、分岐の特定の組み合わせが問題を引き起こす可能性があります。(たとえば、2つの連続したIFステートメントは、別々のテストで分岐することができますが、両方に入るテストが欠落しています。完全な分岐カバレッジですが、1つの実行パスが欠落しています)
Izkata

4
すべての実行パスを含む100%の分岐カバレッジでさえ十分ではありません。たぶん、いくつかのエラーは、あなたが枝のいくつかの組み合わせを取るときに発生し、あなたには、いくつかの外部入力を持っている、不正な形式の日付を言います。すべてのケースがカバーされる可能性はありません。同時に、100%未満のカバレッジで良好な信頼性を得ることができますが、入力として適切に選択されたエッジケースがあります。
アンドレア

32

誰がテストをテストしますか?

それはせいぜい非常に素朴で、理論的な意味でさえ非現実であり、ビジネスの意味では非実用的です。

  • サイクロマティックの複雑さが高いコードでは非現実的です。すべての組み合わせをカバーするには変数が多すぎます。
  • 並行処理が多いコードでは非現実的です。コードは確定的ではないため、テストの実行ごとに動作が変わるため、発生する可能性のあるすべての条件をカバーすることはできません。
  • ビジネスの意味で非現実的であり、クリティカルパスコードであるコード、つまり重要なコードと頻繁に変更される可能性のあるコードのテストを作成するだけで、実際に価値があります。

すべてのコード行をテストすることは良い目標ではありません

テストを書くのは非常に費用がかかります、それは自分で書いてテストしなければならないコードです、実際にテストしようとしているもので文書化されなければならないコードです、ビジネスロジックの変更で維持されなければならないコードですテストは古くなっているため失敗します。自動化されたテストとそれらに関するドキュメントのメンテナンスは、コードのメンテナンスよりもコストがかかる場合があります。

これは、単体テストと統合テストが役に立たないということではなく、それらが意味をなす場合のみであり、人を殺すことができる業界の外では、コードベースのすべてのコード行を試してテストすることは意味がありません。これらの致命的な多くの人々がすぐにコードベースを殺す以外に、100%のコードカバレッジが伴うであろう投資に対する肯定的な利益を計算することは不可能です。

停止の問題:

計算可能性理論では、停止する問題は、任意のコンピュータープログラムの記述と入力から、プログラムが実行を終了するか、永遠に実行を続けるかを決定する問題です。

Alan Turingは1936年に、すべての可能なプログラム入力ペアの停止問題を解決する一般的なアルゴリズムが存在できないことを証明しました。この証明の重要な部分は、コンピューターとプログラムの数学的定義であり、チューリングマシンとして知られるようになりました。停止の問題はチューリングマシン上では決定できません。これは、決定問題の最初の例の1つです。

あなたは何かを100%証明することさえできないので、なぜそれをあなたの目標にしますか?

単純明快、ほとんどの場合、それはビジネスに意味をなしません。


7
これは本当に受け入れられた答えである必要があります。100%のコードカバレッジは、0%とほぼ同じくらい悪いです。
リャサル

1
「すべての組み合わせをカバーするには変数が多すぎます。」これは、100%のコードカバレッジを得ることとは関係ありません。コードの行が記述されるのに十分重要であり、維持するのに十分重要である場合、テストでカバーされるのに十分重要です。テストでカバーされていない場合、唯一の安全な仮定は機能しないことです。一部のコードでは、ビジネスの観点からテストするのは理にかなっていません。これは、ビジネスの観点からは意味をなさない、まったく同じコードです。
still_dreaming_1

2
そのためgetXXX()/setXXX()、値オブジェクトの単純な単純な割り当てコンストラクターをカバーするテストケースを作成することは、時間とリソースの有効な使用であると思います。実際にはそうではなく、それをバックアップするための現実世界の経験に欠ける非常に素朴な意見です。テストコードは、維持する必要があるコードであることを忘れないでください。問題を解決するために書くコードが少なければ少ないほど、すべてのケースで優れてます。

「循環的複雑度の高いコードでは非現実的です。すべての組み合わせをカバーするには変数が多すぎます。」-もちろん、そのため、このようなコードを小さな循環的複雑度を持つ小さな部分に分割する必要があるため、テストが容易になります。このようにリファクタリングすることはテストに不可欠です-テストを簡単にします。
プレドラグストヤディノビッチ

17

ほとんどの場合、100%のコードカバレッジは、少し「だまされた」ことを意味します。

  • システムの頻繁に変更される複雑な部分(GUIなど)は、宣言型テンプレートまたは他のDSLに移動されました。
  • 外部システムに触れるすべてのコードは、ライブラリによって分離または処理されています。
  • 他の依存関係、特に副作用を必要とする依存関係についても同じことが言えます。

基本的に、テストが困難な部分は、必ずしも「コード」としてカウントされない領域に迂回されています。常に現実的ではありませんが、テストの支援とは別に、これらのすべてのプラクティスによりコードベースの作業が容易になることに注意してください。


DSLへの移行はいかがですか?
back2dos

2
@ back2dos-埋め込まれたpythonスクリプトを単体テストするかもしれませんが、htmlテンプレートやCSSを単体テストしたり、カバレッジの推定に向けてそれらの行をカウントしたりすることはないでしょう。
ダンモネゴ

12

100%の分岐カバレッジの印象的な実世界の例については、SQLiteのテスト方法を参照してください。

あなたの質問は具体的にはまったく異なるタイプのソフトウェア製品であるjavascriptについて具体的に尋ねていることを理解していますが、十分な動機で何ができるのかを認識したいと思います。


9

特定のアプリケーションのすべての部分の単体テストの100%コードカバレッジは、新しいプロジェクトであっても夢のようなものです。そうだといいのですが、外部の依存関係をいかに抽象化しようとしても、コードをカバーできない場合があります。たとえば、コードでWebサービスを呼び出す必要があるとします。インターフェイスの背後でWebサービス呼び出しを非表示にして、その部分をモックし、Webサービスの前後でビジネスロジックをテストできます。ただし、Webサービスを呼び出す必要がある実際の部分は、ユニットテストを行うことはできません(とにかくうまくテストできます)。別の例は、TCPサーバーに接続する必要がある場合です。インターフェイスの背後にあるTCPサーバーに接続するコードを非表示にすることができます。ただし、TCPサーバーに物理的に接続するコードはユニットテストできません。何らかの理由でダウンしていると、ユニットテストが失敗するためです。また、ユニットテストはいつ呼び出されても常にパスする必要があります。

経験則として、ビジネスロジックはすべて100%のコードカバレッジを持つ必要があります。ただし、外部コンポーネントを呼び出す必要のある部分は、可能な限り100%近くのコードカバレッジを持つ必要があります。あなたが到達できない場合、私はあまり汗をかかないでしょう。

さらに重要なことは、テストは正しいですか?彼らはあなたのビジネスと要件を正確に反映していますか?単にコードカバレッジを持つためだけにコードカバレッジを持つことは、誤ってテストするか、誤ったコードをテストするだけであれば、何の意味もありません。そうは言っても、テストが良好であれば、92〜95%のカバレッジが傑出しています。


1
エラーケースと応答失敗の奇妙な組み合わせが発生したときに何が起こるかをテストすることは、非常に難しい場合があります。
ドナルドフェローズ

ユニットテストの魅力の一部である、これらの厄介な問題が提示されたときにシステムが何をするのか理解していませんか?また、単体テストと統合テストの間には少し混乱があります。
ピータースミス

これunit testingintegration testing、あなたが書いていないテストコードがテストであると矛盾しintegrationます。TCPスタックは、テストするべきではないOSにあります。これは、それを書いた人によって既にテストされていると仮定する必要があります。

4

100%のテストカバレッジを可能にするという特定の目標を持ってコードが設計されていない限り、100%は達成できない可能性があります。理由の1つは、防御的にコーディングする場合-必要な場合-システムの知識があれば、発生しないはずの状況または発生しない状況を処理するコードが必要になる場合があることです。そのようなコードをテストでカバーすることは、定義上非常に難しいでしょう。そのようなコードを持たないことは危険かもしれません-あなたが間違っていて、この状況が256回のうち1回起こる場合はどうですか?関係のない場所に変更があり、不可能なことが可能になった場合はどうなりますか?など。したがって、100%を「自然な」手段で達成するのはかなり難しいかもしれません-例えば、メモリを割り当てるコードがあり、メモリマネージャをモックアウトしない限り、失敗したかどうかをチェックするコードがある場合(簡単ではないかもしれません) 「メモリ不足」を返すテストを作成し、そのコードをカバーするのは難しいかもしれません。JSアプリケーションの場合、異なるブラウザーで発生する可能性のあるDOMの癖、外部サービスで発生する可能性のある障害などに関する防御的なコーディングが必要になる場合があります

したがって、できる限り100%に近づけるように努力し、デルタに正当な理由を持たせる必要があると思いますが、必ずしも100%が必ずしも失敗するわけではありません。95%は、5%が何であるかに応じて、大きなプロジェクトでは問題ありません。


コードが通常の環境で実稼働環境で実行されることを想定していないからといって、テストで実行されるような方法でコードを記述できないことを意味するわけではありません。その異常なコードが正しく実行されることはどれほど重要ですか?テストでカバーするのに十分重要ですか?テストでカバーするだけの重要性がない場合、そのケースを処理するのに十分な重要性はないと主張します。テストを必要としないコードは、存在する必要がなく、削除する必要があるコードです。
still_dreaming_1

2

新しいプロジェクトを開始し、テストファーストの方法論を厳密に使用している場合、テストが完了した時点ですべてのコードが呼び出されるという意味で、100%のコードカバレッジを持つことは完全に合理的です。実行されました。ただし、メソッドの可視性のために個々のメソッドやアルゴリズムをすべて明示的に直接テストしたわけではない場合があります。また、場合によっては間接的にでも一部のメソッドをテストしていない場合があります。

特にこの目標を達成できるようにシステムを設計していない場合、およびテストの可能性に設計の努力を集中している場合は、おそらくコードの100%をテストすることは潜在的に費用のかかる作業です。特にプロジェクトが大規模な場合、特定の要件を満たすようにアプリケーションを設計します。申し訳ありませんが、妥協することなく両方の方法でそれを実現することはできません。

以前にテストが維持されていない、または含まれていない既存のプロジェクトにテストを導入する場合、労力を上回る演習のコストなしで100%のコードカバレッジを実現することは不可能です。期待できる最善の方法は、最も呼び出されるコードの重要なセクションにテストカバレッジを提供することです。

javascript / jqueryで実際のコードカバレッジが92%から95%前後で推移する場合、100%のカバレッジが満たされないためにスプリントに失敗するのは妥当ですか?

ほとんどの場合、目標を達成していない場合にのみ、スプリントを「失敗」したとみなすべきだと思います。実際、このようなケースではスプリントが失敗するとは思わない方がいいです。なぜなら、次にスプリントを定義するときにプランニングを正しく行うためには、期待を満たしていないスプリントから学ぶ必要があるからです。とにかく、コードカバレッジをスプリントの相対的な成功の要因と見なすことは合理的ではないと思います。目的は、すべてを指定どおりに動作させるのに十分なことであり、テストファーストをコーディングしている場合は、テストがこの目的をサポートすることに自信を持つことができるはずです。追加する必要があると思われる追加のテストは、事実上砂糖コーティングであるため、スプリントを満足のいく形で完成させるための費用が追加されます。


「申し訳ありませんが、何かが侵害されることなく、両方の方法でそれを実現することはできません。」それは真実ではありません。いつでも機能を縮小することも、遅くすることもできます。何かをテストする価値がない場合は、書く価値はありません。コードの行が重要な場合は、テストを続けることが重要です。テストするのに十分な重要性がない場合、維持するのに十分な重要性はありません。テストされていないコード行の唯一の安全な仮定は、動作しないことです。
-still_dreaming_1

@ still_dreaming_1、あなたは私の声明を支持し、自分自身に矛盾したようです。機能の縮小や期限の変更は妥協であり、それぞれがプロジェクトコストと利害関係者の期待に影響を与える可能性があります。これまで完全にテストされていなかったレガシーコードのテストは、実行されるコードだけでなく、元の作成者の意図を理解し、既存のレガシーコードの動作をキャプチャするテストを作成する必要がないため、非常に難しいコードが想定どおりに完全に機能すること。
S.ロビンス

私のポイントは、妥協されたもの、開発がより速く動いているためにまだ作成されていない機能または変更は、本当の妥協ではないということだと思います。とにかく正しく動作しないと想定されるだけです。それでは、それらが正しく機能するかどうかが重要でない場合、それらの変更を行うか、それらの機能を追加することのポイントは何でしたか?それらが正しく機能するかどうかが重要でない場合、これらの変更を行う必要はなく、コードから削除する必要があります。
still_dreaming_1

私はもう完全に信じていない、または少なくともあなたが話している真実の実用性の側面を、特にレガシーコードベースで理解しています。実際、100%のカバレッジを得ることは言うまでもなく、新しいコードベースで常にTDDを行うことについても完全に対立しています。一方で、あらゆる形態の論理と理由は、これらの両方が良いはずであると教えてくれますが、実際にはそれを実用的にすることはできないようです。したがって、プログラミングの世界では何かが非常に間違っています。新しいパラダイムが必要です。
still_dreaming_1

1

当然のこととしてこれを行いませんが、2つの大きなプロジェクトで行っています。とにかくセットアップされた単体テストのフレームワークを持っている場合、それは厳密には難しくありませんが、それは多くのテストになります。

あなたがそれらの最後の数行を打つことを妨げる特定の障害に遭遇していますか?そうでない場合、95%から100%のカバレッジを取得するのが簡単な場合は、それを行ってください。あなたはここに求めているので、私はそこにいると仮定するつもりです何か。それは何ですか?


これは、ここでの最良の答えの1つです。何行のコードが簡単にカバーできないのかを尋ねるのは良い質問です。これらの行をカバーするには、コードを改善してそれを実現させる必要があります。
-still_dreaming_1

0

92%は大丈夫です。本当の質問は次のように感じます:

  • 92%が現在の「新しい」標準ですか?次のスプリントに88%のテストがある場合、それは大丈夫ですか?多くの場合、これは放棄されるテストスイートの開始点です。

  • ソフトウェアが機能し、バグがないことがどれほど重要か。「テストのため」ではなく、これらの理由でテストがあります

  • 戻って不足しているテストを記入する計画はありますか?

  • なぜテストしていますか?フォーカスは機能ではなくカバーされている行の%であるようです


「ソフトウェアが機能し、バグがないことがどれほど重要ですか?」良い質問。バグの定義は何ですか?意図したとおりに機能しないもの。一部のコードが正常に機能しなくても問題ない場合は、記述しないでください。コードの要点は、それが機能することです。
still_dreaming_1

0

Martin Fowlerは彼のブログに次のように書いていますI would be suspicious of anything like 100% - it would smell of someone writing tests to make the coverage numbers happy, but not thinking about what they are doing.

ただし、ユニットレベルで100%のカバレッジを義務付ける標準もあります。たとえば、欧州の宇宙飛行共同体の規格(ECSS、欧州宇宙標準化協力)の要件の1つです。ここにリンクされている論文は、すでに完成したソフトウェアで100%のテストカバレッジを達成することを目標としたプロジェクトの興味深いストーリーを示しています。これは、単体テストを開発した関連エンジニアとの対話に基づいています。

レッスンの一部は次のとおりです。

  • 100%のカバレッジは異常ですが、達成可能です
  • 100%のカバレッジが必要な場合があります
  • 100%のカバレッジが新たなリスクをもたらします
  • 100%メトリックに最適化しないでください
  • カバレッジを最大化するための適切な戦略を開発する
  • 100%のカバレッジは、高品質のための十分な条件ではありません

0

実行可能で合理的かどうかを尋ねることは、おそらく最も役立つ質問ではありません。おそらく最も実用的な答えは受け入れられたものです。これをより哲学的なレベルで分析します。

100%のカバレッジが理想的ですが、理想的には、それは必要ではないか、達成がはるかに簡単です。私はそれが実行可能であるか合理的であるよりも自然で人間であるかどうかについて考えることを好む。

正しくプログラミングするという行為は、今日のツールではほとんど不可能です。完全に正確でバグのないコードを書くことは非常に困難です。それは自然ではありません。そのため、他に明らかなオプションはありませんが、TDDやトラッキングコードカバレッジなどの手法を使用します。しかし、最終結果がまだ不自然なプロセスである限り、人々に一貫して幸せにそれを行わせるのに苦労するでしょう。

100%のコードカバレッジを達成することは不自然な行為です。ほとんどの人にとって、それを成し遂げることを強制することは、一種の拷問でしょう。

自然な精神モデルに対応するプロセス、ツール、言語、コードが必要です。これに失敗した場合、製品の品質をテストする方法はありません。

今日そこにあるすべてのソフトウェアを見てください。それのほとんどはかなり定期的に台無しにします。これを信じたくありません。私たちは私たちの技術が魔法であり、私たちを幸せにしてくれると信じたいです。そのため、ほとんどの場合、テクノロジーが台無しになることを無視し、言い訳し、忘れることにしています。しかし、私たちが物事の正直な評価をすると、今日世に出回っているソフトウェアのほとんどはかなりくだらないものです。

コーディングをより自然にするためのいくつかの取り組みを次に示します。

https://github.com/jcoplien/trygve

https://github.com/still-dreaming-1/PurposefulPhp

後者は非常に不完全で実験的です。実はそれは私が始めたプロジェクトですが、それを完了するために時間を費やすことができれば、プログラミングの技術にとって大きな前進になると思います。基本的に、私たちが気にするクラスの振る舞いの唯一の側面をコントラクトが表現し、すでにコードとしてコントラクトを表現しているのであれば、なぜコントラクトとともにクラスとメソッドの定義だけを持たないのかという考えです。そうすれば、コントラクトはコードになり、すべてのメソッドを実装する必要はなくなります。図書館に私たちのために契約を尊重する方法を理解させてください。


-2

新しいコードで100%に到達することは非常に達成可能であるはずであり、TDDを実践している場合は、プロダクションコードのすべての行のテストを意図的に作成しているため、デフォルトでヒットする可能性があります。

ユニットテストなしで記述された既存のレガシーコードでは、多くの場合、レガシーコードはユニットテストを念頭に置いて書かれておらず、多くのリファクタリングを必要とするため、難しい場合があります。リスクとスケジュールの現実を考えると、そのレベルのリファクタリングはしばしば実用的ではないため、トレードオフを行います。

私のチームでは、100%のコードカバレッジを指定します。コードレビューでそれよりも少ない場合は、コンポーネントの技術所有者が100%が開発者に届かず、開発者の理由に同意する必要があることを話し合います。多くの場合、100%に達する問題がある場合、開発者はコードレビューの前に技術所有者に相談します。習慣を身につけて、定期的に100%ヒットするテストをレガシーコードに追加するいくつかの一般的な問題を回避するためのテクニックを学ぶと、最初に思うほど難しくないことがわかりました。

マイケルフェザーの著書「レガシーコードを効果的に使用する」は、レガシーコードにテストを追加するための戦略を考え出すうえで非常に貴重です。


-3

いいえ、不可能であり、不可能です。可能であれば、数学のすべてが有限に陥ります。たとえば、2つの64ビット整数を取り、それらを乗算する関数をどのようにテストしますか?これは常に、テストとプログラムの正しい証明の問題でした。最も些細なプログラム以外の場合、テストは少数のケースしかカバーしないため、基本的には役に立ちません。それは1,000の数字をチェックして、Goldbachの予想を証明したと言っているようなものです。


ああ!だから誰かが私がその概念の面で問題に答えなかったことに怒っています。テストは無駄です…人気があるかどうかは気にしません。それは決して機能しません。できない。最も賢いコンピューター科学者はこれを知っています(ダイクストラ、クヌース、ホアら)。あなたがeXtreme Programmingを苦しめているJavaScriptプログラマーなら、それらのクランクについては気にしないと思います。なんとか、気にする人は...くだらないコードを書く。テストの実行中にCO ^ 2を無駄にします。—つまり、もう座って考える時間があるのは誰ですか?これをコンピューターにエクスポートしました。
非常に愚かな

3
質問には「TDD」というタグが付いています。TDDはテストツールというよりも設計ツールおよび問題調査ツールであり、各「テスト」はコードが特定のコンテキストでどのように動作するかの単なる例であるため、人々は何が起こっているかを読んで理解し、安全に変更できます。TDDが適切に実行されると、コードがよりクリーンで使いやすくなり、テストを実行するだけでドキュメントが最新のものであることが確認されます。ほとんどのTDDスイートはほとんどバグをキャッチしません。彼らがそこにいるものではありません。あなたの答えは理解の欠如を裏切っているので、あなたは落胆していると思います、そしてこのコメントがそれに役立つことを願っています。
ルニボー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.