Skip to main content
Cypress应用

Cypress中的视觉测试

info
你将学到
  • 功能测试与视觉测试的区别
  • 如何使用视觉测试插件
  • 视觉测试的最佳实践

简介

Cypress提供了多种测试解决方案,包括:

虽然许多解决方案如Test ReplayCypress AccessibilityUI Coverage提供了应用程序的可视化展示,但拥有自动化方法来确保应用程序视觉效果符合预期至关重要。这就是视觉测试的作用。

视觉测试是一种专注于应用程序外观的测试类型。它确保应用程序在更改后对用户看起来保持一致。

it('completes todo', () => {
cy.visit('/') // opens TodoMVC running at "baseUrl"
cy.get('.new-todo').type('write tests{enter}')
cy.contains('.todo-list li', 'write tests').find('.toggle').check()

cy.contains('.todo-list li', 'write tests').should('have.class', 'completed')
})

技术上你可以编写功能测试,使用have.css断言来验证CSS属性,但这些测试可能很快变得繁琐且难以维护,尤其是当视觉样式依赖大量CSS时。

cy.get('.completed').should('have.css', 'text-decoration', 'line-through')
cy.get('.completed').should('have.css', 'color', 'rgb(217,217,217)')

你的视觉样式可能不仅依赖CSS,还可能涉及SVG、图像渲染或Canvas绘制。幸运的是,Cypress提供了一个稳定平台,可以集成插件来进行视觉测试。

这类插件通常会对整个应用程序或特定元素进行截图,然后与之前批准的基准图像进行比较。如果图像相同(在设定的像素容差范围内),则认为应用程序对用户看起来一致。如果有差异,则需要调查DOM布局、字体、颜色或其他视觉属性的变化。

例如,可以使用cypress-plugin-snapshots插件捕获以下视觉回归:

.todo-list li.completed label {
color: #d9d9d9;
/* removed the line-through */
}
it('completes todo', () => {
cy.visit('/')
cy.get('.new-todo').type('write tests{enter}')
cy.contains('.todo-list li', 'write tests').find('.toggle').check()

cy.contains('.todo-list li', 'write tests').should('have.class', 'completed')

// run 'npm install cypress-plugin-snapshots --save'
// capture the element screenshot and
// compare to the baseline image
cy.get('.todoapp').toMatchImageSnapshot({
imageConfig: {
threshold: 0.001,
},
})
})

这个开源插件在像素差异超过阈值时并排显示基准图像(预期结果)和当前图像(实际结果);注意基准图像中的标签文本有删除线,而新图像中没有。

基准图像与当前图像对比

像大多数图像比较工具一样,该插件在鼠标悬停时还会显示差异视图:

高亮显示的变化

工具

插件的视觉测试部分列出了多个开源插件,以下是一些基于Cypress开发的商业视觉测试解决方案。

Applitools

参见Applitools官方文档和我们的教程

与Applitools的第二次联合网络研讨会,重点介绍组件测试

Percy

参见Percy官方文档和我们的教程

info

Cypress 真实世界应用(RWA) 使用Cypress Percy插件提供的cy.percySnapshot()命令,在端到端测试中捕获用户旅程的视觉快照。

查看Real World App测试套件,了解Percy和Cypress的实际应用。

Happo

参见Happo官方文档和我们的网络研讨会博客

Chromatic

Chromatic利用你现有的Cypress设置——配置、模拟和测试——实现对应用程序UI的视觉测试。安装Chromatic插件后,Chromatic会在Cypress测试运行时捕获UI的存档。

参见Chromatic官方文档和他们的博客

Argos

Argos与你现有的Cypress设置——配置、模拟和测试——无缝集成,实现对应用程序UI的视觉测试。设置Argos后,它会在Cypress测试运行期间捕获并分析截图,以检测视觉变化。

查看Argos官方文档获取设置指南和最佳实践。

Wopee.io

Wopee.io与Cypress无缝集成,以增强测试覆盖率,加快维护速度,并确保更稳定的测试运行。Wopee.io旨在实现自主视觉测试,让你轻松将视觉验证集成到现有的Cypress测试中,增加额外的质量保证层。

参见Wopee.io官方文档、我们的网络研讨会及其博客网络研讨会

最佳实践

视觉测试有一些通用的最佳实践。

识别视觉测试的需求

验证样式属性的断言

cy.get('.completed').should('have.css', 'text-decoration', 'line-through')
.and('have.css', 'color', 'rgb(217,217,217)')
cy.get('.user-info').should('have.css', 'display', 'none')
...

如果你的端到端测试中充满了检查可见性、颜色和其他样式属性的断言,可能是时候开始使用视觉差异来验证页面外观了。

DOM状态

tip

最佳实践: 在确认页面已完成更改后拍摄快照。

例如,如果快照命令是cy.mySnapshotCommand

错误用法

// 应用程序需要时间添加新项目,
// 有时会在新项目出现之前拍摄快照
cy.get('.new-todo').type('write tests{enter}')
cy.mySnapshotCommand()

正确用法

// 使用功能断言确保
// 应用程序已重新渲染页面
cy.get('.new-todo').type('write tests{enter}')
cy.contains('.todo-list li', 'write tests')
// 很好,新项目已显示,
// 现在可以拍摄快照
cy.mySnapshotCommand()

时间戳

tip

最佳实践: 控制被测应用程序内部的时间戳。

下面我们使用cy.clock()将操作系统时间固定为2018年1月1日,以确保所有显示日期和时间的图像匹配。

const now = new Date(2018, 1, 1)

cy.clock(now)
// ... 测试
cy.mySnapshotCommand()

应用程序状态

tip

最佳实践: 使用cy.fixture()和网络模拟来设置应用程序状态。

下面我们使用cy.intercept()来存根网络调用,为每个XHR请求返回相同的响应数据。这确保了我们应用程序图像中显示的数据不会变化。

cy.intercept('/api/items', { fixture: 'items' }).as('getItems')
// ... 操作
cy.wait('@getItems')
cy.mySnapshotCommand()

视觉差异元素

tip

最佳实践: 使用视觉差异检查单个DOM元素,而不是整个页面。

针对特定DOM元素有助于避免组件"X"的视觉变化破坏其他无关组件的测试。

组件测试

tip

最佳实践: 使用组件测试来测试单个组件的功能,同时进行端到端和视觉测试。

另请参阅