如果前面的步骤在 Junit 中失败,如何跳过剩余的步骤
How to skip remaining steps if previous steps failed in Junit
我有一些集成测试用例,它们 运行 作为具有特殊类别的 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;
而且我无法在多个线程中 运行 它们。
有人有处理这些事情的好主意吗?
谢谢!
新年快乐!
您已将这些编写为 distinct 测试,但这些测试之间存在一些依赖关系。因此,听起来您已将单个逻辑测试流程拆分为多个测试方法。
为了满足这些依赖性,您采用了测试命名约定,并指示 JUnit 运行 按照命名约定隐含的顺序进行这些测试。此外,您的测试用例中有一些共享状态,这些状态正在 'passed from' 步进。
这种方法听起来很脆弱,可能会使以下操作变得非常困难:
- 诊断故障、问题
- 维护现有步骤
- 添加新步骤
如果先前的测试失败,则指示 JUnit - 以某种方式 - 停止在测试用例中执行后续测试,以及使用静态变量将先前的结果传递到下一步都是决定拆分单个逻辑的症状跨多个 @Test
方法进行测试。
JUnit 没有测试用例中后续或先前测试的正式概念。这是故意的,因为 @Test
方法应该相互独立。
因此,与其尝试实施他的行为:如果先前的测试失败,则停止在测试用例中执行后续测试我建议重新访问您的测试以减少它们运行 时间,减少昂贵的设置时间并删除这种将单个逻辑测试流程拆分到多个测试方法的方法。相反,每个测试都应该是独立的;其范围应包括(a) 设立,(b) 执行; (c) 断言; (d) 拆除。
从你的问题中我可以看出这是一个集成测试,因此设置、依赖管理、执行等可能并不简单,所以这种将单个逻辑测试流程拆分为多个测试方法的方法可能是一种努力将复杂的测试流程分解为更易于消化的单元。如果是这样,那么我建议将这些 'steps' 中的每一个分解为私有方法,并从 single @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() {...}
对于我的集成测试,我添加了以下内容(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 来实现(好吧...我没有尝试太多)但我欢迎一个
我有一些集成测试用例,它们 运行 作为具有特殊类别的 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;
而且我无法在多个线程中 运行 它们。
有人有处理这些事情的好主意吗?
谢谢!
新年快乐!
您已将这些编写为 distinct 测试,但这些测试之间存在一些依赖关系。因此,听起来您已将单个逻辑测试流程拆分为多个测试方法。
为了满足这些依赖性,您采用了测试命名约定,并指示 JUnit 运行 按照命名约定隐含的顺序进行这些测试。此外,您的测试用例中有一些共享状态,这些状态正在 'passed from' 步进。
这种方法听起来很脆弱,可能会使以下操作变得非常困难:
- 诊断故障、问题
- 维护现有步骤
- 添加新步骤
如果先前的测试失败,则指示 JUnit - 以某种方式 - 停止在测试用例中执行后续测试,以及使用静态变量将先前的结果传递到下一步都是决定拆分单个逻辑的症状跨多个 @Test
方法进行测试。
JUnit 没有测试用例中后续或先前测试的正式概念。这是故意的,因为 @Test
方法应该相互独立。
因此,与其尝试实施他的行为:如果先前的测试失败,则停止在测试用例中执行后续测试我建议重新访问您的测试以减少它们运行 时间,减少昂贵的设置时间并删除这种将单个逻辑测试流程拆分到多个测试方法的方法。相反,每个测试都应该是独立的;其范围应包括(a) 设立,(b) 执行; (c) 断言; (d) 拆除。
从你的问题中我可以看出这是一个集成测试,因此设置、依赖管理、执行等可能并不简单,所以这种将单个逻辑测试流程拆分为多个测试方法的方法可能是一种努力将复杂的测试流程分解为更易于消化的单元。如果是这样,那么我建议将这些 'steps' 中的每一个分解为私有方法,并从 single @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() {...}
对于我的集成测试,我添加了以下内容(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 来实现(好吧...我没有尝试太多)但我欢迎一个