@forsakringskassan/cypress-visual-regreation (英语)
将视觉回归测试添加到 齐压。 。 。 .
这是叉子 cypress-visual-regreement( cypress- visual- regression) (英语) 页:1. 最显著的变化是:
- 支持双头和无头.
- 支持 E2E 和组件测试,将截图存储在测试大小写旁边
__screenshots__文件夹. - 重试可操作性:尝试多次来将截图与基础图像相匹配.
- 被延迟的截图:在取取基础截图之前可选择的延迟.
- 强制软件渲染,抗异名检测:防止由不同硬件渲染出略为不同的像素而导致的片面测试.
开始
安装 :
$ npm install --save-dev @forsakringskassan/cypress-visual-regression
在您的配置中添加以下配置 (原始内容存档于2017-09-21). cypress.config.ts. 文件 :
截图文件夹的默认值为 cypress/screenshots。您的截图文件夹是失败的测试将转移到的地方.
{
"screenshotsFolder": "WHERE_YOU_WANT_FAILING_TEST_IMAGES_TO_END_UP/",
"trashAssetsBeforeRuns": true
}
cypress/support/commands.ts数字 :
import "@forsakringskassan/cypress-visual-regression/commands";
cypress.config.ts数字 :
import getToMatchScreenshotsPlugin from "@forsakringskassan/cypress-visual-regression/plugin";
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
config = getToMatchScreenshotsPlugin(on, config);
},
},
});
此插头使用 before:browser:launch 事件,因数 Cypress#5240 (英语) 如果您有另一个插件, 或者您用它自己在 cypress.config.ts 你需要一个工作.
见下文关于这类工作的例子一节.
关于如何使用 Cypress 的 TypeScript 的更多信息,请参考 此文档。 。 。 .
选项
failSilently 默认启用。 在您的配置中添加以下配置 cypress.json (英语) 查看错误的文件 :
{
"env": {
"failSilently": false
}
}
要使用
插件有两种模式, base 财务报告和审定财务报表 actual。 。 。 .
base 抓取新截图以设定为参考图像,或者如果差异超过阈值,更新现有图像. actual 抓取当前截图,并将其与参考图像相比较.
默认是 actual。 。 。 .
跑进去 base-mode 本地添加 type=base 作为环境变量
$ cypress run -- --env type=base
测试文件中的执行
添加 cy.toMatchScreenshot(); 当您想要测试视觉回归时,请在测试规格中输入。 也可以添加一个可选错误阈值:值可以从0.00(无差异)到1.00(每个像素都不同). 因此,如果输入0.51的出错阈值,只有大于51%的像素不同,测试才会失败.
阈值的默认值为0.01,不能低于此值.
更多实例:
| 阈值 | 失败的时间 |
|---|---|
| 页:1 | > 25% |
| 30岁 | > 30% |
| 5.5 国家 | > 50% |
| .75 (中文(简体) ) | > 75% |
样本 :
it("should display the login page correctly", () => {
cy.visit("/03.html");
cy.get("H1").contains("Login");
cy.toMatchScreenshot(0.1);
});
也可以瞄准一个HTML元素:
cy.get("#my-header").toMatchScreenshot();
您可以通过参数作为对象 cy.screenshot(),而不仅仅是一个出错阈值,以及:
it("should display the login page correctly", () => {
cy.visit("/03.html");
cy.toMatchScreenshot({
capture: "fullPage",
errorThreshold: 0.1,
});
});
等待组件装入和重试函数
有时有些东西不会装上截图. 为了解决这个问题,可以使用这个参数 baseDelay 它会 cy.wait(x) 在拍摄底部截图之前.
cy.toMatchScreenshot({ baseDelay: 500 });
当测试不运行为 base,它会在200ms后重取截图,每次延迟到匹配或默认3个尝试。 如果它找不到匹配和不再退休,测试就会失败.
您也可以配置它会做多少次重试 .
cy.toMatchScreenshot({ retries: 6 });
设置默认值
您可以通过在插件注册时添加来配置所有截图比较的阈值和重试等默认值 .
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
getToMatchScreenshotsPlugin(on, config, {
threshold: 0.05,
retries: 2,
});
},
},
component: {
setupNodeEvents(on, config) {
getToMatchScreenshotsPlugin(on, config, {
threshold: 0.05,
retries: 2,
});
},
},
});
这些默认在单个测试呼叫中可以被推翻.
保存了基础图像并测试失败
基本图像将存储在测试所在的同一个目录中, 在一个叫做子文件夹中 __screenshots__。例如
root
├─┬ cypress
│ └─┬ e2e
│ ├── test.cy.ts
│ └─┬ __screenshots__
│ └── test -- should match screenshot.png
└─┬ src
└─┬ component
├── component.vue
├── component.cy.ts
└─┬ __screenshots__
└── component -- should match screenshot.png
当测试失败时, 在您配置下将创建子目录 screenshotsFolder,里面会有底片图像和实际图像的复制件.
使用多个事件听众
Cypress不支持同一事件上的多位听众.
此插件使用 before:browser:launch 如果此插件与其它插件相撞, 您可以应用以下操作 :
cypress.config.ts数字 :
/**
* Workaround for https://github.com/cypress-io/cypress/issues/5240
*
* Cypress `on` cannot accept multiple listeners, since we have multiple plugins
* trying to hook into the same eents only one of them gets called. This
* workaround creates a wrapped `on` supporting multiple listeners.
*/
class EventForwarder {
private emitter: EventEmitter;
private task: Cypress.Tasks;
public on: Cypress.PluginEvents;
public constructor() {
this.emitter = new EventEmitter();
this.task = {};
this.on = (action, arg) => {
if (action === "task") {
Object.assign(this.task, arg);
} else {
this.emitter.on(action, arg as () => void);
}
};
}
public forward(on: Cypress.PluginEvents): void {
for (const event of this.emitter.eventNames()) {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any -- because we cannot extract the action names as a union of strings */
on(event as any, async (...args: unknown[]) => {
if (event === "before:browser:launch") {
const browser = args[0];
let launchOptions = args[1];
for (const listener of this.emitter.listeners(event)) {
launchOptions = await listener(browser, launchOptions);
}
} else {
for (const listener of this.emitter.listeners(event)) {
await listener(...args);
}
}
});
}
on("task", this.task);
}
}
export default defineConfig({
component: {
setupNodeEvents(cypressOn, config) {
const eventForwarder = new EventForwarder();
const on = eventForwarder.on;
try {
/* [..] */
getToMatchScreenshotsPlugin(on, config);
/* [..] */
} finally {
eventForwarder.forward(cypressOn);
}
},
},
});