如何基于选定环境程序化配置Cucumber标签与Feature文件执行?
基于环境动态指定Cucumber标签与Feature文件的优化方案
你之前用@Before抛SkipException的方式会导致被跳过的场景出现在测试报告中,且属于运行时过滤,效率较低。更优的做法是在测试用例生成阶段就过滤掉不需要的场景/Feature,完全避免生成无关测试用例,报告中也不会出现跳过条目。以下是几种适配Spring Boot+Cucumber+TestNG的简洁实现方式:
方案1:系统属性+Spring环境变量(推荐,最简单)
Cucumber支持通过系统属性直接覆盖@CucumberOptions的配置,结合Spring的环境变量读取能力,可轻松实现环境驱动的动态配置:
1.1 修改测试运行器
保留基础配置,通过系统属性动态覆盖标签和Feature路径:
@SpringBootTest(classes = YourApplication.class) @CucumberOptions( features = {"src/test/resources/Features"}, // 默认路径 glue = {"als.system.tests.stepDefinations"}, plugin = {"pretty", "html:target/cucumber-html-report.html"} ) public class CucumberRunnerTests extends AbstractTestNGCucumberTests { @Value("${test.env:dev}") // 从Spring环境读取,默认dev private String targetEnv; @BeforeClass public void setupCucumberProps() { // 动态设置标签过滤规则 System.setProperty("cucumber.filter.tags", "@" + targetEnv.toLowerCase()); // 动态指定Feature目录(按环境分目录存放时使用) System.setProperty("cucumber.features", "src/test/resources/Features/" + targetEnv); } }
1.2 启动测试时指定环境
通过JVM参数或Spring配置文件指定目标环境:
# Maven启动时指定prod环境 mvn test -Dtest.env=prod # Gradle启动时指定prod环境 ./gradlew test -Dtest.env=prod
也可在src/test/resources/application-test.properties中配置默认环境:
test.env=dev
方案2:重写TestNG DataProvider(自定义过滤逻辑)
如果需要更复杂的过滤规则(比如多标签组合、Feature路径匹配),可重写AbstractTestNGCucumberTests的scenarios() DataProvider,直接过滤掉不需要的场景:
@SpringBootTest(classes = YourApplication.class) @CucumberOptions( features = {"src/test/resources/Features"}, glue = {"als.system.tests.stepDefinations"}, plugin = {"pretty", "html:target/cucumber-html-report.html"} ) public class CucumberRunnerTests extends AbstractTestNGCucumberTests { @Value("${test.env:dev}") private String targetEnv; @Override @DataProvider(parallel = true) public Object[][] scenarios() { // 获取所有原始场景 Object[][] allScenarios = super.scenarios(); // 过滤出符合目标环境标签的场景 return Arrays.stream(allScenarios) .filter(scenario -> { PickleWrapper pickle = (PickleWrapper) scenario[0]; // 提取场景所有标签 Set<String> tags = pickle.getPickle().getTags().stream() .map(PickleTag::getName) .collect(Collectors.toSet()); // 匹配目标环境标签,可扩展多标签逻辑 return tags.contains("@" + targetEnv.toLowerCase()); }) .toArray(Object[][]::new); } }
此方案完全自定义过滤逻辑,过滤后的场景才会生成测试用例,报告中仅显示实际执行的内容。
方案3:Cucumber编程式API(高级自定义)
若需要极致灵活的配置(比如动态加载Feature路径、多环境组合),可直接使用Cucumber的TestNG编程式API:
import io.cucumber.testng.CucumberOptions; import io.cucumber.testng.CucumberOptionsBuilder; import io.cucumber.testng.FeatureWrapper; import io.cucumber.testng.PickleWrapper; import io.cucumber.testng.TestNGCucumberRunner; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @SpringBootTest(classes = YourApplication.class) public class CucumberRunnerTests { @Value("${test.env:dev}") private String targetEnv; private TestNGCucumberRunner testRunner; @BeforeClass(alwaysRun = true) public void setUp() { // 动态构建Cucumber配置 CucumberOptions options = new CucumberOptionsBuilder() .features("src/test/resources/Features/" + targetEnv) .glue("als.system.tests.stepDefinations") .tags("@" + targetEnv) .plugin("pretty", "html:target/cucumber-html-report.html") .build(); testRunner = new TestNGCucumberRunner(this.getClass(), options); } @Test(groups = "cucumber", dataProvider = "scenarios") public void runScenario(PickleWrapper pickle, FeatureWrapper feature) { testRunner.runScenario(pickle.getPickle()); } @DataProvider(parallel = true) public Object[][] scenarios() { return testRunner.provideScenarios(); } @AfterClass(alwaysRun = true) public void tearDown() { testRunner.finish(); } }
此方案完全脱离注解配置,所有参数均可程序化生成,适合复杂的多环境测试场景。
内容的提问来源于stack exchange,提问作者Harshit Soni
相关产品推荐
相关产品推荐

