【问题标题】:Force JUnit to run one test case at a time强制 JUnit 一次运行一个测试用例
【发布时间】:2010-10-07 09:48:17
【问题描述】:

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

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

【问题讨论】:

  • 请将此信息编辑到您的问题中,以便所有人都能阅读。
  • “测试用例中没有保存的变量”你确定吗?静态变量呢?
  • 一个测试究竟是如何失败的,即你要测试什么?

标签: java unit-testing testing ant junit


【解决方案1】:

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

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

【讨论】:

  • +1,我不会说“应该”避免但“必须”避免以避免这种情况
  • 我知道依赖测试用例的问题,但我无法确定这是为什么。测试用例中没有保存的变量,因此在 @Before 注释处无事可做。这就是为什么我正在寻找一种紧急解决方案,例如强制 JUnit 单独运行测试。
  • 依赖有很多方面:数据库、文件、系统属性等。你应该将你的套件减少到两个相互冲突的测试。在一个测试中开始注释代码,直到它们成功。然后取消注释并在第二个测试中执行相同操作。这将为您提供有关问题原因的一些见解。
  • “测试用例中没有保存的变量”你确定吗?静态变量呢?
【解决方案2】:

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

另请参阅 JavaDoc 以获取 TestCase。

【讨论】:

    【解决方案3】:

    您的描述告诉我,您的单元测试相互依赖。在单元测试中强烈不推荐

    单元测试必须是独立和隔离的。您必须能够单独执行它们,所有它们(按什么顺序,无关紧要)。

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

    您的模拟可能是在您的@BeforeClass 中创建的。考虑将其放入@Before 语句中。所以没有比测试用例更持久的实例。

    【讨论】:

    • 好吧,强烈不推荐。
    【解决方案4】:

    我知道依赖的问题 测试用例,但我无法确定原因 这是。没有保存的变量 跨越测试用例,所以没什么可做的 在@Before 注释处做。这就是为什么 我正在寻找紧急解决方案 比如强制 JUnit 运行测试 个人。

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

    【讨论】:

      【解决方案5】:

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

      1. 向测试中添加更多断言,以确保每个变量实际上都包含您的想法
      2. 从 Internet 下载一个 IDE 并使用内置调试器查看各种变量
      3. 在测试失败之前转储对象的状态。
      4. 使用断言的“消息”部分输出失败原因的更多信息(见下文)
      5. 禁用除少数测试外的所有测试(在 JUnit 3 中:将源代码中的所有字符串“void test”替换为“void dtest”;在 JUnit 4 中:将“@Test”替换为“//D@TEST”)。

      例子:

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            您应该检查整个代码库,确保没有引用可变状态的静态变量。理想情况下,程序应该没有静态可变状态(或者至少应该记录在like I did here)。如果测试写入文件系统或数据库,你也应该非常小心地清理你写的东西。否则运行测试可能会泄漏一些副作用,这使得测试难以独立和可重复。

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

            【讨论】:

              【解决方案9】:

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

              Lock sequential = new ReentrantLock();
              
              @Override
              protected void setUp() throws Exception {
                  super.setUp();
                  sequential.lock();
              }
              
              @Override
              protected void tearDown() throws Exception {
                  sequential.unlock();
                  super.tearDown();
              }
              

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-01-30
                • 1970-01-01
                • 2017-08-09
                • 2014-01-05
                • 1970-01-01
                • 2016-07-13
                • 1970-01-01
                • 2013-10-30
                相关资源
                最近更新 更多