十、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操作准备数据。
相关推荐
爱勇宝10 小时前
初创公司的“自己人”,到底能当多久?
前端·后端·程序员
晴天1610 小时前
前端模块化规范全景解析:CommonJS、AMD、ESM、UMD
前端
三十而立洋11 小时前
深入理解 npm:从核心机制到常用命令全解析
前端·前端工程化
Canace11 小时前
最新版 Codex 工作流的问题
前端·人工智能·agent
变与不变80611 小时前
引用类型、内存原理与对象
开发语言·前端·javascript
jearry11 小时前
给 C++ 老程序补现代 UI:WebView2 多入口资源加载与虚拟主机名实践
前端
打呵欠的猫11 小时前
让 AI 帮你写 Git Commit Message:从"fix bug"到语义化提交只需一个 Hook
前端·ai编程
labixiong11 小时前
CSS 锚点定位实测:零 JS 实现气泡跟随,自动翻转很香但暗藏 3 个致命坑
前端·css
qibmz11 小时前
用 DeepSeek 给 GitHub 仓库加 PR 自动 Review
前端
计算机魔术师11 小时前
幻觉率从 4.2% 降到 2% 又退回,GPT-6 Astra 到底在藏什么
前端