PITestによる突然変異テスト

PITestを使用した突然変異テスト

1. 概要

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

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

2. Mavenの依存関係

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


    org.pitest
    pitest-parent
    1.1.10
    pom

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


    org.pitest
    pitest-maven
    1.1.10
    
        
            com.example.testing.mutation.*
        
        
            com.example.mutation.test.*
    
     

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ライブラリを使用してcode and mutation coverageに焦点を当てます。

4. コードカバレッジ

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

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

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

残念ながら、100%のコードカバレッジスコアはすべての行が少なくとも1回実行されたことを意味するだけなので、コードカバレッジメトリックはかなりineffectiveになることがありますが、tests accuracyまたはuse-cases completenessについては何も述べていません。そのため、ミューテーションテストが実際に重要になります。

5. 突然変異カバレッジ

ミューテーションテストは、コード内のimprove the adequacyのテストとidentify defectsに使用されるテスト手法です。 アイデアは、生産コードを動的に変更し、テストを失敗させることです。

良いテストは失敗する

コードの各変更はmutantと呼ばれ、その結果、mutationと呼ばれるプログラムのバージョンが変更されます。

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

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

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

  • 100%の回線カバレッジ:7/7

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

明らかに、テストはすべての実行パスをスイープするため、ラインカバレッジスコアは100%です。 一方、PITestライブラリは8 mutantsを導入し、そのうち5つが強制終了され、失敗しましたが、3つは存続しました。

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

image


 


ミューテーションカバレッジテストを実行するときのmutators active by defaultは次のとおりです。

  • INCREMENTS_MUTATOR

  • VOID_METHOD_CALL_MUTATOR

  • RETURN_VALS_MUTATOR

  • MATH_MUTATOR

  • NEGATE_CONDITIONALS_MUTATOR

  • INVERT_NEGS_MUTATOR

  • CONDITIONALS_BOUNDARY_MUTATOR

PITestミューテーターの詳細については、公式のdocumentation pageリンクを確認してください。

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

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

突然変異とは何かがわかったので、突然変異スコアをkilling the surviving mutants改善する必要があります。

例として、6行目の最初の突然変異(否定された条件付き)を取り上げましょう。 コードスニペットを変更しても、突然変異体は生き残りました。

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

To:

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

テストに合格するので、the mutation survivedです。 アイデアは、will fail, in case the mutant is introducedという新しいテストを実装することです。 残りの変異体についても同じことができます。

@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レポートに示されているように、all the mutations were killedが確認されます。

  • 100%の回線カバレッジ:7/7

  • 100%の変異カバレッジ:8/8

7. PITestテストの構成

突然変異テストはリソースを大量に消費する場合があるため、テストの有効性を向上させるために適切な設定を行う必要があります。 targetClassesタグを使用して、変更するクラスのリストを定義できます。 突然変異テストは、時間がかかり、リソースが重要になるため、現実世界のプロジェクトのすべてのクラスに適用することはできません。

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


    
        com.example.testing.mutation.*
    
    
        com.example.mutation.test.*
    
    
        CONSTRUCTOR_CALLS
        VOID_METHOD_CALLS
        RETURN_VALS
        NON_VOID_METHOD_CALLS
    

さらに、PITestライブラリには、customize your testing strategiesで使用できるさまざまなオプションが用意されています。たとえば、maxMutationsPerClassオプションを使用して、クラスごとに導入されるミュータントの最大数を指定できます。 公式Maven quickstart guideのPITestオプションの詳細。

8. 結論

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

また、mutation coverage scoreを改善しながら、基本的なPITestレポートを分析する方法も確認しました。

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

リンクされたGitHub projectで、この記事で提供されている例を確認できます。