java 强制 JUnit 一次运行一个测试用例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/545194/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 12:48:29  来源:igfitidea点击:

Force JUnit to run one test case at a time

javaunit-testingtestingantjunit

提问by Ciryon

I have a problematic situation with some quite advanced unit tests (using PowerMock for mocking and JUnit 4.5). Without going into too much detail, the first test case of a test class will always succeed, but any following test cases in the same test class fails. However, if I select to only run test case 5 out of 10, for example, it will pass. So all tests pass when being run individually. Is there any way to force JUnit to run one test case at a time? I call JUnit from an ant-script.

我有一些非常高级的单元测试(使用 PowerMock 进行模拟和 JUnit 4.5)的问题。无需赘述,测试类的第一个测试用例总是会成功,但同一测试类中的任何后续测试用例都会失败。但是,例如,如果我选择仅运行 10 个中的第 5 个测试用例,它将通过。因此,所有测试在单独运行时都会通过。有没有办法强制 JUnit 一次运行一个测试用例?我从蚂蚁脚本中调用 JUnit。

I am aware of the problem of dependant test cases, but I can't pinpoint why this is. There are no saved variables across the test cases, so nothing to do at @Before annotation. That's why I'm looking for an emergency solution like forcing JUnit to run tests individually.

我知道依赖测试用例的问题,但我无法确定这是为什么。测试用例中没有保存的变量,所以在 @Before 注释上没有任何事情要做。这就是为什么我正在寻找紧急解决方案,例如强制 JUnit 单独运行测试。

采纳答案by Aaron Digulla

Your problem is not that JUnit runs all the tests at once, you problem is that you don't see whya test fails. Solutions:

你的问题不在于JUnit的运行所有测试一次,你的问题是,你没有看到,为什么一个测试失败。解决方案:

  1. Add more asserts to the tests to make sure that every variable actually contains what you think
  2. Download an IDE from the Internet and use the built-in debugger to look at the various variables
  3. Dump the state of your objects just before the point where the test fails.
  4. Use the "message" part of the asserts to output more information why it fails (see below)
  5. Disable all but a handful of tests (in JUnit 3: replace all strings "void test" with "void dtest" in your source; in JUnit 4: Replace "@Test" with "//D@TEST").
  1. 向测试添加更多断言以确保每个变量实际上包含您的想法
  2. 从网上下载一个IDE,使用内置的调试器查看各种变量
  3. 在测试失败之前转储对象的状态。
  4. 使用断言的“消息”部分输出更多信息,为什么它失败(见下文)
  5. 禁用除少数测试之外的所有测试(在 JUnit 3 中:将源代码中的所有字符串“void test”替换为“void dtest”;在 JUnit 4 中:将“@Test”替换为“//D@TEST”)。

Example:

例子:

assertEquals(list.toString(), 5, list.size());

回答by hariseldon78

I am aware of all the recommendations, but to finally answer your question here is a simple way to achieve what you want. Just put this code inside your test case:

我知道所有建议,但最终在这里回答您的问题是实现您想要的简单方法。只需将此代码放入您的测试用例中:

Lock sequential = new ReentrantLock();

@Override
protected void setUp() throws Exception {
    super.setUp();
    sequential.lock();
}

@Override
protected void tearDown() throws Exception {
    sequential.unlock();
    super.tearDown();
}

With this, no test can start until the lock is acquired, and only one lock can be acquired at a time.

这样,在获取锁之前不能开始测试,并且一次只能获取一个锁。

回答by Itay Maman

It seems that your test cases are dependent, that is: the execution of case-X affects the execution of case-Y. Such a testing system should be avoided (for instance: there's no guarantee on the order at which JUnit will run your cases).

看来你的测试用例是依赖的,也就是说:case-X的执行会影响case-Y的执行。应该避免使用这样的测试系统(例如:无法保证 JUnit 运行您的案例的顺序)。

You should refactor your cases to make them independent of each other. Many times the use of @Before and @After methods can help you untangle such dependencies.

您应该重构您的案例,使它们相互独立。很多时候,@Before 和@After 方法的使用可以帮助你解开这种依赖关系。

回答by Chris Nava

Congratulations. You have found a bug. ;-)

恭喜。你发现了一个错误。;-)

If the tests "shouldn't" effect each other, then you may have uncovered a situation where your code can enter a broken state. Try adding asserts and logging to figure out where the code goes wrong. You may even need to run the tests in a debugger and check your code's internal values after the first test.

如果测试“不应该”相互影响,那么您可能已经发现您的代码可能进入损坏状态的情况。尝试添加断言和日志以找出代码出错的地方。您甚至可能需要在调试器中运行测试并在第一次测试后检查代码的内部值。

回答by lindelof

Excuse me if I dont answer your question directly, but isn't your problem exactly what TestCase.setUp() and TestCase.tearDown() are supposed to solve? These are methods that the JUnit framework will always call before and after each test case, and are typically used to ensure you begin each test case in the same state.

对不起,如果我不直接回答你的问题,但你的问题不正是 TestCase.setUp() 和 TestCase.tearDown() 应该解决的问题吗?这些是 JUnit 框架在每个测试用例之前和之后始终调用的方法,通常用于确保您以相同的状态开始每个测试用例。

See also the JavaDocfor TestCase.

另请参阅TestCase的JavaDoc

回答by Esko Luontola

You should check your whole codebase that there are no static variables which refer to mutable state. Ideally the program should have no static mutable state (or at least they should be documented like I did here). Also you should be very careful about cleaning up what you write, if the tests write to the file system or database. Otherwise running the tests may leak some side-effects, which makes it hard to make the tests independent and repeatable.

您应该检查整个代码库,以确保没有引用可变状态的静态变量。理想情况下,程序应该没有静态可变状态(或者至少应该像我在这里所做的那样记录它们)。如果测试写入文件系统或数据库,您还应该非常小心地清理您编写的内容。否则运行测试可能会泄漏一些副作用,这使得很难使测试独立和可重复。

Maven and Ant contain a "forkmode" parameter for running JUnit tests, which specifies whether each test classgets its own JVM or all tests are run in the same JVM. But they do not have an option for running each test methodin its own JVM.

Maven 和 Ant 包含一个用于运行 JUnit 测试的“forkmode”参数,它指定是每个测试类都有自己的 JVM 还是所有测试都在同一个 JVM 中运行。但是他们没有在自己的 JVM 中运行每个测试方法的选项。

回答by Peter

It sounds to me that perhaps it isn't that you are not setting up or tearing down your tests properly (although additional setup/teardown may be part of the solution), but that perhaps you have shared state in your code that you are not aware of. If an early test is setting a static / singleton / shared variable that you are unaware of, the later tests will fail if they are not expecting this. Even with Mocks this is very possible. You need to find this cause. I agree with the other answers in that your tests have exposed a problem that should not be solved by trying to run the tests differently.

在我看来,也许并不是您没有正确设置或拆除测试(尽管额外的设置/拆除可能是解决方案的一部分),而是您在代码中共享了状态,而您没有意识到。如果早期的测试设置了一个您不知道的静态/单例/共享变量,那么如果他们没有预料到,后面的测试就会失败。即使使用 Mocks,这也是很有可能的。你需要找到这个原因。我同意其他答案,因为您的测试暴露了一个不应通过尝试以不同方式运行测试来解决的问题。

回答by guerda

Your description shows me, that your unit tests depend each other. That is strongly not recommendedin unit tests.

你的描述告诉我,你的单元测试相互依赖。在单元测试中强烈不建议这样做。

Unit test must be independent and isolated. You have to be able to execute them alone, all of them (in which order, it does not matter).

单元测试必须是独立的和隔离的。您必须能够单独执行它们,全部执行(按哪个顺序,无关紧要)。

I know, that does not help you. The problem will be in your @BeforeClassor @Beforestatements. There will be dependencies. So refactor them and try to isolate the problem.

我知道,这对你没有帮助。问题将出在您的@BeforeClassor@Before陈述中。会有依赖。所以重构它们并尝试隔离问题。

Probably your mocks are created in your @BeforeClass. Consider to put it into the @Beforestatement. So there's no instance that last longer than a test case.

可能你的模拟是在你的@BeforeClass. 考虑将其放入@Before语句中。所以没有比测试用例持续时间更长的实例。

回答by guerda

I am aware of the problem of dependant test cases, but I can't pinpoint why this is. There are no saved variables across the test cases, so nothing to do at @Before annotation. That's why I'm looking for an emergency solution like forcing JUnit to run tests individually.

我知道依赖测试用例的问题,但我无法确定这是为什么。测试用例中没有保存的变量,所以在 @Before 注释上没有任何事情要做。这就是为什么我正在寻找紧急解决方案,例如强制 JUnit 单独运行测试。

The @Before statement is harmless, because it is called for every test case. The @BeforeClassis dangerous, because it has to be static.

@Before 语句是无害的,因为每个测试用例都会调用它。@Before很危险,因为它必须是静态的。