JaCoCoカバレッジレポートに基づいた単体テストケースの自動生成

本稿では、JaCoCoカバレッジレポートを活用して、より精度の高い単体テストケースを生成する方法について解説します。以下に、JaCoCoレポートの解釈からテストケース生成までのプロセスを示します。

JaCoCoはJavaコードのカバレッジを測定するツールで、XML形式のレポートを生成します。このレポートには、行カバレッジや分岐カバレッジなどの詳細情報が含まれています。

HTML形式のJaCoカバレッジレポートを解析する際、特定の要素に注目する必要があります。例えば、以下のようなHTML要素はコード行のカバレッジ状況を示しています:

<span class="pc bpc" id="L25" title="1 of 4 branches missed.">

この要素の各属性は以下の意味を持ちます:

  • class="pc bpc":部分カバレッジ(pc)であり、分岐カバレッジ(bpc)の対象であることを示します
  • id="L25":ソースコードの25行目に関連付けられていることを示します
  • title="1 of 4 branches missed":4つの分岐のうち1つが未カバレッジであることを示します

次に、TictactoeクラスのcheckXメソッドのカバレッジ状況を分析します。以下にメソッドのHTMLレポートを示します:

private void checkX(int x) {
<span class="pc bpc" id="L25" title="1 of 4 branches missed.">if (x < 1 || x > 3) {</span>
<span class="fc" id="L26">throw new RuntimeException("X is out of board");</span>
}

このレポートから、checkXメソッドの分岐カバレッジが100%ではないことがわかります。具体的には、条件式(x < 1 || x > 3)の偽の分岐(xが1から3の間の場合)がテストされていません。

この状況を改善するため、JUnit 5とAssertJを使用したテストケースを以下のように生成します:

import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class TictactoeTest {
    
    private final Tictactoe game = new Tictactoe();
    
    @Test
    public void checkX_WhenXIsOutOfBounds_ThenThrowException() {
        // 境界値外の入力で例外がスローされることを検証
        RuntimeException exception = assertThrows(RuntimeException.class, () -> {
            game.checkX(0); // 境界値未満
        }, "X座標が範囲外の場合に例外がスローされるべきです");
        
        assertThat(exception.getMessage()).isEqualTo("X is out of board");
        
        // 上限値超えのテスト
        exception = assertThrows(RuntimeException.class, () -> {
            game.checkX(4); // 境界値超え
        });
        
        assertThat(exception.getMessage()).isEqualTo("X is out of board");
    }
    
    @Test
    public void checkX_WhenXIsWithinBounds_ThenNoException() {
        // 境界値内の入力で例外がスローされないことを検証
        assertDoesNotThrow(() -> {
            game.checkX(1); // 下限値
            game.checkX(2); // 中間値
            game.checkX(3); // 上限値
        }, "X座標が有効範囲内の場合に例外がスローされるべきではありません");
    }
}

このテストクラスは、以下のシナリオをカバーしています:

  1. X座標が1未満の場合に例外がスローされること
  2. X座標が3を超える場合に例外がスローされること
  3. X座標が1から3の間の場合に例外がスローされないこと

これらのテストケースを実行することで、checkXメソッドの分岐カバレッジを100%に改善できます。

同様のアプローチを他のメソッドにも適用することで、プロジェクト全体のテストカバレッジを向上させることが可能です。JaCoCoレポートを定期的に確認し、未カバレッジの分岐を特定して適切なテストケースを追加することが重要です。

タグ: JaCoCo 単体テスト JUnit5 AssertJ コードカバレッジ

5月15日 19:11 投稿