1. 概要

ソフトウェアテストとは、ソフトウェアアプリケーションの機能を評価するために使用される手法を指します。 この記事では、コードカバレッジミューテーションテストなど、ソフトウェアテスト業界で使用されるいくつかのメトリックについて、ミューテーションの実行方法に特に関心を持って説明します。 PITestライブラリを使用してテストします。

簡単にするために、このデモンストレーションは基本的な回文関数に基づいています–回文は同じ前後を読み取る文字列であることに注意してください。

2. Mavenの依存関係

Mavenの依存関係の構成でわかるように、JUnitを使用してテストを実行し、 PITestライブラリを使用してミュータントをコードに導入します。心配しないでください。第二に、変異体とは何か。 このリンクをたどると、Maven中央リポジトリに対する最新の依存関係バージョンをいつでも検索できます。

<dependency>
    <groupId>org.pitest</groupId>
    <artifactId>pitest-parent</artifactId>
    <version>1.1.10</version>
    <type>pom</type>
</dependency>

PITestライブラリを稼働させるには、pitest-mavenプラグインをpom.xml構成ファイルに含める必要があります。

<plugin>
    <groupId>org.pitest</groupId>
    <artifactId>pitest-maven</artifactId>
    <version>1.1.10</version>
    <configuration>
        <targetClasses>
            <param>com.baeldung.testing.mutation.*</param>
        </targetClasses>
        <targetTests>
            <param>com.baeldung.mutation.test.*</param>
	</targetTests>
     </configuration>
</plugin>

3. プロジェクトの設定

Mavenの依存関係が構成されたので、この自明の回文関数を見てみましょう。

public boolean isPalindrome(String inputString) {
    if (inputString.length() == 0) {
        return true;
    } else {
        char firstChar = inputString.charAt(0);
        char lastChar = inputString.charAt(inputString.length() - 1);
        String mid = inputString.substring(1, inputString.length() - 1);
        return (firstChar == lastChar) && isPalindrome(mid);
    }
}

ここで必要なのは、実装が目的の方法で機能することを確認するための単純なJUnitテストです。

@Test
public void whenPalindrom_thenAccept() {
    Palindrome palindromeTester = new Palindrome();
    assertTrue(palindromeTester.isPalindrome("noon"));
}

これまでのところ、JUnitテストとしてテストケースを正常に実行する準備ができています。

次に、この記事では、PITestライブラリを使用したコードとミューテーションカバレッジに焦点を当てます。

4. コードカバレッジ

コードカバレッジは、自動テスト中に実行パスの何パーセントが実行されたかを測定するために、ソフトウェア業界で広く使用されています。

EclipseIDEで利用可能なEclemmaなどのツールを使用して、実行パスに基づいて効果的なコードカバレッジを測定できます。

コードカバレッジでTestPalindromeを実行した後、100 % cの超過スコアを簡単に達成できます– isPalindrome は再帰的であるため、空の入力長チェックがとにかくカバーされることは明らかです。

残念ながら、コードカバレッジメトリックは、100 % c odeカバレッジスコアがすべての行が少なくとも1回実行されたことを意味するだけであるため、効果がない場合がありますが、テストの精度については何も述べていません。またはユースケースの完全性、そしてそれがミューテーションテストが実際に重要である理由です。

5. 突然変異カバレッジ

ミューテーションテストは、テストの妥当性を改善し、コードの欠陥を特定するために使用されるテスト手法です。 アイデアは、本番コードを動的に変更し、テストを失敗させることです。

良いテストは失敗します

コードを変更するたびにmutantと呼ばれ、mutationと呼ばれるプログラムのバージョンが変更されます。

テストで失敗する可能性がある場合、ミューテーションはkilledであると言います。 また、ミュータントがテストの動作に影響を与えることができなかった場合、ミューテーションを生き残ったとも言います。

次に、ゴールオプションを org.pitest:pitest-maven:mutationCoverage に設定して、Mavenを使用してテストを実行しましょう。

target / pit-test /YYYYMMDDHHMIディレクトリでHTML形式のレポートを確認できます。

  • 100 % li neカバレッジ:7/7
  • 63%の突然変異カバレッジ:5/8

明らかに、テストはすべての実行パスをスイープするため、ラインカバレッジスコアは100%です。 一方、PITestライブラリは 8つのミュータントを導入し、そのうちの5つが殺されました–失敗を引き起こしました–しかし、3つは生き残りました。

作成されたミュータントの詳細については、com.baeldung.testing.mutation/Palindrome。java.htmlレポートを確認できます。


 


これらは、ミューテーションカバレッジテストを実行するときにデフォルトでアクティブになるミューテーターです。

  • INCREMENTS_MUTATOR
  • VOID_METHOD_CALL_MUTATOR
  • RETURN_VALS_MUTATOR
  • MATH_MUTATOR
  • NEGATE_CONDITIONALS_MUTATOR
  • INVERT_NEGS_MUTATOR
  • CONDITIONALS_BOUNDARY_MUTATOR

PITestミューテーターの詳細については、公式のドキュメントページリンクを確認してください。

回文関数が非パリンドロームおよびニアパリンドロームの文字列入力を拒否することを確認できないため、ミューテーションカバレッジスコアはテストケースの欠如を反映しています。

6. 突然変異スコアを改善する

突然変異が何であるかがわかったので、生き残った突然変異体を殺すことによって突然変異スコアを改善する必要があります。

例として、6行目の最初のミューテーション(条件付きで否定)を取り上げましょう。 コードスニペットを変更しても、ミュータントは存続しました。

if (inputString.length() == 0) {
    return true;
}

に:

if (inputString.length() != 0) {
    return true;
}

テストは合格し、それが突然変異が生き残った理由です。 アイデアは、変異体が導入された場合にが失敗する新しいテストを実装することです。 残りの変異体についても同じことができます。

@Test
public void whenNotPalindrom_thanReject() {
    Palindrome palindromeTester = new Palindrome();
    assertFalse(palindromeTester.isPalindrome("box"));
}
@Test
public void whenNearPalindrom_thanReject() {
    Palindrome palindromeTester = new Palindrome();
    assertFalse(palindromeTester.isPalindrome("neon"));
}

これで、ミューテーションカバレッジプラグインを使用してテストを実行し、ターゲットディレクトリで生成されたPITestレポートで確認できるように、すべてのミューテーションが強制終了されたことを確認できます。

  • 100 % li neカバレッジ:7/7
  • 100%の突然変異カバレッジ:8/8

7. PITestテストの構成

ミューテーションテストはリソースを大量に消費する場合があるため、テストの有効性を向上させるために適切な構成を設定する必要があります。 targetClasses タグを使用して、変更するクラスのリストを定義できます。 ミューテーションテストは、時間がかかり、リソースが重要になるため、実際のプロジェクトのすべてのクラスに適用できるわけではありません。

テストの実行に必要なコンピューティングリソースを最小限に抑えるために、ミューテーションテスト中に使用する予定のミューテーターを定義することも重要です。

<configuration>
    <targetClasses>
        <param>com.baeldung.testing.mutation.*</param>
    </targetClasses>
    <targetTests>
        <param>com.baeldung.mutation.test.*</param>
    </targetTests>
    <mutators>
        <mutator>CONSTRUCTOR_CALLS</mutator>
        <mutator>VOID_METHOD_CALLS</mutator>
        <mutator>RETURN_VALS</mutator>
        <mutator>NON_VOID_METHOD_CALLS</mutator>
    </mutators>
</configuration>

さらに、PITestライブラリには、テスト戦略のカスタマイズに使用できるさまざまなオプションが用意されています。たとえば、 maxMutationsPerClass オプションを使用して、クラスによって導入される変異体の最大数を指定できます。 公式のMavenクイックスタートガイドでPITestオプションの詳細を確認してください。

8. 結論

コードカバレッジは依然として重要な指標ですが、十分にテストされたコードを保証するには不十分な場合があることに注意してください。 そのため、この記事では、 PITestライブラリを使用して、テストの品質を保証し、テストケースを承認するためのより洗練された方法として、ミューテーションテストについて説明しました。

また、ミューテーションカバレッジスコアを改善しながら、基本的なPITestレポートを分析する方法も確認しました。

ミューテーションテストでコードの欠陥が明らかになったとしても、それは非常にコストと時間のかかるプロセスであるため、賢明に使用する必要があります。

この記事で提供されている例は、リンクされているGitHubプロジェクトで確認できます。