如何在Cucumber中获取失败Scenario的错误信息及报错行号
Cucumber获取失败场景错误信息及行号的解决方案
针对你遇到的三个问题,直接给出可行的解决方法和代码修改:
1. 存储失败场景的错误信息与行号
Cucumber并行执行时场景会在独立线程中运行,用ThreadLocal存储错误信息能避免线程冲突,确保每个场景的错误数据独立。修改你的TestListener类:
public class TestListener implements ConcurrentEventListener { // 线程本地变量,存储每个场景的错误、名称和报错行号 public static final ThreadLocal<Throwable> SCENARIO_ERROR = new ThreadLocal<>(); public static final ThreadLocal<String> SCENARIO_NAME = new ThreadLocal<>(); public static final ThreadLocal<Integer> ERROR_LINE_NUMBER = new ThreadLocal<>(); @Override public void setEventPublisher(EventPublisher publisher) { publisher.registerHandlerFor(TestCaseFinished.class, this::handleTestCaseFinished); } private void handleTestCaseFinished(TestCaseFinished event) { TestCase testCase = event.getTestCase(); Result result = event.getResult(); SCENARIO_NAME.set(testCase.getName()); if (result.getStatus() == Status.FAILED) { Throwable error = result.getError(); SCENARIO_ERROR.set(error); // 从错误栈中提取步骤定义的报错行号(需替换为你的步骤类包名) if (error != null) { for (StackTraceElement element : error.getStackTrace()) { if (element.getClassName().startsWith("com.yourpackage.steps")) { ERROR_LINE_NUMBER.set(element.getLineNumber()); break; } } } } else { // 非失败场景清空变量,避免内存泄漏 SCENARIO_ERROR.remove(); ERROR_LINE_NUMBER.remove(); } } }
2. 解决EventPublisher传入null的错误
你不需要手动调用setEventPublisher,Cucumber会自动管理监听器的生命周期并注入有效的EventPublisher实例。直接删除以下错误代码:
// 删掉这两行代码 EventPublisher eventPublisher = null; setEventPublisher(eventPublisher);
然后需要让Cucumber识别你的监听器:
- 在
src/test/resources下创建cucumber.properties文件,添加:cucumber.plugin=com.yourpackage.TestListener - 或者在JUnit运行器类中配置:
@CucumberOptions(plugin = {"com.yourpackage.TestListener"}) public class CucumberTestRunner {}
3. 解决Scenario无getError()方法的问题
Cucumber的Scenario接口确实没有提供getError()方法,需要从监听器的ThreadLocal变量中获取错误信息。修改你的@After钩子:
@After public void nameCatcher(Scenario scenario) throws Exception { if (seleniumCore.driver != null) { seleniumCore.driver.quit(); } if(scenario.isFailed()) { testRailAPItBean.setExecutionResultStatus(TestRailAPIConst.TEST_FAILED); // 从监听器的线程变量中获取错误数据 Throwable error = TestListener.SCENARIO_ERROR.get(); Integer errorLine = TestListener.ERROR_LINE_NUMBER.get(); String scenarioName = TestListener.SCENARIO_NAME.get(); // 将错误信息和行号存入变量或上传到TestRail if (error != null) { String errorDetails = error.getMessage() + " (报错行号: " + errorLine + ")"; testRailAPItBean.setErrorDetails(errorDetails); } } else if (scenario.getStatus() == Status.PASSED) { testRailAPItBean.setExecutionResultStatus(TestRailAPIConst.TEST_PASSED); } TestrailRestApi.updateTestCaseResulForTheLastActiveRun(); // 清空线程变量,防止内存泄漏 TestListener.SCENARIO_ERROR.remove(); TestListener.ERROR_LINE_NUMBER.remove(); TestListener.SCENARIO_NAME.remove(); }
优化Gradle配置
移除重复依赖,替换为JUnit Platform兼容的Cucumber依赖:
plugins { id("java") } group = "org.example" version = "master-SNAPSHOT" repositories { mavenCentral() } dependencies { testImplementation(platform("org.junit:junit-bom:5.9.1")) testImplementation("org.junit.jupiter:junit-jupiter") testImplementation ("io.cucumber:cucumber-java:7.13.0") testImplementation ("io.cucumber:cucumber-junit-platform-engine:7.13.0") } tasks.test { useJUnitPlatform() }
内容的提问来源于stack exchange,提问作者Andreas Panteli
相关产品推荐
相关产品推荐

