十、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操作准备数据。
相关推荐
神明不懂浪漫1 小时前
【第七章】Java中的常用类
java·开发语言·前端·经验分享·笔记
GuWenyue7 小时前
放弃云端API!一套React+WebGPU本地LLM方案,零数据上传、离线可用
前端·人工智能·前端框架
原则猫8 小时前
函数/变量提升
前端
独泪了无痕9 小时前
Vue3 Hooks使用实战解析
前端·vue.js
shawxlee10 小时前
vue3在public下封装config.js自定义配置动态数据,可在打包后直接修改,方便后端部署及后续维护
前端·javascript·经验分享·vue·团队开发·js·项目优化
用户0595401744611 小时前
把记忆存储的回归测试从手工换成 Playwright + GitHub Actions,线上缺陷降低 80%
前端·css
触底反弹11 小时前
🚀 从 DOM0 级到 React 合成事件:前端事件监听的 20 年演进史
前端·react.js·面试
kyriewen11 小时前
我给前端项目的接口请求套了6层保护——才发现以前一直在裸奔
前端·javascript·面试
颜酱11 小时前
04 | 召回前置准备:搭好召回所需的四个数据库
前端·人工智能·后端
郝亚军12 小时前
如何安装webstorm、Node.js和vue CLI
前端·javascript·vue.js