cypress

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cypress (E2E + Component Testing)

Cypress(端到端及组件测试)

Overview

概述

Cypress runs browser automation with first-class network control, time-travel debugging, and a strong local dev workflow. Use it for critical path E2E tests and for component tests when browser-level rendering matters.
Cypress 可实现浏览器自动化,具备一流的网络控制、时间旅行调试功能以及强大的本地开发工作流。可将其用于关键路径的端到端(E2E)测试,以及当浏览器级渲染效果至关重要时的组件测试。

Quick Start

快速开始

Install and open

安装并打开

bash
npm i -D cypress
npx cypress open
bash
npm i -D cypress
npx cypress open

Minimal spec

最小化测试用例

ts
// cypress/e2e/health.cy.ts
describe("health", () => {
  it("loads", () => {
    cy.visit("/");
    cy.contains("Hello").should("be.visible");
  });
});
ts
// cypress/e2e/health.cy.ts
describe("health", () => {
  it("loads", () => {
    cy.visit("/");
    cy.contains("Hello").should("be.visible");
  });
});

Core Patterns

核心模式

1) Stable selectors

1) 稳定选择器

Prefer
data-testid
(or
data-cy
) attributes for selectors. Avoid brittle CSS chains and text-only selectors for critical interactions.
html
<button data-testid="save-user">Save</button>
ts
cy.get('[data-testid="save-user"]').click();
优先使用
data-testid
(或
data-cy
)属性作为选择器。对于关键交互,避免使用脆弱的CSS链式选择器和仅基于文本的选择器。
html
<button data-testid="save-user">Save</button>
ts
cy.get('[data-testid="save-user"]').click();

2) Deterministic waiting (avoid fixed sleeps)

2) 确定性等待(避免固定延迟)

Wait on app-visible conditions or network aliases rather than
cy.wait(1000)
.
ts
cy.intercept("GET", "/api/users/*").as("getUser");
cy.visit("/users/1");
cy.wait("@getUser");
cy.get('[data-testid="user-email"]').should("not.be.empty");
等待应用可见状态或网络别名,而非使用
cy.wait(1000)
ts
cy.intercept("GET", "/api/users/*").as("getUser");
cy.visit("/users/1");
cy.wait("@getUser");
cy.get('[data-testid="user-email"]').should("not.be.empty");

3) Network control with
cy.intercept

3) 使用
cy.intercept
进行网络控制

Stub responses for deterministic tests and speed. Keep a small set of “real backend” smoke tests separate.
ts
cy.intercept("GET", "/api/users/1", {
  statusCode: 200,
  body: { id: "1", email: "a@example.com" },
}).as("getUser");
为实现确定性测试并提升速度,可桩化响应。将少量“真实后端”冒烟测试单独分开。
ts
cy.intercept("GET", "/api/users/1", {
  statusCode: 200,
  body: { id: "1", email: "a@example.com" },
}).as("getUser");

4) Authentication strategies

4) 认证策略

Prefer
cy.session
to cache login for speed and stability.
ts
// cypress/support/commands.ts
Cypress.Commands.add("login", () => {
  cy.session("user", () => {
    cy.request("POST", "/api/auth/login", {
      email: "test@example.com",
      password: "password",
    });
  });
});
ts
// e2e spec
beforeEach(() => {
  cy.login();
});
优先使用
cy.session
缓存登录状态,以提升速度和稳定性。
ts
// cypress/support/commands.ts
Cypress.Commands.add("login", () => {
  cy.session("user", () => {
    cy.request("POST", "/api/auth/login", {
      email: "test@example.com",
      password: "password",
    });
  });
});
ts
// e2e 测试用例
beforeEach(() => {
  cy.login();
});

Component Testing

组件测试

Run component tests to validate UI behavior in isolation while keeping browser rendering.
bash
npx cypress open --component
ts
// cypress/component/Button.cy.tsx
import React from "react";
import Button from "../../src/Button";

describe("<Button />", () => {
  it("clicks", () => {
    cy.mount(<Button onClick={cy.stub().as("onClick")}>Save</Button>);
    cy.contains("Save").click();
    cy.get("@onClick").should("have.been.calledOnce");
  });
});
运行组件测试以隔离验证UI行为,同时保留浏览器渲染环境。
bash
npx cypress open --component
ts
// cypress/component/Button.cy.tsx
import React from "react";
import Button from "../../src/Button";

describe("<Button />", () => {
  it("clicks", () => {
    cy.mount(<Button onClick={cy.stub().as("onClick")}>Save</Button>);
    cy.contains("Save").click();
    cy.get("@onClick").should("have.been.calledOnce");
  });
});

CI Patterns

CI 模式

Artifacts (videos/screenshots)

产物(视频/截图)

Store artifacts for failed runs and keep videos optional to reduce storage.
ts
// cypress.config.ts
import { defineConfig } from "cypress";

export default defineConfig({
  video: false,
  screenshotOnRunFailure: true,
  retries: { runMode: 2, openMode: 0 },
});
为失败的测试运行存储产物,可选择关闭视频以减少存储占用。
ts
// cypress.config.ts
import { defineConfig } from "cypress";

export default defineConfig({
  video: false,
  screenshotOnRunFailure: true,
  retries: { runMode: 2, openMode: 0 },
});

Parallelization (Cypress Cloud)

并行化(Cypress Cloud)

Parallelize long E2E suites via Cypress Cloud when runtime dominates feedback loops.
当运行时间成为反馈循环的主要瓶颈时,通过Cypress Cloud对较长的E2E测试套件进行并行化处理。

Anti-Patterns

反模式

  • Use
    cy.wait(1000)
    as a synchronization mechanism.
  • Select elements via deep CSS paths.
  • Mix heavy network stubbing with “real backend” assertions in the same spec.
  • Depend on test order; isolate state with
    cy.session
    and per-test setup.
  • cy.wait(1000)
    作为同步机制。
  • 通过深层CSS路径选择元素。
  • 在同一个测试用例中混合大量网络桩与“真实后端”断言。
  • 依赖测试执行顺序;使用
    cy.session
    和测试前置设置隔离状态。

Troubleshooting

故障排查

Symptom: flaky click or element not found

症状:点击不稳定或元素未找到

Actions:
  • Add a
    data-testid
    hook for the element.
  • Assert visibility before interaction (
    should("be.visible")
    ).
  • Wait on network alias for the data that renders the element.
解决措施:
  • 为元素添加
    data-testid
    钩子。
  • 交互前断言元素可见(
    should("be.visible")
    )。
  • 等待渲染该元素的数据对应的网络别名。

Symptom: tests fail only in CI

症状:仅在CI环境中测试失败

Actions:
  • Increase run-mode retries and record screenshots on failure.
  • Verify viewport and baseUrl config match CI environment.
  • Eliminate reliance on local-only seed data; create data via API calls.
解决措施:
  • 增加运行模式重试次数,并在失败时记录截图。
  • 验证视口和baseUrl配置与CI环境匹配。
  • 消除对本地独有种子数据的依赖;通过API调用创建测试数据。

Resources

资源