有没有办法让 Eclipse 多次运行 JUnit 测试直到失败?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1835523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to make Eclipse run a JUnit test multiple times until failure?
提问by Uri
We occasionally have bugs that appear once in every X runs. Before people check in stuff (where it is automatically JUnit'd), our devs need to pass JUnit locally via Eclipse.
我们偶尔会遇到在每次 X 运行中出现一次的错误。在人们签入东西之前(它是自动 JUnit 的),我们的开发人员需要通过 Eclipse 在本地传递 JUnit。
Is there some convenient way (built in or high-quality Plugin) to make Eclipse run the same test X times and stop if there's a failure? An alternative to just clicking Run X times?
是否有一些方便的方法(内置或高质量插件)让 Eclipse 运行相同的测试 X 次并在出现故障时停止?仅单击“运行 X 次”的替代方法?
Note that I'm looking for something in the UI (e.g., right click and say "Run X times" instead of just "Run").
请注意,我正在 UI 中查找某些内容(例如,右键单击并说“运行 X 次”,而不仅仅是“运行”)。
采纳答案by Michael Rusch
If the for loop works, then I agree with nos.
如果 for 循环有效,那么我同意 nos。
If you need to repeat the entire setup-test-teardown, then you can use a TestSuite:
如果您需要重复整个 setup-test-teardown,那么您可以使用 TestSuite:
- Right-click on the package containing the test to repeat
- Go to New and choose to create a JUnit test SUITE
- Make sure that only the test you want to repeat is selected and click through to finish.
- Edit the file to run it multiple times.
- 右键单击包含测试的包以重复
- 转到新建并选择创建 JUnit 测试套件
- 确保只选择了您要重复的测试,然后单击以完成。
- 编辑文件以多次运行它。
In the file you just find the
在文件中,您只需找到
addTestSuite(YourTestClass.class)
line, and wrap that in a for loop.
行,并将其包装在 for 循环中。
I'm pretty sure that you can use addTest instead of addTestSuite to get it to only run one test from that class if you just want to repeat a single test method.
如果您只想重复一个测试方法,我很确定您可以使用 addTest 而不是 addTestSuite 来让它只运行该类中的一个测试。
回答by akuhn
If you really want to run a test class until failure, you need your own runner.
如果你真的想运行一个测试类直到失败,你需要自己的运行器。
@RunWith(RunUntilFailure.class)
public class YourClass {
// ....
}
which could be implemented as follows...
这可以实现如下......
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);
}
}
...releasing untested code, feeling TDD guilt :)
...发布未经测试的代码,对 TDD 感到内疚 :)
回答by Kreich
Here is a post I wrote that shows several ways of running the tests repeatedly with code examples: http://codehowtos.blogspot.com/2011/04/run-junit-test-repeatedly.html
这是我写的一篇文章,它展示了使用代码示例重复运行测试的几种方法:http: //codehowtos.blogspot.com/2011/04/run-junit-test-repeatedly.html
You can use the @Parametrized runner, or use the special runner included in the post There is also a reference to a @Retry implementation
您可以使用@Parametrized runner,或者使用帖子中包含的特殊runner 还有一个@Retry 实现的引用
回答by benvolioT
Based on @akuhn's answer, here is what I came up with - rather than running forever, this will run 50 times or until failure, whichever comes first.
根据@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);
}
}
}
回答by Kenneth Cochran
I know it doesn't answer the question directly but if a test isn't passing every time it is run it is a test smell known as Erratic Test. There are several possible causes for this (from xUnit Test Patterns):
我知道它不会直接回答问题,但是如果每次运行测试都没有通过,它就是一种称为Erratic Test的测试气味。这有几个可能的原因(来自xUnit 测试模式):
- Interacting Tests
- Interacting Test Suites
- Lonely Test
- Resource Leakage
- Resource Optimism
- Unrepeatable Test
- Test Run War
- Nondeterministic Test
- 交互测试
- 交互测试套件
- 孤独的考验
- 资源泄漏
- 资源乐观
- 不可重复的测试
- 试运行战
- 非确定性测试
The details of each of these is documented in Chapter 16 of xUnit Test Patterns.
xUnit 测试模式的第 16 章中记录了其中每一个的详细信息。
回答by nos
I don't believe there's a built in way for junit to do exactly what you're asking for.
我不相信 junit 有一种内置的方式可以完全满足您的要求。
If multiple runs produce different result, you should have a unit test testing that case. Wich might be as simple as running a for loop in the relevant test cases.
如果多次运行产生不同的结果,你应该有一个单元测试来测试那个案例。这可能就像在相关测试用例中运行 for 循环一样简单。
回答by Ralph
It is possible to implement such an loop with TestRule
s (since JUnit 4.9)
可以使用TestRule
s实现这样的循环(自 JUnit 4.9 起)
A very simple implementation that runs every Test 10 times:
一个非常简单的实现,每个测试运行 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);
}
}
usage:
用法:
public class Run10TimesTest {
@Rule
public SimpleRepeatRule repeatRule = new SimpleRepeatRule();
@Test
public void myTest(){...}
}
For a more useful implementationbased on an annotation that define which test method has to been executed how often have a look at this blog: http://www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly-without-loops/
有关基于注释的更有用的实现,该注释定义了必须多久执行一次测试方法,请查看此博客:http: //www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly -无环/