十、Cypress最佳实践——写出高效又好维护的测试

Cypress最佳实践------写出高效又好维护的测试

用Cypress写测试不难,但写出稳定、简洁、易维护的测试却需要技巧。这一章咱们聊聊实战中的最佳实践,从项目结构到代码细节,帮你避开"写时一时爽,维护火葬场"的坑。

一、基础配置:让测试跑起来更顺畅

1. 配置baseUrl减少重复代码

cypress.json里设置baseUrl,测试中访问页面时就不用写完整URL了,既简洁又方便切换环境:

json 复制代码
// cypress.json
{
  "baseUrl": "http://localhost:7077"
}
javascript 复制代码
// 直接写相对路径,自动拼接baseUrl
cy.visit('/login') // 等同于访问http://localhost:7077/login

2. 禁用不必要的等待,依赖自动重试

传统测试工具里,我们习惯用sleep(1000)等待页面加载,但Cypress的命令会自动等待元素可操作(默认等4秒),完全不用手动加等待。

javascript 复制代码
// 错误示例:多余的等待
cy.visit('/dashboard')
cy.wait(2000) // 没必要!cy.get会自动等待
cy.get('[data-cy=stats]').should('contain', '销售额')

// 正确做法:依赖Cypress的自动重试
cy.visit('/dashboard')
cy.get('[data-cy=stats]').should('contain', '销售额') // 会自动等元素加载

二、测试用例设计:聚焦核心场景

1. 避免"大而全"的用例,拆分独立场景

一个用例只测一个功能点,比如"登录成功""登录失败(密码错误)""登录失败(账号为空)"应该拆成3个用例,而不是写在一个it里。

好处:失败时能精准定位问题,且可以单独重跑某个场景。

2. 动态生成用例,应对多组数据

如果多个场景的步骤相同,只是输入/输出不同(比如测试登录时的各种错误提示),用数据驱动动态生成用例,不用复制粘贴代码:

javascript 复制代码
// 测试数据:不同输入对应的预期结果
const testData = [
  { username: '', password: '', expectError: '请输入账号' },
  { username: 'jane', password: 'wrong', expectError: '密码错误' },
  { username: 'invalid', password: '123', expectError: '账号不存在' }
]

describe('登录错误场景', () => {
  // 循环数据生成用例
  testData.forEach((data) => {
    it(`输入${data.username}/${data.password}时,提示${data.expectError}`, () => {
      cy.visit('/login')
      cy.get('input[name=username]').type(data.username)
      cy.get('input[name=password]').type(data.password)
      cy.get('[data-cy=login-btn]').click()
      cy.get('[data-cy=error-msg]').should('contain', data.expectError)
    })
  })
})

三、代码复用:减少重复劳动

1. 用Custom Commands封装重复操作

把常用步骤(比如登录、添加商品到购物车)封装成自定义命令,在cypress/support/commands.js里定义:

javascript 复制代码
// 定义登录命令
Cypress.Commands.add('login', (username, password) => {
  cy.visit('/login')
  cy.get('input[name=username]').type(username)
  cy.get('input[name=password]').type(password)
  cy.get('[data-cy=login-btn]').click()
})

之后在所有测试用例里直接调用:

javascript 复制代码
// 测试中直接用cy.login()
it('登录后访问个人中心', () => {
  cy.login('jane.lane', 'password123') // 复用登录逻辑
  cy.visit('/profile')
  cy.get('[data-cy=username]').should('contain', 'jane.lane')
})

2. 用fixture管理测试数据

测试中用到的静态数据(比如用户信息、接口模拟数据)别硬编码在代码里,放在cypress/fixtures文件夹下,用cy.fixture()读取:

json 复制代码
// cypress/fixtures/user.json
{
  "username": "jane.lane",
  "password": "password123",
  "nickname": "简"
}
javascript 复制代码
// 测试中读取fixture数据
it('使用fixture数据登录', () => {
  cy.fixture('user.json').then((user) => {
    cy.login(user.username, user.password) // 用fixture里的数据
  })
})

四、断言与调试:让失败原因一目了然

1. 用清晰的断言描述预期结果

断言不仅要判断"对不对",还要说明"预期是什么",方便其他人看懂测试意图:

javascript 复制代码
// 不好的断言:只知道错了,不知道预期是什么
cy.get('[data-cy=user-count]').should('eq', 5)

// 好的断言:清晰说明预期
cy.get('[data-cy=user-count]')
  .should('contain', '5')
  .and('be.visible') // 同时验证可见性

2. 测试失败时自动截图/录屏

Cypress默认会在测试失败时自动截图,无头模式(cypress run)下还会录屏,这些文件保存在cypress/screenshotscypress/videos里,配合日志能快速定位问题。

如果想手动截图,用cy.screenshot()

javascript 复制代码
// 在关键步骤手动截图
cy.get('[data-cy=order-summary]').screenshot('订单摘要')

五、避坑指南:这些做法要不得

  • 别测UI样式细节:比如颜色、字体大小(容易随设计变更,增加维护成本),专注测功能逻辑。
  • 别依赖第三方服务 :测试中用到的接口尽量用cy.intercept() mock掉,避免因第三方服务不稳定导致测试失败。
  • 别在测试中操作数据库:直接改数据库会污染测试环境,应该通过接口或UI操作准备数据。
相关推荐
GIS之路4 分钟前
GDAL 实现矢量裁剪
前端·python·信息可视化
是一个Bug7 分钟前
后端开发者视角的前端开发面试题清单(50道)
前端
Amumu121389 分钟前
React面向组件编程
开发语言·前端·javascript
持续升级打怪中31 分钟前
Vue3 中虚拟滚动与分页加载的实现原理与实践
前端·性能优化
GIS之路34 分钟前
GDAL 实现矢量合并
前端
hxjhnct37 分钟前
React useContext的缺陷
前端·react.js·前端框架
前端 贾公子1 小时前
从入门到实践:前端 Monorepo 工程化实战(4)
前端
菩提小狗1 小时前
Sqlmap双击运行脚本,双击直接打开。
前端·笔记·安全·web安全
前端工作日常1 小时前
我学习到的AG-UI的概念
前端
韩师傅1 小时前
前端开发消亡史:AI也无法掩盖没有设计创造力的真相
前端·人工智能·后端