第十二篇:《Cypress实战:从安装到第一个端到端测试》

如果说 Playwright 是"全能型选手",那么 Cypress 就是"专为现代前端应用而生"的测试工具。它直接在浏览器中运行,提供实时重载、时间旅行调试、自动等待等特性,深受 React/Vue 开发者喜爱。本文将带你快速上手 Cypress,编写第一个端到端测试,并与 Selenium/Playwright 进行对比。

一、Cypress 是什么?

Cypress 是一个基于 JavaScript 的端到端测试框架,它在浏览器内部运行测试代码,与应用程序共享同一个执行上下文。这意味着它可以直接访问 DOM、网络请求、存储,并且能够自动等待元素和断言。

核心特点:

实时重载:修改测试代码后自动重新执行。

时间旅行:鼠标悬停在每一步,可查看当时的 DOM 快照。

自动等待:无需显式等待或 sleep,自动重试断言直到超时。

网络控制:轻松 stub 和 mock 网络请求。

截图和视频:自动记录失败用例的截图和视频。

调试友好:类似 Chrome DevTools 的调试体验。

二、Cypress 与 Selenium、Playwright 对比

结论:Cypress 非常适合 前端开发者编写组件和端到端测试,尤其是单页应用(SPA)。如果你的应用需要多标签页、跨域 iframe 或 Safari 测试,则需考虑 Playwright。

三、安装与第一个测试

3.1 安装 Cypress

bash 复制代码
mkdir cypress-demo && cd cypress-demo
npm init -y
npm install cypress --save-dev

3.2 打开 Cypress 界面

bash 复制代码
npx cypress open

首次运行会创建示例测试和配置结构。

3.3 编写第一个测试

创建文件 cypress/e2e/first_test.cy.js:

javascript 复制代码
describe('百度搜索测试', () => {
  it('搜索 "Cypress" 应该返回结果', () => {
    cy.visit('https://www.baidu.com');
    // 输入关键词
    cy.get('#kw').type('Cypress 教程');
    // 点击搜索按钮
    cy.get('#su').click();
    // 断言搜索结果包含关键词
    cy.contains('Cypress 教程').should('be.visible');
  });
});

运行:

通过界面:npx cypress open,然后点击测试文件。

命令行(无头模式):npx cypress run

四、Cypress 核心语法

4.1 命令与断言(Chai + Sinon)

Cypress 使用类似 jQuery 的链式 API,所有命令都是异步但不需要 await,内部自动处理。

javascript 复制代码
// 获取元素(自动等待元素出现)
cy.get('.login-form').find('input[name="username"]');
cy.contains('登录');  // 通过文本查找

// 操作
cy.get('#username').type('admin');
cy.get('#password').type('123456{enter}');  // 按回车
cy.get('.btn').click();

// 断言(使用 should,支持链式)
cy.get('.welcome').should('contain', '欢迎回来');
cy.get('.error').should('be.visible');
cy.get('h1').should('have.text', 'Dashboard');

// 多个断言
cy.get('.result').should(($el) => {
  expect($el).to.have.length(3);
  expect($el.first()).to.contain('Cypress');
});

4.2 自动等待与超时

Cypress 会持续等待(默认 4 秒)直到断言成功,无需手动 sleep。

javascript 复制代码
// 即使结果稍后出现,也会等待
cy.get('.loading-spinner').should('not.exist');

可全局或局部修改超时时间:

javascript 复制代码
// 在配置文件 cypress.config.js 中
defaultCommandTimeout: 10000

// 或在测试中
cy.get('.slow-element', { timeout: 15000 }).should('be.visible');

4.3 网络请求 Mock(Stub)

Cypress 可以拦截并修改网络请求,非常适合独立测试前端逻辑。

javascript 复制代码
// 拦截 GET 请求并返回 mock 数据
cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers');

// 拦截 POST 请求并模拟响应
cy.intercept('POST', '/api/login', {
  statusCode: 200,
  body: { token: 'fake-token' }
}).as('login');

// 触发请求
cy.get('#login').click();
cy.wait('@login').its('response.statusCode').should('eq', 200);

4.4 处理 iframe(有限支持)

Cypress 默认不支持跨域 iframe,但可以通过加载 cypress-iframe 插件解决。

bash 复制代码
npm install -D cypress-iframe

在 cypress/support/e2e.js 中引入:

javascript 复制代码
import 'cypress-iframe';

使用:

javascript 复制代码
cy.frameLoaded('#myIframe');
cy.iframe().find('#username').type('admin');

4.5 自定义命令

在 cypress/support/commands.js 中添加可复用命令:

javascript 复制代码
Cypress.Commands.add('login', (username, password) => {
  cy.visit('/login');
  cy.get('#username').type(username);
  cy.get('#password').type(password);
  cy.get('button[type="submit"]').click();
  cy.url().should('include', '/dashboard');
});

测试中使用:

javascript 复制代码
cy.login('admin', '123456');

五、测试组织与钩子

javascript 复制代码
describe('用户管理模块', () => {
  before(() => {
    // 整个 suite 只执行一次
    cy.visit('/');
  });

  beforeEach(() => {
    // 每个测试前执行
    cy.login('admin', '123');
  });

  it('创建用户', () => {
    cy.get('#createUser').click();
    // ...
  });

  it('删除用户', () => {
    // ...
  });

  afterEach(() => {
    // 每个测试后清理
  });

  after(() => {
    // 最后执行
  });
});

六、与 CI 集成(GitHub Actions 示例)

.github/workflows/cypress.yml:

yaml 复制代码
name: Cypress Tests
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Cypress run
        uses: cypress-io/github-action@v5
        with:
          browser: chrome
          headless: true

七、常见坑与解决方案

元素不可见:Cypress 要求元素可见才能交互。确保没有覆盖层或动画。

跨域限制:Cypress 默认不允许访问不同域的页面。解决办法:

将测试和被测应用放在同一域。

使用 cy.origin() 命令(Cypress 10+ 支持跨域测试)。

异步数据不更新:使用 cy.wait() 等待特定网络请求完成,而非固定时间。

无法多标签页:Cypress 不支持多标签页测试。如有此需求,考虑 Playwright。

八、总结与选型建议

Cypress 的优势

调试体验极佳,时间旅行功能秒杀其他工具。

自动等待机制非常智能,测试代码简洁。

与前端开发工作流无缝集成。

局限性:

仅支持 JavaScript/TypeScript。

不原生支持多标签页、Safari 浏览器。

iframe 支持有限。

选型建议:

如果你是前端开发,测试自己的 React/Vue 应用 → Cypress 首选。

如果你需要跨浏览器(特别是 Safari)或多标签页测试 → Playwright。

如果你有大量遗留 Selenium 代码或需要 IE 测试 → Selenium。

相关推荐
IvorySQL1 小时前
PostgreSQL 技术日报 (6月9日)|PL/SQL 迁移自动化,前沿峰会即将启幕
sql·postgresql·自动化
Black蜡笔小新1 小时前
自动化AI算法训练服务器DLTM训推一体工作站赋能多行业智能化升级
人工智能·算法·自动化
xiami_world3 小时前
2026年UI/UX设计工具私有化部署方案深度解析
人工智能·ui·ai·产品经理·ux
北京耐用通信3 小时前
耐达讯自动化工业网关:极简组态实现 Modbus 转 PROFINET 稳定通讯
人工智能·物联网·网络协议·自动化·信息与通信
@Ma4 小时前
企业微信外部群的消息自动化:从协议层到工程实践
运维·自动化·企业微信
川石课堂软件测试4 小时前
UI自动化测试|XPath元素定位实践
功能测试·测试工具·jmeter·microsoft·ui·postman·harmonyos
Mr -老鬼5 小时前
2026移动端自动化平台横向对比指南:15+主流平台深度评测,开发者选型必备
运维·自动化·easyclick·移动测试
会Tk矩阵群控的小木5 小时前
小红书矩阵软件:基于Python+ADB的多设备批量管理自动化脚本实战
运维·python·adb·矩阵·自动化·新媒体运营·个人开发
ai_coder_ai5 小时前
使用ocr实现自动化脚本
运维·自动化·ocr
极客先躯5 小时前
高级java每日一道面试题-2026年02月04日-实战篇[Docker]-如何在容器之间共享数据?
java·运维·网络·docker·容器·自动化·高级面试题