基于Java的Cucumber:Gherkin特性文件失败后立即重跑方案咨询
解决方案:基于JUnit4 TestRule实现Scenario级立即重试
针对Cucumber 7 + JUnit4环境下的失败Scenario立即重跑需求,可通过自定义JUnit TestRule拦截测试执行流程,实现失败后立即重试,同时保证BeforeAll/AfterAll仅执行一次。
实现步骤
1. 编写自定义重试规则类
该类负责拦截每个Scenario的执行,在失败时触发立即重试,直到达到最大重试次数:
import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; public class CucumberRetryRule implements TestRule { // 最大重试次数 private static final int MAX_RETRY = 2; @Override public Statement apply(Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { Throwable lastFailure = null; for (int retryCount = 0; retryCount <= MAX_RETRY; retryCount++) { try { // 执行当前Scenario base.evaluate(); return; // 测试成功,终止重试 } catch (Throwable t) { lastFailure = t; System.err.printf("Scenario [%s] 失败,第 %d 次重试中...%n", description.getDisplayName(), retryCount + 1); } } // 所有重试失败,抛出最后一次异常 throw lastFailure; } }; } }
2. 配置Cucumber生命周期钩子
确保BeforeAll和AfterAll仅执行一次,在步骤定义包下创建钩子类:
import io.cucumber.java.AfterAll; import io.cucumber.java.BeforeAll; public class SuiteHooks { @BeforeAll public static void beforeAll() { System.out.println("执行BeforeAll()"); // 全局初始化逻辑 } @AfterAll public static void afterAll() { System.out.println("执行AfterAll()"); // 全局清理逻辑 } }
3. 修改Cucumber Runner类
引入重试规则,并确保钩子类在Cucumber的扫描路径中:
import org.junit.Rule; import org.junit.runner.RunWith; import io.cucumber.junit.Cucumber; import io.cucumber.junit.CucumberOptions; import java.util.stream.Stream; @RunWith(Cucumber.class) @CucumberOptions( tags = "@xxx", plugin = {"pretty"}, features = {"classpath:features"}, glue = {"StepDefinitions", "your.package.path"} // 替换为包含SuiteHooks的包路径 ) public class Runner { // 注册重试规则 @Rule public CucumberRetryRule retryRule = new CucumberRetryRule(); private static String[] defaultOptions = { "classpath:features", "--glue", "StepDefinitions", "--tags", "@xxx", "--plugin", "pretty", }; public static void main(String[] args) { Stream<String> cucumberOptions = Stream.concat(Stream.of(defaultOptions), Stream.of(args)); ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); byte exitStatus = io.cucumber.core.cli.Main.run(cucumberOptions.toArray(String[]::new), contextClassLoader); // 自定义PDF报告逻辑 } }
流程验证
该方案完全符合你的预期流程:
- 所有Scenario执行前,仅执行一次
BeforeAll() - 每个Scenario执行前触发
@Before(步骤定义中的非静态钩子) - 执行Scenario,失败则立即重试,最多2次
- 每次Scenario(含重试)执行后触发
@After - 所有Scenario执行完成后,执行
AfterAll()
关键说明
- JUnit4的
TestRule会自动拦截Cucumber生成的每个Scenario测试方法,实现粒度精准的重试控制 - 无需依赖已弃用的Cucumber EventListener,完全适配Cucumber 7.x版本
- 可关闭Maven Surefire的
rerunFailingTestsCount参数,避免重复重试
内容的提问来源于stack exchange,提问作者user22334850
相关产品推荐
相关产品推荐

