服务端阅读 05月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() 可以对同一元素连续验证多个条件。// 链式断言:验证按钮可见且可点击cy.get('#submit-btn') .should('be.visible') .and('not.be.disabled');// 链式文本断言cy.get('.menu-wrapper') .should('contain', '首页') .and('contain', '关于我们');.and() 是 .should() 的别名,仅用于提升可读性,两者功能完全一致。常见断言类型1. 存在性与可见性断言验证元素是否存在于 DOM 以及是否对用户可见,这是最基础也是最常用的断言类别。// 元素存在于 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:none、visibility:hidden、宽高为 0 等)。两者区别是常见面试考点。2. 值断言验证输入框的值、文本内容或元素数量。// 输入框的 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 样式。// 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. 状态断言验证表单元素的交互状态。// 禁用状态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 响应、计算结果)进行断言时,使用显式断言。// 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() 替代:// 推荐写法:隐式断言 + 自动重试cy.request('/api/status').its('body.status').should('eq', 'ready');深度相等与对象断言验证复杂对象或数组时,需要使用深度比较。// 深度相等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 不会立即失败,而是在超时时间内反复重试。// 以下断言会持续重试,直到元素可见或超时(默认 4 秒)cy.get('.notification').should('be.visible');这意味着你不需要在断言前手动添加 cy.wait():// 错误写法:硬编码等待cy.wait(3000);cy.get('.notification').should('be.visible');// 正确写法:依赖自动重试cy.get('.notification').should('be.visible');如果默认超时不够,可以在命令或全局配置中调整:// 单条命令设置超时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.text 与 contain 的精确/模糊匹配,以及避免在显式断言中处理需要等待的异步逻辑。