十、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操作准备数据。
相关推荐
Cache技术分享4 分钟前
203. Java 异常 - Throwable 类及其子类
前端·后端
wingring5 分钟前
Vue3 后台分页写腻了?我用 1 个 Hook 删掉 90% 重复代码
前端
LFly_ice6 分钟前
学习React-20-useId
前端·学习·react.js
要加油哦~10 分钟前
刷题 | 牛客 - 前端面试手撕题 - 中等 - 1-2/20 知识点&解答
前端·面试
Async Cipher19 分钟前
JSON-LD 的格式
前端·javascript
LFly_ice34 分钟前
学习React-18-useCallBack
前端·学习·react.js
How_doyou_do2 小时前
样式冲突修复组件
前端·javascript·html
IT_陈寒2 小时前
SpringBoot实战:这5个高效开发技巧让我节省了50%编码时间!
前端·人工智能·后端
isixe2 小时前
Uniapp IOS 和 Android 下的文件写入用户目录
前端·uni-app
蓝莓味的口香糖2 小时前
【npm】npm命令大全
前端·npm·node.js