Cypress - 别名
Cypress - 使用别名(Aliases)构建健壮的测试
Section titled “Cypress - 使用别名(Aliases)构建健壮的测试”Cypress 中的别名(Aliases)是使用 .as() 命令创建的强大功能,可以帮助你编写更清晰、更易于维护和更健壮的测试。它们允许你在测试后期引用和重用诸如 DOM 元素、网络请求、fixtures(测试数据)和其他值等主题(subjects)。
使用别名共享上下文
Section titled “使用别名共享上下文”别名可用于在不同的测试步骤或钩子(hooks)(例如 beforeEach)之间共享数据或主题。
1. 为原始值和对象创建别名 (Mocha 上下文)
Section titled “1. 为原始值和对象创建别名 (Mocha 上下文)”对于不属于 Cypress 命令队列管理的简单值或对象(例如原始字符串或数字),你可以为它们创建别名,并通过 Mocha 的共享 this 上下文访问它们。这要求你的测试和钩子使用函数声明(function() { ... }),而不是箭头函数,以确保 this 指向 Mocha 上下文。
describe('User Profile', function() { beforeEach(function() { cy.wrap({ name: 'Alice', role: 'admin' }).as('userData'); cy.wrap('main-content').as('contentId'); });
it('should display user name from aliased data', function() { // Accessing alias via Mocha's 'this' context // 通过 Mocha 的 'this' 上下文访问别名 expect(this.userData.name).to.equal('Alice'); cy.log(`Content ID is: ${this.contentId}`); });});注意:this 上的属性在每次测试后都会重置。
2. 为 Cypress 主题创建别名(DOM 元素、截取请求、普通请求)
Section titled “2. 为 Cypress 主题创建别名(DOM 元素、截取请求、普通请求)”当你为 Cypress 产出的主题(例如来自 cy.get() 的 DOM 元素、来自 cy.intercept() 的网络截取或来自 cy.request() 的请求结果)创建别名时,你应该使用 cy.get('@aliasName') 来访问它们。这是处理 Cypress 管理对象别名更常用和推荐的方式,因为它尊重 Cypress 的可重试性(retry-ability)。
为 DOM 元素创建别名
Section titled “为 DOM 元素创建别名”无需不必要地重新查询 DOM,即可重用 DOM 元素的选择。如果元素未立即找到或已从 DOM 中分离,Cypress 将重新运行 cy.get('@aliasName') 的查询,从而提高健壮性。
describe('DOM Element Aliasing', () => { beforeEach(() => { // Example: <table id='users-table'><tbody><tr><td>UserA</td><td>Active</td></tr></tbody></table> // 示例:<table id='users-table'><tbody><tr><td>UserA</td><td>Active</td></tr></tbody></table> cy.visit('/path-to-your-page-with-table.html'); // Replace with your page // 替换为你自己的页面路径 // Alias the collection of table data cells (td) in the first row // 为第一行中的表格数据单元格 (td) 集合创建别名 cy.get('#users-table tbody tr:first-child td').as('firstRowCells'); });
it('should interact with aliased cells', () => { cy.get('@firstRowCells').eq(0).should('contain.text', 'UserA'); cy.get('@firstRowCells').eq(1).click(); // Example: click the status cell // 示例:点击状态单元格 });});使用 cy.get('@aliasName') 可确保 Cypress 与元素的最新状态进行交互。
为网络截取(Network Intercepts)创建别名(以前称为 Routes)
Section titled “为网络截取(Network Intercepts)创建别名(以前称为 Routes)”cy.intercept() 用于管理网络请求和响应。为截取创建别名允许你等待它完成并对其属性进行断言。
describe('Network Intercept Aliasing', () => { it('should wait for a POST request and verify its body', () => { // Intercept POST requests to '/users' and alias it as 'createUser' // 拦截 POST 请求到 '/users' 并将其别名为 'createUser' cy.intercept('POST', '/api/users').as('createUser');
// Trigger the action that makes the POST request (e.g., submitting a form) // 触发发起 POST 请求的动作(例如,提交表单) cy.get('#user-form-name').type('Test User'); cy.get('#user-form-submit').click();
// Wait for the aliased 'createUser' intercept to complete // 等待别名为 'createUser' 的截取请求完成 cy.wait('@createUser').then((interception) => { // Assert on the request body // 断言请求体 expect(interception.request.body).to.have.property('name', 'Test User'); // Assert on the response status code // 断言响应状态码 expect(interception.response.statusCode).to.equal(201); });
cy.contains('User successfully added!').should('be.visible'); });});为 cy.request() 结果创建别名
Section titled “为 cy.request() 结果创建别名”你可以为 cy.request() 的结果创建别名,以便稍后使用其属性(如 status、body、headers)。
describe('cy.request() Aliasing', () => { it('should fetch comments and verify the response', () => { cy.request('https://jsonplaceholder.cypress.io/comments?postId=1').as('postComments');
// Other test steps can occur here // 这里可以执行其他测试步骤
cy.get('@postComments').should((response) => { expect(response.status).to.equal(200); expect(response.body).to.be.an('array').and.not.be.empty; response.body.forEach(comment => { expect(comment).to.have.property('postId', 1); }); }); });});使用别名的主要好处
Section titled “使用别名的主要好处”- 可读性: 通过为复杂主题赋予有意义的名称,使测试更易于理解。
- 可重用性: 允许你定义一个主题一次,并在多个地方引用它。
- 弹性(针对 DOM 元素): 当对 DOM 元素使用
cy.get('@aliasName')时,Cypress 会重新查询 DOM,有助于避免对过时元素的引用。 - 同步: 对于管理异步操作(如网络请求
cy.wait('@aliasName'))至关重要。
最佳实践:对于访问 Cypress 产出的主题,首选 cy.get('@aliasName')。需要时,才使用 this.aliasName(配合 function())主要用于存储在 Mocha 上下文中的简单数据。