1. 概要

デフォルトでは、 JUnitは、決定論的であるが予測できない順序 MethodSorters.DEFAULT )を使用してテストを実行します。

ほとんどの場合、その動作は完全に問題なく、許容範囲内です。 ただし、特定の順序を適用する必要がある場合があります。

2. JUnit5でのテスト順序

JUnit 5では、 @TestMethodOrderを使用して、テストの実行順序を制御できます。

後で説明するように、独自のMethodOrdererを使用できます。

または、次の3つの組み込み注文者から1つを選択できます。

  1. 英数字注文
  2. @Orderアノテーション
  3. 順不同

2.1. 英数字の注文を使用する

JUnit 5には、英数字順にテストを実行するための一連の組み込みのMethodOrderer実装が付属しています。

たとえば、 MethodOrderer.MethodName を提供して、名前と正式なパラメータリストに基づいてテストメソッドをソートします。

@TestMethodOrder(MethodOrderer.MethodName.class)
public class AlphanumericOrderUnitTest {
    private static StringBuilder output = new StringBuilder("");
    
    @Test
    void myATest() {
        output.append("A");
    }
    
    @Test
    void myBTest() {
        output.append("B");        
    }
    
    @Test
    void myaTest() {
        output.append("a");
    }
 
    @AfterAll
    public static void assertOutput() {
        assertEquals("ABa", output.toString());
    }
}

同様に、 MethodOrderer.DisplayName を使用して、表示名に基づいて英数字でメソッドを並べ替えることができます。

MethodOrderer.Alphanumericは別の方法であることに注意してください。 ただし、この実装は非推奨であり、6.0で削除される予定です。

2.2. @Orderアノテーションの使用

@Order アノテーションを使用して、テストを特定の順序で実行するように強制できます。

次の例では、メソッドは firstTest()、次に secondTest()、最後に thirdTest()を実行します。

@TestMethodOrder(OrderAnnotation.class)
public class OrderAnnotationUnitTest {
    private static StringBuilder output = new StringBuilder("");
    
    @Test
    @Order(1)    
    void firstTest() {
        output.append("a");
    }
    
    @Test
    @Order(2)    
    void secondTest() {
        output.append("b");
    }
 
    @Test
    @Order(3)    
    void thirdTest() {
        output.append("c");
    }
 
    @AfterAll
    public static void assertOutput() {
        assertEquals("abc", output.toString());
    }
}

2.3. ランダムオーダーの使用

MethodOrderer.Random 実装を使用して、テストメソッドを疑似ランダムに並べ替えることもできます。

@TestMethodOrder(MethodOrderer.Random.class)
public class RandomOrderUnitTest {

    private static StringBuilder output = new StringBuilder("");

    @Test
    void myATest() {
        output.append("A");
    }

    @Test
    void myBTest() {
        output.append("B");
    }

    @Test
    void myCTest() {
        output.append("C");
    }

    @AfterAll
    public static void assertOutput() {
        assertEquals("ACB", output.toString());
    }

}

実際のところ、JUnit5はSystem.nanoTime()をデフォルトのシードとして使用してテストメソッドを並べ替えます。 これは、繰り返し可能なテストでメソッドの実行順序が同じでない可能性があることを意味します。

ただし、 junit.jupiter.execution.order.random.seed プロパティを使用してカスタムシードを構成し、繰り返し可能なビルドを作成できます。

カスタムシードの値は、junit-platform.propertiesファイルで指定できます。

junit.jupiter.execution.order.random.seed=100

2.4. カスタムオーダーの使用

最後に、 MethodOrderer インターフェイスを実装することで、独自のカスタムオーダーを使用できます。

CustomOrder では、名前に基づいて、大文字と小文字を区別しない英数字の順序でテストを並べ替えます。

public class CustomOrder implements MethodOrderer {
    @Override
    public void orderMethods(MethodOrdererContext context) {
        context.getMethodDescriptors().sort(
         (MethodDescriptor m1, MethodDescriptor m2)->
           m1.getMethod().getName().compareToIgnoreCase(m2.getMethod().getName()));
    }
}

次に、 CustomOrder を使用して、前の例と同じテストを myATest() myaTest()、最後に myBTest( )

@TestMethodOrder(CustomOrder.class)
public class CustomOrderUnitTest {

    // ...
 
    @AfterAll
    public static void assertOutput() {
        assertEquals("AaB", output.toString());
    }
}

2.5. デフォルトの順序を設定する

JUnit 5は、junit.jupiter.testmethod.order.defaultパラメーターを介してデフォルトのメソッド順序を設定する便利な方法を提供します。

同様に、junit-platform.propertiesファイルでパラメーターを構成できます。

junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$DisplayName

デフォルトの順序付けは、@TestMethodOrderで修飾されていないすべてのテストに適用されます。

言及すべきもう1つの重要なことは、指定されたクラスがMethodOrdererインターフェースを実装する必要があるということです。

3. JUnit4でのテスト順序

まだJUnit4を使用している場合、テストを注文するためのAPIは少し異なります。

以前のバージョンでもこれを実現するためのオプションを見ていきましょう。

3.1. MethodSorters.DEFAULTの使用

このデフォルトの戦略では、ハッシュコードを使用してテストメソッドを比較します。

ハッシュ衝突の場合、辞書式順序が使用されます。

@FixMethodOrder(MethodSorters.DEFAULT)
public class DefaultOrderOfExecutionTest {
    private static StringBuilder output = new StringBuilder("");

    @Test
    public void secondTest() {
        output.append("b");
    }

    @Test
    public void thirdTest() {
        output.append("c");
    }

    @Test
    public void firstTest() {
        output.append("a");
    }

    @AfterClass
    public static void assertOutput() {
        assertEquals(output.toString(), "cab");
    }
}

上記のクラスでテストを実行すると、 assertOutput()を含むすべてのテストに合格することがわかります。

3.2. MethodSorters.JVMの使用

もう1つの順序付け戦略は、MethodSorters.JVMです。

この戦略は、実行ごとに異なる可能性のある自然なJVMの順序を利用します

@FixMethodOrder(MethodSorters.JVM)
public class JVMOrderOfExecutionTest {    
    // same as above
}

このクラスでテストを実行するたびに、異なる結果が得られます。

3.3. MethodSorters.NAME_ASCENDINGの使用

最後に、この戦略は、辞書式順序でテストを実行するために使用できます。

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class NameAscendingOrderOfExecutionTest {
    // same as above
    
    @AfterClass
    public static void assertOutput() {
        assertEquals(output.toString(), "abc");
    }
}

このクラスでテストを実行すると、 assertOutput()を含むすべてのテストに合格していることがわかります。 これにより、アノテーションで設定した実行順序が確認されます。

4. 結論

このクイック記事では、JUnitで使用可能な実行順序を設定する方法について説明しました。

いつものように、この記事で使用されている例は、GitHubにあります。