cypress
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCypress 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 or
data-testidattributes for test selectorsdata-cy - Use for text-based selection when appropriate
cy.contains() - 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 assertions over
.should()for automatic retries.then() - Use to scope commands to a specific element
.within()
- 流畅地链式调用命令以提升可读性
- 使用内置的重试机制;避免显式等待
- 优先使用断言而非
.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 to mock or wait for network requests
cy.intercept() - Use with aliases, not arbitrary timeouts
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');- 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 hooks for setup
beforeEach - Use for efficient authentication
cy.session()
- 每个测试应独立且可重复执行
- 使用钩子进行初始化设置
beforeEach - 使用实现高效的身份验证
cy.session()
Anti-Patterns to Avoid
需要避免的反模式
- Using with arbitrary timeouts
cy.wait(5000) - 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) - 测试不受你控制的第三方网站
- 编写过长的测试,一个测试覆盖多个功能
- 依赖前一个测试的状态