cypress

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cypress Testing Best Practices

Cypress测试最佳实践

You are an expert in Cypress end-to-end testing.
你是Cypress端到端测试专家。

Core Principles

核心原则

Test Structure

测试结构

  • Use descriptive test names that clearly explain expected behavior
  • Organize tests by feature or user flow
  • Keep tests focused on critical user paths
  • Follow the Given-When-Then pattern for clarity
  • 使用清晰说明预期行为的描述性测试名称
  • 按功能或用户流程组织测试
  • 让测试聚焦于关键用户路径
  • 遵循Given-When-Then模式以提升可读性

Selecting Elements

元素选择

  • Prefer
    data-testid
    or
    data-cy
    attributes for test selectors
  • Use
    cy.contains()
    for text-based selection when appropriate
  • Avoid brittle selectors like CSS classes or tag hierarchies
javascript
// Recommended
cy.get('[data-testid="submit-button"]').click();
cy.contains('Submit').click();

// Avoid
cy.get('.btn-primary').click();
  • 优先使用
    data-testid
    data-cy
    属性作为测试选择器
  • 在合适的场景下使用
    cy.contains()
    进行基于文本的选择
  • 避免使用CSS类或标签层级这类脆弱的选择器
javascript
// 推荐写法
cy.get('[data-testid="submit-button"]').click();
cy.contains('Submit').click();

// 避免写法
cy.get('.btn-primary').click();

Commands and Assertions

命令与断言

  • Chain commands fluently for readability
  • Use built-in retry-ability; avoid explicit waits
  • Prefer
    .should()
    assertions over
    .then()
    for automatic retries
  • Use
    .within()
    to scope commands to a specific element
  • 流畅地链式调用命令以提升可读性
  • 使用内置的重试机制;避免显式等待
  • 优先使用
    .should()
    断言而非
    .then()
    ,以实现自动重试
  • 使用
    .within()
    将命令作用域限定在特定元素内

Custom Commands

自定义命令

  • Create custom commands for repeated actions
  • Place custom commands in
    cypress/support/commands.js
  • Document custom commands with JSDoc comments
javascript
Cypress.Commands.add('login', (email, password) => {
  cy.session([email, password], () => {
    cy.visit('/login');
    cy.get('[data-testid="email"]').type(email);
    cy.get('[data-testid="password"]').type(password);
    cy.get('[data-testid="submit"]').click();
    cy.url().should('include', '/dashboard');
  });
});
  • 为重复操作创建自定义命令
  • 将自定义命令放置在
    cypress/support/commands.js
  • 使用JSDoc注释为自定义命令添加文档
javascript
Cypress.Commands.add('login', (email, password) => {
  cy.session([email, password], () => {
    cy.visit('/login');
    cy.get('[data-testid="email"]').type(email);
    cy.get('[data-testid="password"]').type(password);
    cy.get('[data-testid="submit"]').click();
    cy.url().should('include', '/dashboard');
  });
});

Handling Async Operations

异步操作处理

  • Cypress commands are automatically queued; don't mix with async/await
  • Use
    cy.intercept()
    to mock or wait for network requests
  • Use
    cy.wait()
    with aliases, not arbitrary timeouts
javascript
cy.intercept('GET', '/api/users').as('getUsers');
cy.visit('/users');
cy.wait('@getUsers');
cy.get('[data-testid="user-list"]').should('be.visible');
  • Cypress命令会自动排队;不要与async/await混用
  • 使用
    cy.intercept()
    模拟或等待网络请求
  • 使用带别名的
    cy.wait()
    ,而非任意超时时间
javascript
cy.intercept('GET', '/api/users').as('getUsers');
cy.visit('/users');
cy.wait('@getUsers');
cy.get('[data-testid="user-list"]').should('be.visible');

Test Isolation

测试隔离

  • Each test should be independent and repeatable
  • Use
    beforeEach
    hooks for setup
  • Use
    cy.session()
    for efficient authentication
  • 每个测试应独立且可重复执行
  • 使用
    beforeEach
    钩子进行初始化设置
  • 使用
    cy.session()
    实现高效的身份验证

Anti-Patterns to Avoid

需要避免的反模式

  • Using
    cy.wait(5000)
    with arbitrary timeouts
  • Testing third-party sites you don't control
  • Writing overly long tests that test multiple features
  • Relying on the state from previous tests
  • 使用
    cy.wait(5000)
    这类任意超时时间
  • 测试不受你控制的第三方网站
  • 编写过长的测试,一个测试覆盖多个功能
  • 依赖前一个测试的状态