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

如何在Selenium WebDriver中将截图存为字符串并保存到Excel工作表

问题改造方案

你当前代码存在两个核心问题:

  1. 原本的FailedTestScreenCapture是JUnit专属的测试规则,只会在JUnit执行用例抛出异常时自动触发截图,你当前自定义的main方法循环执行测试逻辑,完全没有走JUnit执行链,原有截图逻辑不会触发
  2. 你直接调用failedTstCase.toString()拿到的只是对象内存地址,无法获取截图路径;且你初始化FailedTestScreenCapture时driver还是null,就算触发截图也会报空指针

1. 改造FailedTestScreenCapture类

将截图方法改为可主动调用,同时返回截图的存储路径,方便后续写入Excel:

package utilities;

import java.io.File;
import java.util.UUID;
import org.openqa.selenium.io.FileHandler;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

public class FailedTestScreenCapture implements MethodRule {
    private WebDriver driver;
    // 统一管理截图存储根路径
    private static final String SCREENSHOT_DIR = "./Screenshots/";

    public FailedTestScreenCapture(WebDriver driver) {
        this.driver = driver;
        // 初始化时自动创建截图目录,避免路径不存在报错
        File dir = new File(SCREENSHOT_DIR);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    // 新增:支持主动调用的截图方法,返回截图完整存储路径
    public String captureScreen(String caseName) {
        try {
            TakesScreenshot ts = (TakesScreenshot) driver;
            File source = ts.getScreenshotAs(OutputType.FILE);
            String fileName = caseName + "_" + UUID.randomUUID() + ".jpg";
            String fullPath = SCREENSHOT_DIR + fileName;
            FileHandler.copy(source, new File(fullPath));
            return fullPath;
        } catch (Exception e) {
            System.out.println("截图失败:" + e.getMessage());
            return "";
        }
    }

    // 保留原有JUnit规则逻辑,不影响后续JUnit用例执行
    @Override
    public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object obj) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                try {
                    statement.evaluate();
                } catch (Throwable t) {
                    captureScreen(frameworkMethod.getName());
                    throw t;
                }
            }
        };
    }
}

2. 修正OTMGeneral类逻辑

调整两个核心点:

  • 把FailedTestScreenCapture的初始化时机延后到driver实例化之后,避免空指针
  • 测试失败分支主动调用截图方法,将获取到的截图路径写入Excel
package view;

import java.io.IOException;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

import utilities.ExcelUtils;
import utilities.FailedTestScreenCapture;
import utilities.Constants;

public class OTMGeneral {
    static WebDriver driver;
    static ExcelUtils excelUtils = new ExcelUtils();
    // 取消静态初始化,等driver创建后再实例化
    static FailedTestScreenCapture failedTstCase;
    static String excelFilePath = Constants.Path_TestData + Constants.File_TestData;

    public static void main(String args[]) throws IOException {
        System.setProperty("webdriver.chrome.driver", Constants.chromeDriverPath);
        driver = new ChromeDriver();
        // 在这里初始化截图工具,此时driver已经完成实例化
        failedTstCase = new FailedTestScreenCapture(driver);

        driver.manage().window().maximize();
        driver.navigate().to(Constants.BaseUrl);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));

        WebElement continueBtn = driver.findElement(By.xpath("/html/body/div[1]/div/div/div[2]/button"));
        WebElement loginBtn = driver.findElement(By.xpath("/html/body/header/div/div/nav/div/ul/li[2]/a"));
        WebElement popupMsg = driver.findElement(By.xpath("/html/body/div[1]/div/div"));

        if (popupMsg.isDisplayed()) {
            continueBtn.click();
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
            loginBtn.click();
        } else {
            loginBtn.click();
        }

        WebElement email = driver.findElement(By.id("Email"));
        WebElement pwd = driver.findElement(By.id("Password"));
        WebElement signInBtn = driver.findElement(By.id("btnlogin"));

        excelUtils.setExcelFile(excelFilePath, "Login_Data");

        for (int i = 1; i <= excelUtils.getRowCountInSheet(); i++) {
            if (i > 1) {
                driver.navigate().refresh();
                driver.findElement(By.xpath("/html/body/header/div/div/nav/div/ul/li[2]/a")).click();
                driver.findElement(By.id("Email")).sendKeys(excelUtils.getCellData(i, 0));
                driver.findElement(By.id("Password")).sendKeys(excelUtils.getCellData(i, 1));
                driver.findElement(By.id("btnlogin")).click();
            } else {
                driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
                email.sendKeys(excelUtils.getCellData(i, 0));
                pwd.sendKeys(excelUtils.getCellData(i, 1));
                signInBtn.click();
            }

            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
            boolean helloCustomer = driver.findElement(By.xpath("/html/body/header/div/div/nav/div/ul/li[1]/a"))
                    .getText().equalsIgnoreCase("Regístrate");
            System.out.println(helloCustomer);

            if (!helloCustomer) {
                excelUtils.setCellValue(i, 2, "Pass", excelFilePath);
                System.out.println("login pass");
                WebElement logout = driver.findElement(By.id("logout"));
                logout.click();
            } else {
                excelUtils.setCellValue(i, 2, "Fail", excelFilePath);
                System.out.println("login fail");
                // 主动调用截图方法,传入用例行号作为标识,拿到截图路径
                String screenshotPath = failedTstCase.captureScreen("login_case_" + i);
                excelUtils.setCellValue(i, 3, screenshotPath, excelFilePath);
            }
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
        }
        driver.quit();
    }
}

3. 可选:直接嵌入截图到Excel单元格

如果不需要存路径,要把截图直接插入到Excel单元格中,可给ExcelUtils新增插入图片的方法(基于Apache POI实现):

// 该方法加入ExcelUtils类即可
public void addScreenshotToCell(Workbook workbook, Sheet sheet, int rowNum, int colNum, String imgPath) throws IOException {
    if (imgPath == null || imgPath.isEmpty()) return;
    File imgFile = new File(imgPath);
    if (!imgFile.exists()) return;

    byte[] imgBytes = Files.readAllBytes(imgFile.toPath());
    int pictureIdx = workbook.addPicture(imgBytes, Workbook.PICTURE_TYPE_JPEG);
    CreationHelper helper = workbook.getCreationHelper();
    Drawing<?> drawing = sheet.createDrawingPatriarch();
    ClientAnchor anchor = helper.createClientAnchor();
    // 设置图片插入的位置
    anchor.setCol1(colNum);
    anchor.setRow1(rowNum);
    // 设置图片占用单元格范围,可按需调整
    anchor.setCol2(colNum + 1);
    anchor.setRow2(rowNum + 1);
    Picture pic = drawing.createPicture(anchor, pictureIdx);
    pic.resize(0.5); // 按比例缩放图片
}

在测试失败分支拿到截图路径后,调用上述方法即可把图片插入到指定单元格。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:24:01