単体テストはソフトウェア品質の基盤であり、その実施にはテストフレームワークが欠かせません。フレームワークはテストコードの記述・実行・管理を効率化し、CI/CDやカバレッジ測定ツールと連携することで自動化や品質分析を可能にします。
これらのテストツールの中心には「テストコード」があり、テストコードがなければフレームワークもツールも機能せず、品質保証は成立しません。つまり、テストコードは信頼性の高いソフトウェア開発を支える土台であり、不可欠な資産なのです。
しかし、テストコードの作成は時間がかかることが多く、テストコードを書くのに抵抗がある開発者も多いのも事実です。
そして、十分なテストコードの網羅度の指標として、コードカバレッジがあります。
今回はコードカバレッジの概要や種類、テスト設計との関係について解説します。
コードカバレッジとは
コードカバレッジとは、ソースコードのテスト網羅率を示す指標です。
具体的には、テストが実行されたコードの行数や分岐の割合を測定し、どれだけのコードがテストされているかを数値化します。
例えば、以下のようなコードがあるとします。(プログラミング言語はPythonのイメージです。)
| “`python def add_or_subtract(a, b, operation): if operation == ‘add’: return a + b elif operation == ‘subtract’: return a – b else: raise ValueError(“Invalid operation”) “` |
そして、このコードに対して以下のテストケースを考えます。(ここではPythonのテストツールであるunittestをイメージしています。)
| “`python import unittest class TestAddOrSubtract(unittest.TestCase): def test_add(self): self.assertEqual(add_or_subtract(1, 2, ‘add’), 3) def test_subtract(self): self.assertEqual(add_or_subtract(5, 3, ‘subtract’), 2) “` |
この場合、 `add_or_subtract` 関数のコードカバレッジ66%となります。
これは、ValueErrorを発生させるケースがテストされていないためです。そこで、以下のようなテストケースを追加すれば、カバレッジを100%にできます。
| “`python def test_invalid_operation(self): with self.assertRaises(ValueError): add_or_subtract(1, 2, ‘multiply’) “` |
これがテストカバレッジ率の基本的な考え方です。
1-1 コードカバレッジの重要性
コードカバレッジは、テストがどれだけコードを網羅しているかを示す重要な指標です。開発者がテストの質を向上させるための手助けとなります。
テストされていないコードがあるということは、実運用の中でそのロジックを通過した場合に、その挙動が予期せぬものになる可能性があるということです。コードカバレッジが高ければ、そういったリスクを減らすことができます。
1-2 「カバレッジ率が100%=バグがない」わけではない
コードカバレッジ率が100%であったとしても、不具合がないとは限りません。
カバレッジ率はあくまでテストの網羅性を示す指標であり、テストケースの質や設計が不十分であれば、バグが残る可能性があります。また、そもそもシステムのロジックや要件定義に不具合があれば、カバレッジ率が高くてもバグは発生します。
つまり、テストコード自体の品質が十分でないと、不具合の発見はできません。カバレッジ率だけを追求するのではなく、テストケースの設計や実装の質を高めることが重要です。

コードカバレッジの種類
コードカバレッジには、いくつかの種類があります。それぞれのカバレッジの特徴と適用シーンを理解することが、効果的なテスト設計に繋がります。
| カバレッジの種類 | 特徴 | 適用シーン |
| ステートメントカバレッジ | 処理の網羅性を測定 | 基本的なテスト、シンプルなコード |
| ブランチカバレッジ | 条件分岐の網羅性を測定 | 条件分岐が多いコード、複雑なロジック |
| 関数カバレッジ | 関数の実行率を測定 | モジュール化されたコード、ライブラリのテスト |
| 条件カバレッジ | 条件式の各部分の評価を測定 | 複雑な条件式、ビジネスロジックのテスト |
| 修正条件カバレッジ | 条件の組み合わせを測定 | 複数の条件が組み合わさる場合のテスト |
| パスカバレッジ | 実行パス全体を測定 | 複雑なロジック、すべての実行パスをテストしたい場合 |
ステートメントカバレッジを基本として、条件分岐などを考慮しながら、詳細なテスト設計を行うことが重要です。
安全性や堅牢性が求められるシステムほど、ブランチカバレッジや条件カバレッジなど、複雑なカバレッジを考慮したテスト設計が求められます。
2-1 ステートメントカバレッジ
ステートメントカバレッジは、コードの各行が少なくとも一度は実行されたかを測定します。これは最も基本的なカバレッジの形式で、ソースコード内の命令、処理に対するテストの実行率を示します。
テストケースの作成は容易ですが、分岐の網羅性は低いため、複雑なロジックや条件分岐が多いコードでは十分なカバレッジを提供できません。
2-2 ブランチカバレッジ
ブランチカバレッジは、条件分岐(if文やswitch文など)の各分岐が実行されたかを測定します。これにより、条件分岐の網羅性を確認できます。例えば、if文の真と偽の両方がテストされているかをチェックします。
ステートメントカバレッジよりも詳細な情報を提供し、特に条件分岐が多いコードに対して有効です。
2-3 関数カバレッジ
関数カバレッジは、コード内の各関数が少なくとも一度は呼び出されたかを測定します。
これは、関数の実行率を示し、特に大規模なコードベースで有用です。関数単位でのテストが行われているかを確認するため、特にモジュール化されたコードやライブラリのテストに適しています。
2-4 条件カバレッジ
条件カバレッジは、条件式の各部分が真と偽の両方で評価されたかを測定します。これは、複雑な条件式の網羅性を確認するのに役立ちます。
例えば、`if (a > 0 && b < 10)` の場合、`a > 0` と `b < 10` の両方が真と偽で評価される必要があります。
各条件と、その組み合わせによる網羅性を確認するため、より詳細なテスト設計が可能になります。特に、複数の条件が組み合わさる場合に有効です。
2-5 複合条件カバレッジ(MC/DC)
修正条件カバレッジは、条件カバレッジの一歩進んだ形式で、複数の条件が組み合わさった場合の網羅性を測定します。
これは、各条件が独立して評価されるだけでなく、組み合わせによる影響も考慮します。たとえば、`if (a > 0 && b < 10 && c == 5)` の場合、`a`, `b`, `c` の各条件が真と偽で評価されるだけでなく、それらの組み合わせによる影響も確認します。
このカバレッジは、条件式の複雑さをより深く理解するために有用です。より安全性が求められるシステムや、複雑なビジネスロジックを持つコードに適しています。
2-6 パスカバレッジ
パスカバレッジは、コードの実行パス全体を測定します。
これは、特に複雑なロジックや多くの条件分岐がある場合に有用です。すべての可能な実行パスがテストされているかを確認します。
理論上は、すべての実行パスをテストすることで、バグの発見や品質の向上が期待できます。しかし、実際にはすべてのパスをテストするのは困難であり、現実的には主要なパスに焦点を当てることが一般的です。
コードカバレッジの基準
コードカバレッジを考える上で、どの程度のカバレッジを目指すかは重要なポイントです。
ただし、コードカバレッジ率について、明確なガイドラインはありません。ここでは有名なテック企業を例に挙げて、一般的な基準を紹介します。
-
Google
– 60%を許容範囲
– 75%を称賛
– 90%を模範的
– 90%を95%にするのにこだわるべきではない -
SonarQube
– 新しいコードについて、80%を推奨 -
Microsoft
– 60〜70%を最低限
– 70~80%が最適
– 80〜100%は過剰
このような各社の基準を参考にすると、カバレッジ率70〜80%が一般的な目標値となるでしょう。そこにプロジェクトの性質やチームの状況に応じて調整を加える形になります。
カバレッジが低い(ここでは70%未満)場合は、テストの質や設計を見直す必要があります。逆に、カバレッジが高い(90%以上)場合では、テストの質を維持しつつ、無駄なテストケースを減らすことが重要です。テストケースが多すぎると、保守性や新機能の開発生産性が低下する可能性があります。
コードカバレッジを高めるテスト設計の重要な役割
次に、テスト設計とカバレッジの関係について解説します。テスト設計は、コードカバレッジを高めるための重要な要素です。最適なテスト設計は、カバレッジを向上させるだけでなく、テストの質や効率も高めます。
この章ではテストケースの作成や実行におけるテスト設計の役割について解説します。
4-1 テストケースの網羅性を確保
テスト設計では、コードの各部分が適切にテストされるように、テストケースを設計します。
その結果として、コードカバレッジを高めるのにつながります。
特に、条件分岐や例外処理のパスを重点的にテストすることで、カバレッジの向上とコードの網羅性を確保できます。
4-2 テストの効率を向上
テスト設計は、テストの効率を向上させるためにも重要です。
適切なテストケースの設計により、無駄なテストを避け、必要十分なテストに集中できます。これは、テストの実行時間やリソースの消費を最小限に抑えるのに必要です。
4-3 テストの保守性を高める
テスト設計は、テストの保守性を高める上でも重要な役割を担います。
テストケースの粒度を揃えることで、テストの保守性が向上します。例えば、類似したコードに対してテストを共通化して再利用性を高める、関数単位・機能単位でのテストにより、テストケースの一貫性を保つことができます。
カバレッジを高めるテスト設計の実践ポイント
最後に、カバレッジを高めるためのテスト設計の実践ポイントを解説します。
これらのポイントを考慮することで、効果的なテスト設計が可能になるでしょう。
-
テスト観点の明確化
どの機能やロジックをテストするかを明確にし、テストケースを設計します。 -
無駄なテストとテスト漏れを避ける
テストケースが多すぎると、保守性や新機能の開発生産性が低下します。一方で、テストケースが少なすぎると、バグの発見が難しくなりますので、適切なバランスを保つことが重要です。 -
テストの粒度を揃える
テストケースの粒度を揃えると、テストの保守性が向上します。例えば、関数単位でのテストや、機能単位でのテストを行うことで、テストケースの一貫性を保てます。 -
分岐と例外パスに注目する
条件分岐や例外処理のパスを重点的にテストし、コードの網羅性を高めます。特に、条件分岐が多いコードでは、ブランチカバレッジや条件カバレッジを意識したテスト設計が重要です。 -
自動化ツールとの連携
テスト自動化は、テスト効率を高め、カバレッジ向上に寄与します。自動化ツールを活用して定期的にテストを実行し、カバレッジの維持・向上を図ります。 -
カバレッジツールの活用
コードカバレッジ測定ツールを活用し、テストケースの網羅性を確認します。これはテストケースの不足や冗長な部分を特定し、改善に役立ちます。
コードカバレッジツールとコードレビューを組み合わせることで、コードのカバレッジ率の低い状態ではマージ対象外とするなどのルール設定も可能です。
これはテスト漏れの防止や、想定外の不具合防止に役立ちます。
まとめ
今回は、コードカバレッジを高める点に注目し、テスト設計の考え方を解説しました。コードカバレッジは、テストの網羅性を示す重要な指標であり、テスト設計においてはその向上が求められます。
ただし、過剰なカバレッジを追求するのではなく、適切なバランスを保つことが重要です。
バルテスはテスト専門企業として、テスト設計や自動化のご支援を行っています。
テストに関する課題や悩みをお持ちの方は、ぜひバルテスにご相談ください。