如果之前的步骤在Junit中失败,如何跳过剩余的步骤

时间:2018-01-02 19:31:47

标签: java maven junit integration-testing

我有一些集成测试用例,他们使用特殊类别的Junit测试用例运行:

@Category(IntegrationTest.class)

因为它们是集成测试用例,所以每个步骤的成本都很高。 通常我会重复使用之前步骤的一些结果来降低此成本。 为了使其有效,我将其添加到其中:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)

这样的一些样本:

@Category(IntegrationTest.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestAllocationPlanApi {

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

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

除失败过程外,它们运作良好:

如果step01失败,我们不需要运行step02,但是Junit仍然转到step02。

这是一种浪费,使测试用例更加复杂,因为您需要仔细处理传递给step02的变量。

我试过

-Dsurefire.skipAfterFailureCount=1

another thread中对此进行了讨论,但它不起作用,如果之前的步骤失败,测试用例仍会进入下一步。

关于测试用例的另一个烦人的事情是Junit总是在每一步之前重置所有实例变量。这迫使我使用静态变量将先前的结果传递到下一步:

private static Integer contractAId;

我无法在多个线程中运行它们。

有没有人有好的想法来处理这些事情?

谢谢!

新年快乐!

2 个答案:

答案 0 :(得分:2)

您已将这些测试编写为 distinct 测试,但这些测试之间存在一些依赖关系。所以,听起来你已经在多个测试方法中划分了一个逻辑测试流程。

为了满足这些依赖关系,您采用了测试的命名约定,并指示JUnit按命名约定隐含的顺序运行这些测试。此外,您在测试用例中有一些共享状态,即从一步到另一步传递。

这种方法听起来很脆弱,可能会使以下情况变得非常困难:

  • 诊断故障,问题
  • 维护现有步骤
  • 添加新步骤

指示JUnit - 以某种方式 - 如果先前的测试失败并且使用静态变量将先前的结果传递到下一步,则在测试用例中停止执行后续测试都是决定将单个逻辑测试拆分的症状多个@Test方法。

JUnit在测试用例中没有后续或先前测试的正式概念。这是故意的,因为预期@Test方法彼此独立。

所以,不要试图实现他的行为:如果先前的测试失败,停止在测试用例中执行后续测试我建议重新访问测试以减少运行时间,减少昂贵的设置时间和删除这种在多个测试方法中拆分单个逻辑测试流的方法。相反,每个测试应该是自包含的;其范围应包括(a)设置,(b)执行; (c)断言; (d)拆除。

我可以从你的问题中看出这是一个集成测试,因此设置,依赖关系管理,执行等可能并不简单,所以也许这种将多个测试方法中的单个逻辑测试流分开的方法就是分解一个复杂的测试流程进入更易消化的单位。如果是这样,那么我建议将每个“步骤”分解为私有方法,并在单个 @Test方法中编排它们。例如:

@Test
public void test_verifyOrigProgram22275() {
    // you'll probably want to return some sort of context object from each step
    // i.e. something which allows you to (a) test whether a step has succeeded 
    // and abort if not and (b) pass state between steps

    step01_verifyOrigProgram22275();

    step02_verifyOrigProgram22275();

    ...
}

private void step01_verifyOrigProgram22275() {...}

private void step02_CopyProgram() {...}

答案 1 :(得分:1)

对于集成测试,我添加了以下内容(JUnit5,测试是有序的)。

private static boolean soFarSoGood = true;
private static String failingMethod = null;
void testSoFarSoGood() throws Exception {
    Assertions.assertTrue(soFarSoGood, "Failed at method " + failingMethod);
    failingMethod = new Throwable() 
            .getStackTrace()[1] 
            .getMethodName(); 
    soFarSoGood = false;
    logger.info("Starting {}()", failingMethod);
}
void soFarSoGood() {
    soFarSoGood = true;
    logger.info("End of {}()", failingMethod);
}

@Test
@Order(10)
void first() throws Exception {
  testSoFarSoGood();
  ... test code ...
  soFarSoGood();
}
@Test
@Order(20)
void second() throws Exception {
  testSoFarSoGood();
  ... test code ...
  soFarSoGood();
}

以此类推...

我无法使用@BeforeEach / @AfterEach工作来实现(好吧……我并没有做太多尝试),但是我欢迎您