有没有办法让Eclipse多次运行JUnit测试直到失败?

时间:2009-12-02 20:19:43

标签: java eclipse junit

我们偶尔会在每次X次运行中出现一次错误。在人们检查内容(它自动为JUnit)之前,我们的开发人员需要通过Eclipse在本地传递JUnit。

是否有一些方便的方法(内置或高质量的插件)使Eclipse运行X次相同的测试并在出现故障时停止?只需单击Run X times?

请注意,我正在寻找UI中的内容(例如,右键单击并说“Run X times”而不是“Run”)。

7 个答案:

答案 0 :(得分:11)

如果for循环有效,那么我同意nos。

如果您需要重复整个setup-test-teardown,那么您可以使用TestSuite:

  1. 右键单击包含要重复的测试的包
  2. 转到“新建”并选择创建JUnit测试套件
  3. 确保只选择了您要重复的测试并点击完成。
  4. 编辑文件以多次运行。
  5. 在文件中,您只需找到

    addTestSuite(YourTestClass.class)
    

    行,并将其包装在for循环中。

    我很确定你可以使用addTest而不是addTestSuite来让它只运行该类中的一个测试,如果你只想重复一个测试方法。

答案 1 :(得分:7)

如果你真的想在失败前运行测试课程,你需要自己的跑步者。

@RunWith(RunUntilFailure.class)
public class YourClass {

    // ....

}

可以实现如下......

package com.example;

import org.junit.internal.runners.*;
import org.junit.runner.notification.*;
import org.junit.runner.*;

public class RunUntilFailure extends Runner {

    private TestClassRunner runner;

    public RunUntilFailure(Class<?> klass) throws InitializationError {
        this.runner = new TestClassRunner(klass);
    }

    @Override
    public Description getDescription() {
        Description description = Description.createSuiteDescription("Run until failure");
        description.addChild(runner.getDescription());
        return description;
    }

    @Override
    public void run(RunNotifier notifier) {
        class L extends RunListener {
            boolean fail = false;
            public void testFailure(Failure failure) throws Exception { fail = true; }
        }
        L listener = new L();
        notifier.addListener(listener);
        while (!listener.fail) runner.run(notifier);
    }

}

...发布未经测试的代码,感觉TDD内疚:)

答案 2 :(得分:3)

我知道它没有直接回答这个问题但是如果测试没有在每次运行时都没有通过,那么它就是一种被称为 Erratic Test 的测试气味。有几种可能的原因(来自 xUnit测试模式):

  • 互动测试
  • 互动测试套件
  • 孤独的测试
  • 资源泄漏
  • 资源乐观
  • 不可重复的测试
  • 试运行战争
  • 非确定性测试

xUnit Test Patterns 的第16章介绍了每个细节。

答案 3 :(得分:3)

这是我写的一篇文章,其中显示了使用代码示例重复运行测试的几种方法: http://codehowtos.blogspot.com/2011/04/run-junit-test-repeatedly.html

您可以使用@Parametrized跑步者,或使用帖子中包含的特殊跑步者 还有对@Retry实现的引用

答案 4 :(得分:3)

根据@ akuhn的回答,这是我想出的 - 而不是永远跑,这将运行50次或直到失败,以先到者为准。

package com.foo    

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public class RunManyTimesUntilFailure extends Runner {

    private static final int MAX_RUN_COUNT = 50;

    private BlockJUnit4ClassRunner runner;

    @SuppressWarnings("unchecked")
    public RunManyTimesUntilFailure(final Class testClass) throws InitializationError {
        runner = new BlockJUnit4ClassRunner(testClass); 
    }

    @Override
    public Description getDescription() {
        final Description description = Description.createSuiteDescription("Run many times until failure");
        description.addChild(runner.getDescription());
        return description;
    }

    @Override
    public void run(final RunNotifier notifier) {
        class L extends RunListener {
            boolean shouldContinue = true;
            int runCount = 0;

            @Override
            public void testFailure(@SuppressWarnings("unused") final Failure failure) throws Exception {
                shouldContinue = false;
            }

            @Override
            public void testFinished(@SuppressWarnings("unused") Description description) throws Exception {
                runCount++;

                shouldContinue = (shouldContinue && runCount < MAX_RUN_COUNT);
            }
        }

        final L listener = new L();
        notifier.addListener(listener);

        while (listener.shouldContinue) {
            runner.run(notifier);
        }
    }
}

答案 5 :(得分:2)

我不相信有一个内置的方式让junit完全按照你的要求去做。

如果多次运行产生不同的结果,您应该对该情况进行单元测试。可能就像在相关测试用例中运行for循环一样简单。

答案 6 :(得分:2)

可以用TestRule s(自JUnit 4.9)

实现这样的循环

一个非常简单的实现,每次运行10次:

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

public class SimpleRepeatRule implements TestRule {

    private static class SimpleRepeatStatement extends Statement {

        private final Statement statement;

        private SimpleRepeatStatement(Statement statement) {
            this.statement = statement;
        }

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

    @Override
    public Statement apply(Statement statement, Description description) {
        return new SimpleRepeatStatement(statement);
    }
}

用法:

public class Run10TimesTest {

   @Rule
   public SimpleRepeatRule repeatRule = new SimpleRepeatRule();

   @Test
   public void myTest(){...}
}

对于更有用的实现,基于定义哪个测试方法必须执行的注释,经常查看此博客: http://www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly-without-loops/