如何用Playwright和Cucumber进行视觉测试(图像对比)
解决Playwright + Cucumber中视觉测试
toHaveScreenshot()/toMatchSnapshot()报错问题 核心原因
Playwright的快照断言方法依赖自身测试运行器提供的上下文来管理快照的创建、对比和存储,而Cucumber的Given/When/Then步骤定义中不存在该上下文,直接调用就会触发Error: toMatchSnapshot() must be called during the test。
可行解决方案
1. 用Playwright原生assert模块手动实现快照对比
绕过Playwright的expect断言,直接调用底层API处理截图和对比:
const { assert } = require('@playwright/test'); Then('页面应匹配基准快照', async function () { // 捕获当前页面截图 const screenshot = await page.screenshot(); // 手动对比快照,可配置差异阈值 await assert.snapshot(screenshot, 'page-baseline.png', { maxDiffPixels: 100 }); });
快照默认会存储在测试文件同层级的__snapshots__目录下,首次运行需手动确认基准快照的正确性。
2. 给Cucumber World绑定Playwright测试上下文
通过自定义Cucumber的World对象,注入Playwright测试上下文,让步骤能支持原生快照断言:
首先在world.js中配置:
const { World } = require('@cucumber/cucumber'); const { test } = require('@playwright/test'); class CustomWorld extends World { constructor(options) { super(options); this.playwrightTest = test; } } module.exports = { CustomWorld };
然后在步骤定义中使用:
Then('页面应匹配基准快照', async function () { await this.playwrightTest.expect(page).toHaveScreenshot('page-baseline.png'); });
这种方式让Cucumber步骤拥有Playwright测试运行器的上下文,完全兼容原生快照断言逻辑。
3. 用第三方库手动实现像素对比
如果上述方案不适用,可使用pixelmatch配合文件系统模块自行实现视觉对比:
const fs = require('fs').promises; const path = require('path'); const pixelmatch = require('pixelmatch'); const { PNG } = require('pngjs'); Then('页面应匹配基准快照', async function () { // 获取当前页面截图的PNG数据 const currentBuffer = await page.screenshot({ encoding: 'binary' }); const currentPng = PNG.sync.read(currentBuffer); // 读取基准快照文件 const baselinePath = path.join(__dirname, '__baselines__', 'page-baseline.png'); const baselineBuffer = await fs.readFile(baselinePath); const baselinePng = PNG.sync.read(baselineBuffer); // 计算像素差异 const diffPng = new PNG({ width: currentPng.width, height: currentPng.height }); const mismatchCount = pixelmatch( currentPng.data, baselinePng.data, diffPng.data, currentPng.width, currentPng.height, { threshold: 0.1 } ); // 断言差异在允许范围内 if (mismatchCount > 100) { await fs.writeFile(path.join(__dirname, '__diffs__', 'page-diff.png'), PNG.sync.write(diffPng)); throw new Error(`快照不匹配,差异像素数:${mismatchCount}`); } });
需提前安装依赖:npm install pixelmatch pngjs
注意事项
- 首次运行需手动生成并确认基准快照的正确性;
- 确保Cucumber环境中已正确初始化Playwright的page实例;
- 并行运行Cucumber场景时,避免多个场景同时读写快照文件导致冲突。
内容的提问来源于stack exchange,提问作者Nuttan Abhijan
相关产品推荐
相关产品推荐

