代码之家  ›  专栏  ›  技术社区  ›  Justin

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

  •  1
  • Justin  · 技术社区  · 7 年前

    我有一些集成测试用例,它们作为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 回复  |  直到 7 年前
        1
  •  4
  •   glytching    7 年前

    您将这些写为 不同的 但这些测试之间存在一些依赖关系。因此,听起来您已经将单个逻辑测试流拆分为多个测试方法。

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

    这种方法听起来很脆弱,可能会使以下方面变得相当困难:

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

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

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

    因此,与其试图实施他的行为,不如: 如果先前的测试失败,请停止执行测试用例中的后续测试 我建议重新访问您的测试,以减少它们的运行时间,减少昂贵的安装时间,并消除这种将单个逻辑测试流拆分为多个测试方法的方法。相反,每个测试都应该是独立的;其范围应包括(a)设立,(b)执行;(c) 断言;(d) 拆除。

    我可以从您的问题中看出,这是一个集成测试,因此设置、依赖关系管理、执行等可能并不简单,所以这种将单个逻辑测试流拆分为多个测试方法的方法可能是为了将复杂的测试流分解为更易消化的单元。如果是这样,那么我建议将这些“步骤”中的每一个分解为私有方法,并从 仅有一个的 @测试 方法例如:

    @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() {...}
    
        2
  •  1
  •   Zg Mglw    4 年前

    对于我的集成测试,我添加了以下内容(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();
    }
    

    等等

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