5月28日 00:27

Cypress 中的断言有哪些类型和用法?

Cypress 的断言是验证页面元素状态、属性或行为是否符合预期的核心机制。Cypress 断言基于 Chai 断言库,支持隐式断言和显式断言两种方式,并内置自动重试机制——断言失败时 Cypress 会自动重试直到超时,无需手动添加 cy.wait()

隐式断言与显式断言的区别

对比项隐式断言(Implicit)显式断言(Explicit)
语法.should() / .and()expect() / assert
重试自动重试直到通过或超时不自动重试,立即判定
适用场景DOM 元素验证API 响应、复杂逻辑判断
链式调用支持 .and() 链接多个断言需在 .then() 回调中使用

实际开发中,优先使用隐式断言,因为自动重试能大幅减少因异步渲染导致的测试不稳定问题。

隐式断言:should() 与 and()

.should() 是 Cypress 最常用的断言方法,配合链式调用 .and() 可以对同一元素连续验证多个条件。

javascript
// 链式断言:验证按钮可见且可点击 cy.get('#submit-btn') .should('be.visible') .and('not.be.disabled'); // 链式文本断言 cy.get('.menu-wrapper') .should('contain', '首页') .and('contain', '关于我们');

.and().should() 的别名,仅用于提升可读性,两者功能完全一致。

常见断言类型

1. 存在性与可见性断言

验证元素是否存在于 DOM 以及是否对用户可见,这是最基础也是最常用的断言类别。

javascript
// 元素存在于 DOM(不要求可见) cy.get('#app-container').should('exist'); // 元素不存在 cy.get('#loading-spinner').should('not.exist'); // 元素在视口内可见 cy.get('.success-message').should('be.visible'); // 元素隐藏 cy.get('.hidden-tip').should('not.be.visible');

exist 检查 DOM 节点存在性,be.visible 检查元素是否实际可见(非 display:nonevisibility:hidden、宽高为 0 等)。两者区别是常见面试考点。

2. 值断言

验证输入框的值、文本内容或元素数量。

javascript
// 输入框的 value 属性 cy.get('#username').should('have.value', 'admin'); // 元素的文本内容(精确匹配) cy.get('.title').should('have.text', '欢迎使用'); // 文本包含(模糊匹配) cy.get('.status').should('contain', '成功'); // 元素数量 cy.get('.list-item').should('have.length', 5);

have.text 是精确匹配,contain 是包含匹配——这是另一个高频考点。

3. 属性与 CSS 断言

验证 HTML 属性值和 CSS 样式。

javascript
// href 属性 cy.get('a.home-link').should('have.attr', 'href', '/home'); // class 属性 cy.get('#tab-1').should('have.class', 'active'); // CSS 属性 cy.get('.warning').should('have.css', 'color', 'rgb(255, 0, 0)'); // data-* 自定义属性 cy.get('[data-testid="modal"]').should('have.attr', 'data-testid', 'modal');

CSS 断言中颜色值需要用 rgb() 格式,不能直接用十六进制。

4. 状态断言

验证表单元素的交互状态。

javascript
// 禁用状态 cy.get('#submit-btn').should('be.disabled'); // 选中状态(复选框/单选框) cy.get('#agree-checkbox').should('be.checked'); // 聚焦状态 cy.get('#search-input').should('be.focused');

显式断言:expect 与 assert

当需要在 .then() 回调中对非 DOM 对象(如 API 响应、计算结果)进行断言时,使用显式断言。

javascript
// expect 风格(BDD) cy.request('/api/user/1').then((response) => { expect(response.status).to.eq(200); expect(response.body).to.have.property('name', '张三'); expect(response.body.roles).to.include('admin'); }); // assert 风格(TDD) cy.request('/api/stats').then((response) => { assert.equal(response.body.total, 100, '总数应为 100'); assert.isArray(response.body.items, 'items 应为数组'); });

显式断言不会自动重试,如果 API 响应需要等待,应使用 .its() 配合 .should() 替代:

javascript
// 推荐写法:隐式断言 + 自动重试 cy.request('/api/status').its('body.status').should('eq', 'ready');

深度相等与对象断言

验证复杂对象或数组时,需要使用深度比较。

javascript
// 深度相等 cy.request('/api/config').its('body').should('deep.eq', { theme: 'dark', lang: 'zh-CN' }); // 对象属性 cy.wrap({ name: 'test', age: 25 }).should('have.property', 'age', 25); // 数组长度与内容 cy.get('.tag').should('have.length', 3) .and('contain.text', '前端');

断言自动重试机制

Cypress 隐式断言的自动重试是区别于其他测试框架的核心特性。当断言条件不满足时,Cypress 不会立即失败,而是在超时时间内反复重试。

javascript
// 以下断言会持续重试,直到元素可见或超时(默认 4 秒) cy.get('.notification').should('be.visible');

这意味着你不需要在断言前手动添加 cy.wait()

javascript
// 错误写法:硬编码等待 cy.wait(3000); cy.get('.notification').should('be.visible'); // 正确写法:依赖自动重试 cy.get('.notification').should('be.visible');

如果默认超时不够,可以在命令或全局配置中调整:

javascript
// 单条命令设置超时 cy.get('.slow-element', { timeout: 10000 }).should('be.visible'); // cypress.config.js 全局配置 module.exports = { defaultCommandTimeout: 10000 };

常见断言速查表

断言用法说明
exist.should('exist')DOM 中存在
be.visible.should('be.visible')元素可见
have.value.should('have.value', 'x')输入框值匹配
have.text.should('have.text', 'x')文本精确匹配
contain.should('contain', 'x')文本包含
have.length.should('have.length', n)元素数量
have.attr.should('have.attr', 'href', '/x')属性匹配
have.class.should('have.class', 'active')CSS 类匹配
be.disabled.should('be.disabled')元素禁用
be.checked.should('be.checked')复选框选中
deep.eq.should('deep.eq', obj)深度相等

掌握 Cypress 断言的关键在于三点:优先用隐式断言获取自动重试能力,区分 have.textcontain 的精确/模糊匹配,以及避免在显式断言中处理需要等待的异步逻辑。

标签:Cypress