Back

コードカバレッジが本当に教えてくれること

コードカバレッジが本当に教えてくれること

テストスイートは合格しています。カバレッジレポートは85%を示しています。ダッシュボードは緑色です。しかし、その数字は本当にコードが正しく動作していることを意味しているのでしょうか?

コードカバレッジはフロントエンドテストにおいて最も目に見える指標の1つですが、頻繁に誤解されています。この記事では、カバレッジ指標が実際に何を測定しているのか、なぜ高いパーセンテージが深刻なギャップを隠す可能性があるのか、そして実際のJavaScriptプロジェクトでこれらの数値をどのように解釈すべきかを説明します。

重要なポイント

  • コードカバレッジは、テスト中にどの行が実行されたかを測定するものであり、コードが正しく動作するかどうかを測定するものではない
  • ブランチカバレッジは、特に条件分岐ロジックにおいて、行カバレッジが見逃すギャップを明らかにする
  • テストに意味のあるアサーションが欠けている場合、高いカバレッジパーセンテージは誤った自信を生み出す可能性がある
  • 異なるカバレッジプロバイダー(IstanbulとV8)は、同一のコードに対して異なる数値を報告することがある
  • カバレッジは品質スコアとしてではなく、盲点を見つけるための診断ツールとして使用する

コードカバレッジが実際に測定するもの

コードカバレッジが教えてくれるのは1つのことだけです:テスト実行中にソースコードのどの部分が実行されたか。それだけです。

コードが正しく動作したかどうかは教えてくれません。アサーションがバグを捕捉したかどうかを確認しません。エッジケースが処理されたかどうかを検証しません。カバレッジツールは単にコードを計装し、何が実行されたかを追跡するだけです。

jest --coverageを実行するか、Vitestでカバレッジを有効にすると、ツールは実行を監視してパーセンテージを報告します。これらのパーセンテージは実行を表すものであり、正確性を表すものではありません。

テストカバレッジ指標の理解

ほとんどのJavaScriptテストカバレッジツールは、いくつかの異なる指標を報告します。それぞれが異なるものを測定します。

行カバレッジは、ソースコードの各行が実行されたかどうかを追跡します。ステートメントカバレッジは実行されたステートメントをカウントします—これは、1行に複数のステートメントが存在する場合、行とは異なります。関数カバレッジは、各関数が少なくとも1回呼び出されたかどうかを報告します。

ブランチカバレッジはさらに深く掘り下げます。条件分岐ロジックを通る各パスが実行されたかどうかを追跡します。if/elseブロックには2つのブランチがあります。ブランチカバレッジは両方のパスが実行されることを要求します。

この違いが重要になる場面は次のとおりです:

function getDiscount(user) {
  if (user.isPremium || user.hasPromo) {
    return 0.2
  }
  return 0
}

user.isPremium = trueのテストは100%の行カバレッジを達成します。すべての行が実行されます。しかし、ブランチカバレッジはギャップを明らかにします:isPremiumがfalseでhasPromoがtrueの場合、または両方がfalseの場合をテストしていません。

これが、ブランチカバレッジと行カバレッジの違いが重要な理由です。行カバレッジは100%に達する一方で、論理パスが完全にテストされていない状態を残す可能性があります。

高いカバレッジが誤解を招く理由

意味のあるアサーションなしでコードを実行するテストは、バグを捕捉せずにカバレッジを膨らませます。次の例を考えてみましょう:

test('processes order', () => {
  processOrder(mockOrder)
  // アサーションなし
})

このテストは数十行を実行し、カバレッジパーセンテージを上げるかもしれません。しかし、何も検証していません。コードが間違った値を返したり、サイレントにキャッチされたエラーをスローしたり、状態を破壊したりしても、このテストは合格します。

カバレッジツールは、動作を徹底的に検証するテストと、単にコードを実行するだけのテストを区別できません。どちらもパーセンテージに対して同じようにカウントされます。

カバレッジプロバイダー:数値が変動する理由

最新のJavaScriptテストカバレッジは、異なる計装アプローチに依存しています。JestはデフォルトでIstanbulスタイルの計装を使用し、実行前にコードを変換します。VitestはIstanbulとV8ベースのネイティブカバレッジの両方をサポートしています。

これらのプロバイダーは、同一のコードとテストに対して異なる数値を報告することがあります。V8カバレッジはエンジンレベルで動作し、Istanbulのソース変換アプローチとは異なる方法でカバレッジをカウントすることがあります。

プロバイダーの切り替え、ツールのアップグレード、または設定の変更により、コードの変更なしに報告されるカバレッジが変動する可能性があります。これは一方のアプローチが間違っているという意味ではありません—それらは異なるレベルで微妙に異なるものを測定しています。

カバレッジの数値は、正確な測定値ではなく、方向性を示すシグナルとして扱ってください。

カバレッジが役立つ場面と誤解を招く場面

カバレッジが役立つ場面:

  • 完全にテストされていないファイルや関数を特定する
  • 実行されないデッドコードを見つける
  • テストし忘れたブランチを発見する
  • 時間経過に伴う傾向を追跡する(新しいコードでカバレッジが低下)

カバレッジが誤解を招く場面:

  • チームが動作のテストではなくパーセンテージを追求する
  • テストが結果をアサートせずにコードを実行する
  • 高い数値がテスト品質に対する誤った自信を生み出す
  • 閾値が開発者に浅いテストを書くようプレッシャーをかける

実際のプロジェクトでカバレッジを解釈する

カバレッジレポートは、品質スコアとしてではなく、診断ツールとして使用してください。カバーされていない行を見たときは、次のように問いかけてください:このコードパスは重要か?エラー処理、エッジケース、または重要なロジックを扱っている場合は、そのためのテストを書いてください。本当に到達不可能または些細なものである場合は、そのコードが存在すべきかどうかを検討してください。

テストの代わりにではなく、テストと一緒にカバレッジをレビューしてください。60%のカバレッジと強力なアサーションを持つファイルは、95%のカバレッジと弱いテストを持つファイルよりも多くの信頼を提供することがよくあります。

コードレビューでは、カバレッジの差分が新しいコードにテストが含まれているかどうかを特定するのに役立ちます。しかし、レビュー自体は、それらのテストが意味のある動作を検証しているかどうかを評価すべきです。

チームでカバレッジを機能させる

カバレッジの閾値は慎重に設定してください。70-80%の下限は、チームをカバレッジの見せかけに追い込むことなく、明らかなギャップを防ぎます。さらに重要なのは、ロジックが多いコードについてはブランチカバレッジに焦点を当てることです—これは行カバレッジが見逃すギャップを捕捉します。

CIでカバレッジを実行して傾向を追跡しますが、わずかな低下でビルドを失敗させないでください。リファクタリングは、テストされたコードが削除または再構築されるため、一時的にカバレッジを低下させることがよくあります。

結論

目標は数値ではありません。ユーザーが遭遇する前にテストが実際のバグを捕捉するという確信です。カバレッジは盲点を見つけるのに役立ちます。優れたテスト設計、意味のあるアサーション、そして思慮深いレビューが、実際にそれらを埋めるかどうかを決定します。

よくある質問

ほとんどのチームは、妥当な下限として70-80%を目標にしています。しかし、パーセンテージはテストしている内容よりも重要ではありません。重要なパス、エラー処理、ビジネスロジックのカバーに焦点を当ててください。意味のある検証を欠く浅いテストによる高いカバレッジよりも、強力なアサーションを持つ低いパーセンテージの方が優れていることがよくあります。

わずかなカバレッジの低下でビルドを失敗させることは避けてください。リファクタリングは、テストされたコードが削除または再構築されるため、一時的にカバレッジを低下させることがよくあります。代わりに、カバレッジの傾向を使用してパターンを特定し、プルリクエストでカバレッジの差分をレビューして、新しいコードに適切なテストが含まれていることを確認してください。

異なるカバレッジプロバイダーは異なる計装アプローチを使用します。Istanbulは実行前にコードを変換し、V8はエンジンレベルで動作します。これらのアプローチは微妙に異なるものを測定するため、プロバイダーの切り替えやツールのアップグレードにより、実際のコード変更なしに報告される数値が変動する可能性があります。

カバレッジの数値だけでなく、アサーションをレビューしてください。アサーションがないテストや、些細なチェックのみのテストは、バグを捕捉せずにカバレッジを膨らませます。ミューテーションテストツールは、小さなコード変更を導入して、動作が予期せず変更されたときにテストが実際に失敗することを検証することで役立ちます。

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay