web-dev-qa-db-ja.com

メソッドレベル(クラスレベルではない)でjunit 4テストの順序を指定する

これは悪い習慣だと知っていますが、実行する必要があります。そうしないと、testngに切り替える必要があります。 JUnit 3のtestSuiteと同様に、クラスで実行されるテストの順序を指定する方法はありますか?

39
K Poole

あなたが確信している場合本当にこれを実行したい:より良い方法があるかもしれませんが、これが私が思いつくことができるすべてです...

JUnit4には注釈があります。_@RunWith_を使用すると、テストのデフォルトランナーをオーバーライドできます。

あなたの場合、_BlockJunit4ClassRunner_の特別なサブクラスを作成し、computeTestMethods()をオーバーライドして、実行したい順序でテストを返す必要があります。たとえば、テストをアルファベット順で実行したいとします。

_public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List computeTestMethods() {
        List list = super.computeTestMethods();
        List copy = new ArrayList(list);
        Collections.sort(copy, new Comparator() {
            public int compare(FrameworkMethod o1, FrameworkMethod o2) {
                return o2.getName().compareTo(o1.getName());
            }
        });
        return copy;
    }
}_
_@RunWith(OrderedRunner.class)
public class OrderOfTest {
    @Test public void testA() { System.out.println("A"); }
    @Test public void testC() { System.out.println("C"); }
    @Test public void testB() { System.out.println("B"); }
}_

このテストを実行すると、以下が生成されます。

C 
 B 
 A

特定のケースでは、テストを実行する順序で名前順にテストするコンパレータが必要になります。 (Google GuavaのクラスOrdering.explicit("methodName1","methodName2").onResultOf(...);のようなものを使用してコンパレータを定義することをお勧めします。onResultOfには、FrameworkMethodをその名前に変換する関数が用意されています...もちろん、自由に実装できます。

62
Michael D

特にJUnitを使用して機能テストを実行したり、永続オブジェクトをテストしたりすると、いくつかの理由がわかります。たとえば、ある種の永続ストレージに永続化されているオブジェクトArticleについて考えてみます。ユニットテストの原則「すべてのテストは並べ替え可能で、機能の特定の部分のみをテストする」に従ってArticleオブジェクトの挿入、更新、削除機能をテストしたい場合、3つのテストを行います。

  • testInsertArticle()
  • testUpdateArticle()
  • testDeleteArticle()

ただし、更新機能をテストできるようにするには、まず記事を挿入する必要があります。削除機能をテストするには、記事も挿入する必要があります。したがって、実際には、挿入機能はtestUpdateArticle()testDeleteArticle()の両方ですでにテストされています。次に、すべてを行うテストメソッドtestArticleFunctionality()を作成するのは魅力的ですが、そのようなメソッドは最終的に巨大になります(そして、Articleの機能の一部をテストするだけではありません)オブジェクト)。

同じことは、たとえばRESTful APIに対して機能テストを実行する場合にも当てはまります。 JUnitは、テストの順序が定まっていなかった場合、これらのケースにも最適です。

そうは言っても、Michael DのOrderedRunnerを拡張して、注釈を使用してテストの順序を決定しました。たとえば、各テストが依存するテストを正確に指定することで、さらに拡張できますが、これは今のところ使用しています。

これが使用方法です。 AA_testInsert()AB_testUpdate()AC_testDelete()、...、ZC_testFilter()などのような名前付けテストの必要性を回避します。

@RunWith(OrderedRunner.class)
public class SomethingTest {
    @Test
    @Order(order=2)
    public void testUpdateArticle() {
        // test update
    }

    @Test
    @Order(order=1)
    public void testInsertArticle() {
        // test insert
    }

    @Test
    @Order(order=3)
    public void testDeleteArticle() {
        // test delete
    }
}

これらのテストがファイルにどのように配置されていても、Antを使用してEclipse内から実行するかどうかに関係なく、常に最初にorder=1、最後にorder=2、最後にorder=3として実行されます。 、またはその他の方法。

実装は次のとおりです。まず、注釈Orderです。

@Retention(RetentionPolicy.RUNTIME)
public @interface Order {
    public int order();
}

次に、変更されたOrderedRunner

public class OrderedRunner extends BlockJUnit4ClassRunner {
    public OrderedRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        Collections.sort(list, new Comparator<FrameworkMethod>() {
            @Override
            public int compare(FrameworkMethod f1, FrameworkMethod f2) {
                Order o1 = f1.getAnnotation(Order.class);
                Order o2 = f2.getAnnotation(Order.class);

                if (o1 == null || o2 == null)
                    return -1;

                return o1.order() - o2.order();
            }
        });
        return list;
    }
}
62
joscarsson

JUnitバージョン4.11以降では、クラスに@FixMethodOrderの注釈を付け、使用可能なMethodSortersのいずれかを指定することで、テストの実行順序に影響を与えることができます。詳細は this リンクを参照してください。

26
Shiva Kumar

junit 4.11新しい注釈@FixMethodOrderを使用すると、特定の順序を設定できます。

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
4
Philippe Blayo

JoscarssonとMichael Dのコードをgithubリポジトリに入れました。彼らが気にしないことを望みます。 Parameterizedクラスの注文バージョンも提供します。 Mavenの依存関係としてすでに使用されています

<repositories>
    <repository>
        <id>git-xxx</id>
        <url>https://github.com/crsici/OrderedRunnerJunit4.11/raw/master/</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.sici.org.junit</groupId>
    <artifactId>ordered-runner</artifactId>
    <version>0.0.1-RELEASE</version>
</dependency>
1
Trung Pham

Junitテストを「ソースコードに存在するとおり」の順序で実行したいが、テストコードを変更したくない場合は、これに関する私のメモを参照してください。

junitテストをソースコードに存在する順序で実行する方法

しかし、それは本当に良い考えではありません。テストは独立している必要があります。

1
kornero