You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JUnit5测试失败时自动截图并集成Allure2报告的实现方案

解决方案:测试失败截图集成Allure2+并行执行+Teardown信息展示

核心思路

放弃JUnit5 TestWatcher的冗余实现,改用Allure原生的TestLifecycleListener接口,利用其beforeTestStop方法在测试结束前统一处理:测试失败截图、Driver销毁、Teardown信息上报。该方案天然适配并行执行(依赖ThreadLocal隔离Driver),且能避免之前Driver提前销毁导致的空指针问题。


步骤1:重构TestBase类

移除原@ExtendWith(CustomTestWatcher.class)注解,取消@AfterEach的Driver销毁逻辑,统一交由Allure Listener处理:

public class TestBase {

    protected WebDriver driver;
    private static final String BASE_URL = "你的测试基础URL";

    @BeforeAll
    public static void beforeAll() {
        AllureFeatures.generateEnvironmentVariablesForAllure(); // 生成Allure环境配置
    }

    @BeforeEach
    public void setupDriver() {
        WebDriverThreadLocal.setDriver();
        this.driver = WebDriverThreadLocal.getDriver();
        driver.get(BASE_URL);
        // 可选:给Allure报告添加初始化步骤
        Allure.step("初始化浏览器,打开基础URL: " + BASE_URL);
    }
}

步骤2:实现Allure生命周期监听器

创建CustomAllureListener类,实现TestLifecycleListener接口,在beforeTestStop中统一处理所有测试状态的逻辑:

import io.qameta.allure.Allure;
import io.qameta.allure.model.Status;
import io.qameta.allure.testframework.TestLifecycleListener;
import io.qameta.allure.testframework.TestResult;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

import java.io.ByteArrayInputStream;

public class CustomAllureListener implements TestLifecycleListener {

    @Override
    public void beforeTestStop(TestResult result) {
        // 获取当前线程的Driver(ThreadLocal保证并行安全)
        WebDriver driver = WebDriverThreadLocal.getDriver();
        if (driver == null) {
            return;
        }

        // 测试失败时捕获截图并添加到Allure报告
        if (result.getStatus() == Status.FAILED) {
            try {
                byte[] screenshotBytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
                Allure.addAttachment("测试失败截图", new ByteArrayInputStream(screenshotBytes));
                Allure.step("测试执行失败,已捕获浏览器截图");
            } catch (Exception e) {
                Allure.step("截图捕获失败: " + e.getMessage());
            }
        }

        // 统一执行Driver销毁,无论测试结果如何
        try {
            WebDriverThreadLocal.teardown();
            Allure.step("执行Teardown:关闭浏览器并释放Driver资源");
        } catch (Exception e) {
            Allure.step("Teardown执行失败: " + e.getMessage());
        }
    }
}

步骤3:注册Allure监听器

在项目的src/main/resources/META-INF/services目录下创建文件io.qameta.allure.testframework.TestLifecycleListener,写入监听器的全类名(替换为你的实际包路径):

com.your.package.CustomAllureListener

步骤4:确保ThreadLocal Driver的线程安全

WebDriverThreadLocal类需保证每个线程持有独立的Driver实例,支持并行执行:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class WebDriverThreadLocal {
    private static final ThreadLocal<WebDriver> driverThreadLocal = new ThreadLocal<>();

    public static void setDriver() {
        // 可根据需求扩展为多浏览器支持
        WebDriver driver = new ChromeDriver();
        driverThreadLocal.set(driver);
    }

    public static WebDriver getDriver() {
        return driverThreadLocal.get();
    }

    public static void teardown() {
        WebDriver driver = driverThreadLocal.get();
        if (driver != null) {
            driver.quit();
            driverThreadLocal.remove(); // 清理ThreadLocal资源,避免内存泄漏
        }
    }
}

方案优势

  1. 消除代码冗余:无需在TestWatcher的4种测试状态方法中重复调用销毁逻辑,统一在beforeTestStop处理。
  2. 解决Driver空指针问题:截图操作在Driver销毁前执行,保证Driver实例有效。
  3. 并行执行兼容:依赖ThreadLocal隔离每个线程的Driver实例,无线程安全问题。
  4. Teardown信息可视化:通过Allure.step添加的操作会直接显示在Allure报告的测试步骤列表中,清晰展示销毁过程。

内容的提问来源于stack exchange,提问作者FlappyCat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:45:36