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

时间:2009-09-29 14:20:10

标签: java eclipse junit

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

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

我们已经有了一种复杂的方法,但我正在寻找一种简单的方法来做到这一点,这样我就可以确定我一直试图修复的片状测试仍然是固定的。

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

12 个答案:

答案 0 :(得分:113)

最简单(至少需要新代码的数量)方法是将测试作为参数化测试运行(使用@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仅运行一次。这可能会在JUnit的下一个版本中发生变化(@Before将在@Rule之后运行),但无论你是在同一个对象的实例上行动(事情都不是Parameterized亚军)。这假设您运行该类的任何跑步者都能正确识别@Rule注释。只有当它委托给JUnit跑步者时才会这样。

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

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

答案 1 :(得分:62)

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

enter image description here

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

运行624次测试的示例10次: enter image description here

答案 2 :(得分:57)

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

@Repeat(value = 10)

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

答案 3 :(得分:30)

启发this solution

使用@Repeat这样的注释:

public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

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

您只需要这两个类:

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,其中包含this patch )。

答案 4 :(得分:18)

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

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

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

答案 5 :(得分:10)

有什么问题:

@Test
void itWorks() {
    // stuff
}

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

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

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

答案 6 :(得分:7)

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

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

答案 7 :(得分:7)

这对我来说更容易。

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 :(得分:0)

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

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

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

答案 9 :(得分: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

            }
        }

    }

}

答案 10 :(得分:0)

这本质上就是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() { }
}

答案 11 :(得分:0)

JUnit 5中,使用@RepeatedTest

要简单得多

@RepeatedTest用于表示带注释的方法是测试 模板方法,应重复指定的次数。

    @RepeatedTest(3) // Runs N Times
    public void test_Prime() {
    }

有关www.baeldung.com的更多信息