1. 概述
在使用 Selenium 编写自动化测试时,我们经常需要对网页或页面的某一部分进行截图。这在调试测试失败或验证应用在不同浏览器中行为一致性时非常有用。
本文将介绍几种在 JUnit 测试中通过 Selenium WebDriver 实现截图的方法。✅
如果你对 Selenium 测试还不熟悉,可以先阅读我们的 Selenium 使用指南。
2. 依赖与配置
首先,在 pom.xml
中添加 Selenium 依赖:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
最新版本可从 Maven Central 获取。同时,Chrome Driver 的最新版本可以从其官网下载。
接下来,在单元测试中配置 ChromeDriver:
private static ChromeDriver driver;
@BeforeClass
public static void setUp() {
System.setProperty("webdriver.chrome.driver", resolveResourcePath("chromedriver.mac"));
Capabilities capabilities = DesiredCapabilities.chrome();
driver = new ChromeDriver(capabilities);
driver.manage()
.timeouts()
.implicitlyWait(5, TimeUnit.SECONDS);
driver.get("http://www.google.com/");
}
这是一个标准的 ChromeDriver 配置,用于控制本地 Chrome 浏览器。我们设置了 5 秒的隐式等待时间,避免元素未加载完成就操作导致异常。⚠️
最后,在测试执行前打开 Google 首页作为操作目标。
3. 截取可视区域
Selenium 提供了 TakesScreenshot
接口,可以直接用于截取当前浏览器窗口的可视区域。
我们封装一个简单的截图方法:
public void takeScreenshot(String pathname) throws IOException {
File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(src, new File(pathname));
}
关键点如下:
- ✅ 将
driver
强转为TakesScreenshot
接口 - ✅ 调用
getScreenshotAs(OutputType.FILE)
获取截图文件对象 - ✅ 使用 Apache Commons IO 的
FileUtils.copyFile
保存到指定路径
整个过程仅需两行核心代码,简单粗暴有效。💥
在测试中调用该方法:
@Test
public void whenGoogleIsLoaded_thenCaptureScreenshot() throws IOException {
takeScreenshot(resolveTestResourcePath("google-home.png"));
assertTrue(new File(resolveTestResourcePath("google-home.png")).exists());
}
截图保存至 test/resources/google-home.png
,并通过断言验证文件是否存在。
4. 截取页面特定元素
有时候我们只关心某个元素(比如登录按钮、弹窗、Logo),而不是整个页面。Selenium 原生 API 不支持直接截取元素,但我们可以借助第三方库 aShot 实现。
aShot 从 Selenium 3 开始被广泛使用,提供了更灵活的截图能力。
先添加依赖:
<dependency>
<groupId>ru.yandex.qatools.ashot</groupId>
<artifactId>ashot</artifactId>
<version>1.5.4</version>
</dependency>
aShot 提供了流畅的 API(Fluent API),可灵活配置截图策略。
下面示例展示如何截取 Google 首页的 Logo:
@Test
public void whenGoogleIsLoaded_thenCaptureLogo() throws IOException {
WebElement logo = driver.findElement(By.id("hplogo"));
Screenshot screenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(1000))
.coordsProvider(new WebDriverCoordsProvider())
.takeScreenshot(driver, logo);
ImageIO.write(screenshot.getImage(), "jpg", new File(resolveTestResourcePath("google-logo.png")));
assertTrue(new File(resolveTestResourcePath("google-logo.png")).exists());
}
关键步骤解析:
- ✅ 使用
findElement(By.id("hplogo"))
定位目标元素 - ✅ 设置截图策略:
viewportPasting(1000)
表示滚动视口并拼接截图,最长等待 1000ms - ✅ 设置坐标提供器:
WebDriverCoordsProvider
使用 WebDriver 原生 API 获取元素坐标,避免 jQuery 兼容性问题 ❌- ⚠️ 默认使用 jQuery 解析坐标,但某些 WebDriver(如 HtmlUnit)不支持 JS,容易踩坑
- ✅ 调用
takeScreenshot(driver, logo)
截取指定元素 - ✅ 使用
ImageIO.write
将Screenshot.getImage()
写入文件
aShot 会自动计算元素位置和尺寸,并从全屏截图中裁剪出目标区域,结果精准可靠。
5. 总结
本文介绍了两种 Selenium 截图方案:
方式 | 工具 | 适用场景 |
---|---|---|
原生 API | TakesScreenshot |
截取整个可视区域,简单直接 |
第三方库 | aShot | 截取特定元素、处理滚动、跨浏览器一致性 |
✅ 推荐在复杂项目中使用 aShot,主要原因:
- 抽象了不同 WebDriver 的截图差异(如 Chrome、Firefox 渲染行为不同)
- 支持元素级截图、滚动拼接、高亮区域等高级功能
- API 设计清晰,易于集成
完整示例代码已托管至 GitHub:https://github.com/eugenp/tutorials/tree/master/testing-modules/selenium
如果你在 CI/CD 中做自动化视觉回归测试,aShot + Image Comparison 是个不错的组合,后续可以单独写一篇展开。