视觉测试
它能做什么?
WebdriverIO提供屏幕、元素或整个页面的图像比较功能,适用于:
- 🖥️ 桌面浏览器(Chrome / Firefox / Safari / Microsoft Edge)
- 📱 移动/平板浏览器(通过Appium在Android模拟器上的Chrome / iOS模拟器上的Safari / 模拟器 / 真实设备)
- 📱 原生应用(通过Appium在Android模拟器 / iOS模拟器 / 真实设备上)(🌟 新功能 🌟)
- 📳 通过Appium的混合应用
这些功能通过轻量级WebdriverIO服务@wdio/visual-service
提供。
这使您能够:
- 保存或比较屏幕/元素/整页截图与基准图像
- 当没有基准图像时自动创建基准
- 屏蔽自定义区域,甚至在比较期间自动排除状态栏和工具栏(仅限移动设备)
- 增加元素尺寸截图
- 在网站比较期间隐藏文本,以:
- 提高稳定性并防止字体渲染不稳定
- 只关注网站的布局
- 使用不同的比较方法和一组额外的匹配器,使测试更易读
- 验证您的网站如何支持键盘Tab键导航,参见通过网站Tab导航
- 以及更多功能,查看服务和方法选项
该服务是一个轻量级模块,用于为所有浏览器/设备检索所需的数据和截图。比较功能来自ResembleJS。如果您想在线比较图像,可以查看在线工具。
方法saveScreen
、saveElement
、checkScreen
、checkElement
以及匹配器toMatchScreenSnapshot
和toMatchElementSnapshot
可用于原生应用/上下文。
如果您想将其用于混合应用,请在服务设置中使用isHybridApp:true
属性。
安装
最简单的方法是通过以下命令将@wdio/visual-service
作为开发依赖保存在您的package.json
中:
npm install --save-dev @wdio/visual-service
使用方法
@wdio/visual-service
可以作为普通服务使用。您可以在配置文件中按以下方式设置:
import path from "node:path";
// wdio.conf.ts
export const config = {
// ...
// =====
// Setup
// =====
services: [
[
"visual",
{
// 一些选项,查看文档了解更多
baselineFolder: path.join(process.cwd(), "tests", "baseline"),
formatImageName: "{tag}-{logName}-{width}x{height}",
screenshotPath: path.join(process.cwd(), "tmp"),
savePerInstance: true,
// ... 更多选项
},
],
],
// ...
};
更多服务选项可以在这里找到。
在WebdriverIO配置中设置好后,您可以继续向您的测试添加视觉断言。
能力配置
要使用视觉测试模块,您不需要向能力配置添加任何额外选项。但是,在某些情况下,您可能希望向视觉测试添加额外的元数据,例如logName
。
logName
允许您为每个能力分配一个自定义名称,然后可以将其包含在图像文件名中。这对于区分在不同浏览器、设备或配置上拍摄的截图特别有用。
要启用此功能,您可以在capabilities
部分定义logName
,并确保视觉测试服务中的formatImageName
选项引用它。以下是设置方法:
import path from "node:path";
// wdio.conf.ts
export const config = {
// ...
// =====
// Setup
// =====
capabilities: [
{
browserName: 'chrome',
'wdio-ics:options': {
logName: 'chrome-mac-15', // Chrome的自定义日志名
},
}
{
browserName: 'firefox',
'wdio-ics:options': {
logName: 'firefox-mac-15', // Firefox的自定义日志名
},
}
],
services: [
[
"visual",
{
// 一些选项,查看文档了解更多
baselineFolder: path.join(process.cwd(), "tests", "baseline"),
screenshotPath: path.join(process.cwd(), "tmp"),
// 下面的格式将使用capabilities中的`logName`
formatImageName: "{tag}-{logName}-{width}x{height}",
// ... 更多选项
},
],
],
// ...
};
工作原理
-
设置
logName
:- 在
capabilities
部分,为每个浏览器或设备分配一个唯一的logName
。例如,chrome-mac-15
标识在macOS 15版本上运行的Chrome测试。
- 在
-
自定义图像命名:
-
formatImageName
选项将logName
集成到截图文件名中。例如,如果tag
是homepage,分辨率是1920x1080
,则生成的文件名可能如下所示:homepage-chrome-mac-15-1920x1080.png
-
-
自定义命名的好处:
- 区分来自不同浏览器或设备的截图变得更加容易,特别是在管理基准和调试差异时。
-
默认值说明:
- 如果在capabilities中未设置
logName
,则formatImageName
选项将在文件名中显示为空字符串(homepage--15-1920x1080.png
)
- 如果在capabilities中未设置
WebdriverIO MultiRemote
我们也支持MultiRemote。为了使其正常工作,请确保您在capabilities中添加了wdio-ics:options
,如下所示。这将确保每个截图都有自己的唯一名称。
与使用testrunner相比,编写测试不会有任何不同
// wdio.conf.js
export const config = {
capabilities: {
chromeBrowserOne: {
capabilities: {
browserName: "chrome",
"goog:chromeOptions": {
args: ["disable-infobars"],
},
// 这个!!!
"wdio-ics:options": {
logName: "chrome-latest-one",
},
},
},
chromeBrowserTwo: {
capabilities: {
browserName: "chrome",
"goog:chromeOptions": {
args: ["disable-infobars"],
},
// 这个!!!
"wdio-ics:options": {
logName: "chrome-latest-two",
},
},
},
},
};
以编程方式运行
以下是通过remote
选项使用@wdio/visual-service
的最小示例:
import { remote } from "webdriverio";
import VisualService from "@wdio/visual-service";
let visualService = new VisualService({
autoSaveBaseline: true,
});
const browser = await remote({
logLevel: "silent",
capabilities: {
browserName: "chrome",
},
});
// "启动"服务,将自定义命令添加到`browser`
visualService.remoteSetup(browser);
await browser.url("https://webdriver.io/");
// 或使用此方法仅保存截图
await browser.saveFullPageScreen("examplePaged", {});
// 或使用此方法进行验证。这两种方法不需要组合使用,参见FAQ
await browser.checkFullPageScreen("examplePaged", {});
await browser.deleteSession();
通过网站Tab导航
您可以通过使用键盘TAB键检查网站是否可访问。测试可访问性的这部分一直是一项耗时的(手动)工作,并且通过自动化实现相当困难。
使用saveTabbablePage
和checkTabbablePage
方法,您现在可以在网站上绘制线条和点来验证Tab键导航顺序。
请注意,这仅适用于桌面浏览器,不适用于移动设备。所有桌面浏览器都支持此功能。
这项工作的灵感来自Viv Richards的博客文章"AUTOMATING PAGE TABABILITY (IS THAT A WORD?) WITH VISUAL TESTING"。
可Tab导航元素的选择方式基于模块tabbable。如果有关于Tab导航的任何问题,请查看README.md,特别是更多详情部分。
工作原理
这两种方法都会在您的网站上创建一个canvas
元素,并绘制线条和点来显示如果最终用户使用Tab键会导航到哪里。之后,它会创建一个全页截图,为您提供流程的良好概览。
仅在您需要创建截图而不想将其与基准图像进行比较时使用saveTabbablePage
。
当您想将Tab导航流程与基准进行比较时,可以使用checkTabbablePage
方法。您不需要同时使用这两种方法。如果已经创建了基准图像(可以通过在实例化服务时提供autoSaveBaseline: true
自动完成),
则checkTabbablePage
将首先创建_实际_图像,然后将其与基准进行比较。
选项
这两种方法使用与saveFullPageScreen
或
compareFullPageScreen
相同的选项。
示例
这是Tab导航在我们的测试网站上如何工作的示例:
自动更新失败的视觉快照
通过添加参数--update-visual-baseline
在命令行中更新基准图像。这将
- 自动复制实际拍摄的截图并将其放入基准文件夹
- 如果有差异,它将让测试通过,因为基准已更新
用法:
npm run test.local.desktop --update-visual-baseline
在日志信息/调试模式下运行时,您将看到以下添加的日志:
[0-0] ..............
[0-0] #####################################################################################
[0-0] INFO:
[0-0] Updated the actual image to
[0-0] /Users/wswebcreation/Git/wdio/visual-testing/localBaseline/chromel/demo-chrome-1366x768.png
[0-0] #####################################################################################
[0-0] ..........
TypeScript支持
本模块包含TypeScript支持,让您在使用视觉测试服务时能够受益于自动完成、类型安全和改进的开发体验。
步骤1:添加类型定义
为确保TypeScript识别模块类型,请在tsconfig.json的types字段中添加以下条目:
{
"compilerOptions": {
"types": ["@wdio/visual-service"]
}
}
步骤2:为服务选项启用类型安全
要对服务选项强制类型检查,请更新您的WebdriverIO配置:
// wdio.conf.ts
import { join } from 'node:path';
// 导入类型定义
import type { VisualServiceOptions } from '@wdio/visual-service';
export const config = {
// ...
// =====
// Setup
// =====
services: [
[
"visual",
{
// 服务选项
baselineFolder: join(process.cwd(), './__snapshots__/'),
formatImageName: '{tag}-{logName}-{width}x{height}',
screenshotPath: join(process.cwd(), '.tmp/'),
} satisfies VisualServiceOptions, // 确保类型安全
],
],
// ...
};
系统要求
版本5及以上
对于版本5及以上,该模块是一个纯JavaScript模块,除了项目要求外,没有额外的系统依赖项。它使用Jimp,这是一个完全用JavaScript编写的Node.js图像处理库,没有原生依赖项。
版本4及以下
对于版本4及以下,该模块依赖于Canvas,这是一个适用于Node.js的canvas实现。Canvas依赖于Cairo。
安装详情
默认情况下,在您项目的npm install
期间,将下载适用于macOS、Linux和Windows的二进制文件。如果您没有受支持的操作系统或处理器架构,则该模块将在您的系统上编译。这需要几个依赖项,包括Cairo和Pango。
有关详细的安装信息,请参见node-canvas wiki。以下是常见操作系统的一行安装说明。请注意,libgif/giflib
、librsvg
和libjpeg
是可选的,仅在需要GIF、SVG和JPEG支持时才需要。需要Cairo v1.10.0或更高版本。
- OS
- Ubuntu
- Fedora
- Solaris
- OpenBSD
- Window
- Others
使用Homebrew:
brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman
Mac OS X v10.11+: 如果您最近更新到Mac OS X v10.11+并在编译时遇到问题,请运行以下命令:xcode-select --install
。在Stack Overflow上阅读更多关于此问题的信息。
如果您安装了Xcode 10.0或更高版本,要从源代码构建,您需要NPM 6.4.1或更高版本。
sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev
sudo yum install gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel
pkgin install cairo pango pkg-config xproto renderproto kbproto xextproto
doas pkg_add cairo pango png jpeg giflib
请参见wiki
请参见wiki