一遍又一遍地运行相同的junit测试的简单方法?

时间:2022-11-04 14:49:50

Like the title says, I'm looking for some simple way to run JUnit 4.x tests several times in a row automatically using Eclipse.

就像标题所说,我正在寻找一些使用Eclipse自动连续多次运行JUnit 4.x测试的简单方法。

An example would be running the same test 10 times in a row and reporting back the result.

一个例子是连续10次运行相同的测试并报告结果。

We already have a complex way of doing this but I'm looking for a simple way of doing it so that I can be sorta sure that the flaky test I've been trying to fix stays fixed.

我们已经有了一个复杂的方法来做到这一点,但我正在寻找一种简单的方法来做到这一点,以便我可以确定我一直试图修复的片状测试保持不变。

An ideal solution would be an Eclipse plugin/setting/feature that I am unaware of.

一个理想的解决方案是我不知道的Eclipse插件/设置/功能。

10 个解决方案

#1


97  

The easiest (as in least amount of new code required) way to do this is to run the test as a parametrized test (annotate with an @RunWith(Parameterized.class) and add a method to provide 10 empty parameters). That way the framework will run the test 10 times.

最简单的(至少需要新代码量)方法是将测试作为参数化测试运行(使用@RunWith(Parameterized.class)进行注释并添加一个方法来提供10个空参数)。这样,框架将运行测试10次。

This test would need to be the only test in the class, or better put all test methods should need to be run 10 times in the class.

这个测试需要是该类中唯一的测试,或者更好地将所有测试方法都需要在类中运行10次。

Here is an example:

这是一个例子:

@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");
    }
}

With the above, it is possible to even do it with a parameter-less constructor, but I'm not sure if the framework authors intended that, or if that will break in the future.

有了上述内容,甚至可以使用无参数构造函数来完成它,但我不确定框架作者是否打算这样做,或者将来是否会破坏。

If you are implementing your own runner, then you could have the runner run the test 10 times. If you are using a third party runner, then with 4.7, you can use the new @Rule annotation and implement the MethodRule interface so that it takes the statement and executes it 10 times in a for loop. The current disadvantage of this approach is that @Before and @After get run only once. This will likely change in the next version of JUnit (the @Before will run after the @Rule), but regardless you will be acting on the same instance of the object (something that isn't true of the Parameterized runner). This assumes that whatever runner you are running the class with correctly recognizes the @Rule annotations. That is only the case if it is delegating to the JUnit runners.

如果您正在实施自己的跑步者,那么您可以让跑步者进行10次测试。如果您使用的是第三方运行程序,那么使用4.7,您可以使用新的@Rule注释并实现MethodRule接口,以便它获取语句并在for循环中执行10次。目前这种方法的缺点是@Before和@After只运行一次。这可能会在下一版本的JUnit中发生变化(@Before将在@Rule之后运行),但是无论你是在同一个对象实例上行动(参与者都不是这样)。这假设您正在运行该类的任何跑步者正确识别@Rule注释。只有当它委托给JUnit跑步者时才是这种情况。

If you are running with a custom runner that does not recognize the @Rule annotation, then you are really stuck with having to write your own runner that delegates appropriately to that Runner and runs it 10 times.

如果你运行的是一个不能识别@Rule注释的自定义运行器,那么你真的不得不编写自己的运行器,它适当地委托给Runner并运行它10次。

Note that there are other ways to potentially solve this (such as the Theories runner) but they all require a runner. Unfortunately JUnit does not currently support layers of runners. That is a runner that chains other runners.

请注意,还有其他方法可以解决这个问题(例如Theories runner),但它们都需要跑步者。不幸的是,JUnit目前不支持跑步者的层次。这是一个连锁其他选手的跑步者。

#2


50  

I've found that Spring's repeat annotation is useful for that kind of thing:

我发现Spring的重复注释对于这种事情很有用:

@Repeat(value = 10)

Latest (Spring Framework 4.3.11.RELEASE API) doc:

最新(Spring Framework 4.3.11.RELEASE API)doc:

#3


26  

Inspired on this solution:

灵感来自这个解决方案:

Use @Repeat annotation like this:

像这样使用@Repeat注​​释:

public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

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

You'll only need these two classes:

你只需要这两个类:

Repeat.java:

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:

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 Edit: In order to use this solution when using @RunWith(PowerMockRunner.class), update to Powermock 1.6.5 (which includes this patch).

2016-10-25编辑:为了在使用@RunWith(PowerMockRunner.class)时使用此解决方案,请更新到Powermock 1.6.5(包括此补丁)。

#4


23  

With IntelliJ, you can do this from the test configuration. Once you open this window, you can choose to run the test any number of times you want,.

使用IntelliJ,您可以从测试配置中执行此操作。打开此窗口后,您可以选择任意次数运行测试。

一遍又一遍地运行相同的junit测试的简单方法?

when you run the test, intellij will execute all tests you have selected for the number of times you specified.

当您运行测试时,intellij将执行您指定的所有测试次数。

Example running 624 tests 10 times: 一遍又一遍地运行相同的junit测试的简单方法?

示例运行624次测试10次:

#5


12  

With JUnit 5 I was able to solve this using the @RepeatedTest annotation:

使用JUnit 5,我能够使用@RepeatedTest注释来解决这个问题:

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

Note that @Test annotation shouldn't be used along with @RepeatedTest.

请注意,@ Test注释不应与@RepeatedTest一起使用。

#6


9  

Anything wrong with:

有什么不对:

@Test
void itWorks() {
    // stuff
}

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

Unlike the case where you are testing each of an array of values, you don't particularly care which run failed.

与测试每个值数组的情况不同,您并不特别关心哪个运行失败。

No need to do in configuration or annotation what you can do in code.

无需在配置或注释中执行代码中的操作。

#7


7  

This works much easier for me.

这对我来说更容易。

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;
    }
}

#8


7  

There's an Intermittent annotation in the tempus-fugit library which works with JUnit 4.7's @Rule to repeat a test several times or with @RunWith.

在tempus-fugit库中有一个Intermittent注释,它与JUnit 4.7的@Rule一起重复测试几次或使用@RunWith。

For example,

例如,

@RunWith(IntermittentTestRunner.class)
public class IntermittentTestRunnerTest {

   private static int testCounter = 0;

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

After the test is run (with the IntermittentTestRunner in the @RunWith), testCounter would be equal to 99.

运行测试后(使用@RunWith中的IntermittentTestRunner),testCounter将等于99。

#9


0  

I build a module that allows do this kind of tests. But it is focused not only in repeat. But in guarantee that some piece of code is Thread safe.

我构建了一个允许进行此类测试的模块。但它的重点不仅在于重复。但是保证一些代码是Thread安全的。

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

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

Maven dependency:

Maven依赖:

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

Example of use:

使用示例:

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");
    }
}

This is a open source project. Feel free to improve.

这是一个开源项目。随意改进。

#10


0  

You could run your JUnit test from a main method and repeat it so many times you need:

您可以从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

            }
        }

    }

}

#1


97  

The easiest (as in least amount of new code required) way to do this is to run the test as a parametrized test (annotate with an @RunWith(Parameterized.class) and add a method to provide 10 empty parameters). That way the framework will run the test 10 times.

最简单的(至少需要新代码量)方法是将测试作为参数化测试运行(使用@RunWith(Parameterized.class)进行注释并添加一个方法来提供10个空参数)。这样,框架将运行测试10次。

This test would need to be the only test in the class, or better put all test methods should need to be run 10 times in the class.

这个测试需要是该类中唯一的测试,或者更好地将所有测试方法都需要在类中运行10次。

Here is an example:

这是一个例子:

@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");
    }
}

With the above, it is possible to even do it with a parameter-less constructor, but I'm not sure if the framework authors intended that, or if that will break in the future.

有了上述内容,甚至可以使用无参数构造函数来完成它,但我不确定框架作者是否打算这样做,或者将来是否会破坏。

If you are implementing your own runner, then you could have the runner run the test 10 times. If you are using a third party runner, then with 4.7, you can use the new @Rule annotation and implement the MethodRule interface so that it takes the statement and executes it 10 times in a for loop. The current disadvantage of this approach is that @Before and @After get run only once. This will likely change in the next version of JUnit (the @Before will run after the @Rule), but regardless you will be acting on the same instance of the object (something that isn't true of the Parameterized runner). This assumes that whatever runner you are running the class with correctly recognizes the @Rule annotations. That is only the case if it is delegating to the JUnit runners.

如果您正在实施自己的跑步者,那么您可以让跑步者进行10次测试。如果您使用的是第三方运行程序,那么使用4.7,您可以使用新的@Rule注释并实现MethodRule接口,以便它获取语句并在for循环中执行10次。目前这种方法的缺点是@Before和@After只运行一次。这可能会在下一版本的JUnit中发生变化(@Before将在@Rule之后运行),但是无论你是在同一个对象实例上行动(参与者都不是这样)。这假设您正在运行该类的任何跑步者正确识别@Rule注释。只有当它委托给JUnit跑步者时才是这种情况。

If you are running with a custom runner that does not recognize the @Rule annotation, then you are really stuck with having to write your own runner that delegates appropriately to that Runner and runs it 10 times.

如果你运行的是一个不能识别@Rule注释的自定义运行器,那么你真的不得不编写自己的运行器,它适当地委托给Runner并运行它10次。

Note that there are other ways to potentially solve this (such as the Theories runner) but they all require a runner. Unfortunately JUnit does not currently support layers of runners. That is a runner that chains other runners.

请注意,还有其他方法可以解决这个问题(例如Theories runner),但它们都需要跑步者。不幸的是,JUnit目前不支持跑步者的层次。这是一个连锁其他选手的跑步者。

#2


50  

I've found that Spring's repeat annotation is useful for that kind of thing:

我发现Spring的重复注释对于这种事情很有用:

@Repeat(value = 10)

Latest (Spring Framework 4.3.11.RELEASE API) doc:

最新(Spring Framework 4.3.11.RELEASE API)doc:

#3


26  

Inspired on this solution:

灵感来自这个解决方案:

Use @Repeat annotation like this:

像这样使用@Repeat注​​释:

public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

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

You'll only need these two classes:

你只需要这两个类:

Repeat.java:

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:

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 Edit: In order to use this solution when using @RunWith(PowerMockRunner.class), update to Powermock 1.6.5 (which includes this patch).

2016-10-25编辑:为了在使用@RunWith(PowerMockRunner.class)时使用此解决方案,请更新到Powermock 1.6.5(包括此补丁)。

#4


23  

With IntelliJ, you can do this from the test configuration. Once you open this window, you can choose to run the test any number of times you want,.

使用IntelliJ,您可以从测试配置中执行此操作。打开此窗口后,您可以选择任意次数运行测试。

一遍又一遍地运行相同的junit测试的简单方法?

when you run the test, intellij will execute all tests you have selected for the number of times you specified.

当您运行测试时,intellij将执行您指定的所有测试次数。

Example running 624 tests 10 times: 一遍又一遍地运行相同的junit测试的简单方法?

示例运行624次测试10次:

#5


12  

With JUnit 5 I was able to solve this using the @RepeatedTest annotation:

使用JUnit 5,我能够使用@RepeatedTest注释来解决这个问题:

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

Note that @Test annotation shouldn't be used along with @RepeatedTest.

请注意,@ Test注释不应与@RepeatedTest一起使用。

#6


9  

Anything wrong with:

有什么不对:

@Test
void itWorks() {
    // stuff
}

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

Unlike the case where you are testing each of an array of values, you don't particularly care which run failed.

与测试每个值数组的情况不同,您并不特别关心哪个运行失败。

No need to do in configuration or annotation what you can do in code.

无需在配置或注释中执行代码中的操作。

#7


7  

This works much easier for me.

这对我来说更容易。

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;
    }
}

#8


7  

There's an Intermittent annotation in the tempus-fugit library which works with JUnit 4.7's @Rule to repeat a test several times or with @RunWith.

在tempus-fugit库中有一个Intermittent注释,它与JUnit 4.7的@Rule一起重复测试几次或使用@RunWith。

For example,

例如,

@RunWith(IntermittentTestRunner.class)
public class IntermittentTestRunnerTest {

   private static int testCounter = 0;

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

After the test is run (with the IntermittentTestRunner in the @RunWith), testCounter would be equal to 99.

运行测试后(使用@RunWith中的IntermittentTestRunner),testCounter将等于99。

#9


0  

I build a module that allows do this kind of tests. But it is focused not only in repeat. But in guarantee that some piece of code is Thread safe.

我构建了一个允许进行此类测试的模块。但它的重点不仅在于重复。但是保证一些代码是Thread安全的。

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

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

Maven dependency:

Maven依赖:

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

Example of use:

使用示例:

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");
    }
}

This is a open source project. Feel free to improve.

这是一个开源项目。随意改进。

#10


0  

You could run your JUnit test from a main method and repeat it so many times you need:

您可以从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

            }
        }

    }

}