web-dev-qa-db-ja.com

同じjunitテストを何度も実行する簡単な方法は?

タイトルが言うように、Eclipseを使用して自動的にJUnit 4.xテストを連続して数回実行する簡単な方法を探しています。

たとえば、同じテストを10回連続して実行し、結果を報告します。

私たちはすでにこれを行うための複雑な方法を持っていますが、私が修正しようとしている不安定なテストが修正されたままであると確信できるように、私はそれを行う簡単な方法を探しています。

理想的なソリューションは、私が知らないEclipseプラグイン/設定/機能です。

106
Stefan Thyberg

これを行う最も簡単な方法(少なくとも新しいコードが必要なため)は、テストをパラメーター化されたテストとして実行することです(@RunWith(Parameterized.class)で注釈を付け、10個の空のパラメーターを提供するメソッドを追加します)。そのようにして、フレームワークはテストを10回実行します。

このテストはクラス内の唯一のテストである必要があります。または、クラス内ですべてのテストメソッドを10回実行する必要があります。

以下に例を示します。

@RunWith(Parameterized.class)
public class RunTenTimes {

    @Parameterized.Parameters
    public static Object[][] data() {
        return new Object[10][0];
    }

    public RunTenTimes() {
    }

    @Test
    public void runsTenTimes() {
        System.out.println("run");
    }
}

上記により、パラメータなしのコンストラクタでそれを行うことも可能ですが、フレームワークの作者がそれを意図していたのか、それとも将来壊れるのかはわかりません。

独自のランナーを実装している場合、ランナーにテストを10回実行させることができます。サードパーティのランナーを使用している場合、4.7では、新しい@Ruleアノテーションを使用してMethodRuleインターフェイスを実装し、ステートメントを取得してforループで10回実行できるようにします。このアプローチの現在の欠点は、@Beforeおよび@Afterが1回しか実行されないことです。これは、JUnitの次のバージョンで変更される可能性があります(@Before@Ruleの後に実行されます)が、オブジェクトの同じインスタンスで動作するかどうかに関係なく( Parameterizedランナー)。これは、クラスを実行しているランナーが@Ruleアノテーションを正しく認識することを前提としています。 JUnitランナーに委任している場合のみです。

@Ruleアノテーションを認識しないカスタムランナーで実行している場合、そのランナーに適切に委任して10回実行する独自のランナーを作成する必要があります。

これを潜在的に解決する方法は他にもあります(Theoriesランナーなど)が、すべてランナーが必要です。残念ながら、現在、JUnitはランナーのレイヤーをサポートしていません。それは他のランナーをつなぐランナーです。

115
Yishai

IntelliJを使用すると、テスト構成からこれを行うことができます。このウィンドウを開いたら、何度でもテストを実行することを選択できます。

enter image description here

テストを実行すると、intellijは指定した回数だけ選択したすべてのテストを実行します。

624テストを10回実行する例: enter image description here

81
smac89

私は、Springのリピートアノテーションがそのようなことには役立つことを発見しました。

@Repeat(value = 10)

最新(Spring Framework 4.3.11.RELEASE API)ドキュメント:

59
laura

このソリューション

次のように_@Repeat_注釈を使用します。

_public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

    @Test
    @Repeat(10)
    public void testMyCode() {
        //your test code goes here
    }
}
_

次の2つのクラスのみが必要です。

Repeat.Java:

_import static Java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static Java.lang.annotation.ElementType.METHOD;
import Java.lang.annotation.Retention;
import Java.lang.annotation.RetentionPolicy;
import Java.lang.annotation.Target;

@Retention( RetentionPolicy.RUNTIME )
@Target({ METHOD, ANNOTATION_TYPE })
public @interface Repeat {
    int value() default 1;
}
_

RepeatRule.Java:

_import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class RepeatRule implements TestRule {

    private static class RepeatStatement extends Statement {
        private final Statement statement;
        private final int repeat;    

        public RepeatStatement(Statement statement, int repeat) {
            this.statement = statement;
            this.repeat = repeat;
        }

        @Override
        public void evaluate() throws Throwable {
            for (int i = 0; i < repeat; i++) {
                statement.evaluate();
            }
        }

    }

    @Override
    public Statement apply(Statement statement, Description description) {
        Statement result = statement;
        Repeat repeat = description.getAnnotation(Repeat.class);
        if (repeat != null) {
            int times = repeat.value();
            result = new RepeatStatement(statement, times);
        }
        return result;
    }
}
_

2016-10-25編集:@RunWith(PowerMockRunner.class)を使用するときにこのソリューションを使用するには、 Powermock 1.6。 5このパッチを含む)。

30
R. Oosterholt

JUnit 5では、 @ RepeatedTest アノテーションを使用してこれを解決できました。

@RepeatedTest(10)
public void testMyCode() {
    //your test code goes here
}

@Test注釈を@RepeatedTestとともに使用しないでください。

19
César Alberca

何か問題がある:

@Test
void itWorks() {
    // stuff
}

@Test
void itWorksRepeatably() {
    for (int i = 0; i < 10; i++) {
        itWorks();
    }
}

値の各配列をテストする場合とは異なり、どの実行が失敗したかは特に気にしません。

コードでできることを構成や注釈で行う必要はありません。

10
soru

tempus-fugit ライブラリには断続的な注釈があり、JUnit 4.7の@Ruleテストを数回繰り返す、または@RunWith

例えば、

@RunWith(IntermittentTestRunner.class)
public class IntermittentTestRunnerTest {

   private static int testCounter = 0;

   @Test
   @Intermittent(repition = 99)
   public void annotatedTest() {
      testCounter++;
   }
}

テストが実行された後(IntermittentTestRunnerを@RunWith)、testCounterは99と等しくなります。

7
Toby

これは私にとってずっと簡単です。

public class RepeatTests extends TestCase {

    public static Test suite() {
        TestSuite suite = new TestSuite(RepeatTests.class.getName());

        for (int i = 0; i < 10; i++) {              
        suite.addTestSuite(YourTest.class);             
        }

        return suite;
    }
}
7
Qualk

この種のテストを実行できるモジュールを作成します。しかし、繰り返しに焦点を合わせているだけではありません。ただし、コードの一部がスレッドセーフであることを保証します。

https://github.com/anderson-marques/concurrent-testing

Maven依存関係:

<dependency>
    <groupId>org.lite</groupId>
    <artifactId>concurrent-testing</artifactId>
    <version>1.0.0</version>
</dependency>

使用例:

package org.lite.concurrent.testing;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import ConcurrentTest;
import ConcurrentTestsRule;

/**
 * Concurrent tests examples
 */
public class ExampleTest {

    /**
     * Create a new TestRule that will be applied to all tests
     */
    @Rule
    public ConcurrentTestsRule ct = ConcurrentTestsRule.silentTests();

    /**
     * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
     */
    @Test
    @ConcurrentTest(requests = 20, threads = 10)
    public void testConcurrentExecutionSuccess(){
        Assert.assertTrue(true);
    }

    /**
     * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
     */
    @Test
    @ConcurrentTest(requests = 200, threads = 10, timeoutMillis = 100)
    public void testConcurrentExecutionSuccessWaitOnly100Millissecond(){
    }

    @Test(expected = RuntimeException.class)
    @ConcurrentTest(requests = 3)
    public void testConcurrentExecutionFail(){
        throw new RuntimeException("Fail");
    }
}

これはオープンソースプロジェクトです。気軽に改善してください。

0

MainメソッドからJUnitテストを実行し、必要な回数だけ繰り返すことができます。

package tests;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.Result;

public class RepeatedTest {

    @Test
    public void test() {
        fail("Not yet implemented");
    }

    public static void main(String args[]) {

        boolean runForever = true;

        while (runForever) {
            Result result = org.junit.runner.JUnitCore.runClasses(RepeatedTest.class);

            if (result.getFailureCount() > 0) {
                runForever = false;
               //Do something with the result object

            }
        }

    }

}
0
silver_mx

これは基本的に、Yishaiが上記で提供した、Kotlinで書き直された答えです。

@RunWith(Parameterized::class)
class MyTest {

    companion object {

        private const val numberOfTests = 200

        @JvmStatic
        @Parameterized.Parameters
        fun data(): Array<Array<Any?>> = Array(numberOfTests) { arrayOfNulls<Any?>(0) }
    }

    @Test
    fun testSomething() { }
}
0
mark