如何在JUnit5 Cucumber中隔离运行含重复步骤定义的测试套件
我有两个基于JUnit5平台的Cucumber测试套件:
套件A
@Suite @IncludeEngines("cucumber") @SelectPackages("de.bla.blubb1") @SelectClasspathResource("de/bla/blubb1") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "de.bla.blubb1") @ConfigurationParameter(key = PLUGIN_PUBLISH_QUIET_PROPERTY_NAME, value = "true") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty,json:target/blubb1cucumber.json") public class RunBlubb1CucumberTest { // 无代码 }
套件B
@Suite @IncludeEngines("cucumber") @SelectPackages("de.bla.blubb2") @SelectClasspathResource("de/bla/blubb2") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "de.bla.blubb2") @ConfigurationParameter(key = PLUGIN_PUBLISH_QUIET_PROPERTY_NAME, value = "true") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty,json:target/blubb2cucumber.json") public class RunBlubb2CucumberTest { // 无代码 }
步骤定义类与对应测试套件同包,两个套件的步骤定义存在重复(仅方法体不同),示例步骤定义如下:
@Gegebensei("Example") public void gegebenSeiExample(Map<String, Map<String, String>> map) { for (Entry<String, Map<String, String>> e : map.entrySet()) { blabla.put(e.getKey(), new BlaMock(e.getValue())); } }
单独运行任意一个套件时测试全部通过,但运行所有测试时会抛出DuplicateStepDefinitionException:
DuplicateStepDefinitionException io.cucumber.core.runner.DuplicateStepDefinitionException: Duplicate step definitions in de.bla.blubb1.StepDefsEingangsparameter.erstelle() and de.bla.blubb2.StepDefsEingangsparameter.erstelle() at io.cucumber.core.runner.CachingGlue.lambda$prepareGlue$3(CachingGlue.java:278) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at io.cucumber.core.runner.CachingGlue.prepareGlue(CachingGlue.java:272) at io.cucumber.core.runner.Runner.runPickle(Runner.java:72) at io.cucumber.junit.platform.engine.CucumberEngineExecutionContext.lambda$runTestCase$4(CucumberEngineExecutionContext.java:112) at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$5(CucumberExecutionContext.java:136) at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23) at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:136) at io.cucumber.junit.platform.engine.CucumberEngineExecutionContext.runTestCase(CucumberEngineExecutionContext.java:109) at io.cucumber.junit.platform.engine.NodeDescriptor$PickleDescriptor.execute(NodeDescriptor.java:168) at io.cucumber.junit.platform.engine.NodeDescriptor$PickleDescriptor.execute(NodeDescriptor.java:90) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
已尝试在运行配置中按类fork,但会大幅降低其他测试的运行效率。需求要求步骤定义保持原样(重命名方案不可行),希望找到无需修改Maven和运行配置的隔离方法,优先通过注解或配置属性实现。
可以通过以下两种方式实现测试套件的隔离,无需修改Maven或运行配置:
1. 使用JUnit 5的@Isolated注解
JUnit 5提供的@Isolated注解可让标记的测试类在独立JVM进程中运行,彻底隔离两个套件的Glue上下文,避免重复步骤定义冲突。
只需在两个测试套件类上添加该注解:
@Suite @Isolated // 添加此注解 @IncludeEngines("cucumber") @SelectPackages("de.bla.blubb1") // 其他原有注解和配置 public class RunBlubb1CucumberTest { ... }
@Suite @Isolated // 添加此注解 @IncludeEngines("cucumber") @SelectPackages("de.bla.blubb2") // 其他原有注解和配置 public class RunBlubb2CucumberTest { ... }
注意:该注解需要JUnit Platform 1.8.0及以上版本支持,仅在使用JUnit Platform的测试引擎(包括Cucumber JUnit Platform Engine)时生效。
2. 配置Cucumber的Glue隔离
如果不想启动独立JVM,可通过Cucumber的配置参数强制每个套件使用独立的Glue上下文。在测试套件类中添加@ConfigurationParameter配置GLUE_USE_SINGLETON_PROPERTY_NAME为false:
@Suite @IncludeEngines("cucumber") @SelectPackages("de.bla.blubb1") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "de.bla.blubb1") @ConfigurationParameter(key = GLUE_USE_SINGLETON_PROPERTY_NAME, value = "false") // 添加此配置 // 其他原有配置 public class RunBlubb1CucumberTest { ... }
同样在套件B中添加该配置。此参数会让Cucumber为每个测试套件创建独立的Glue实例,避免全局上下文共享导致的重复步骤定义冲突。
注意:该参数需要Cucumber 7.0.0及以上版本支持,仅在JUnit Platform环境下有效。
内容的提问来源于stack exchange,提问作者Kuronashi

