Skip to content

Cypress - 别名

Cypress - 使用别名(Aliases)构建健壮的测试

Section titled “Cypress - 使用别名(Aliases)构建健壮的测试”

Cypress 中的别名(Aliases)是使用 .as() 命令创建的强大功能,可以帮助你编写更清晰、更易于维护和更健壮的测试。它们允许你在测试后期引用和重用诸如 DOM 元素、网络请求、fixtures(测试数据)和其他值等主题(subjects)。

别名可用于在不同的测试步骤或钩子(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,即可重用 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() 的结果创建别名,以便稍后使用其属性(如 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);
});
});
});
});
  • 可读性: 通过为复杂主题赋予有意义的名称,使测试更易于理解。
  • 可重用性: 允许你定义一个主题一次,并在多个地方引用它。
  • 弹性(针对 DOM 元素): 当对 DOM 元素使用 cy.get('@aliasName') 时,Cypress 会重新查询 DOM,有助于避免对过时元素的引用。
  • 同步: 对于管理异步操作(如网络请求 cy.wait('@aliasName'))至关重要。

最佳实践:对于访问 Cypress 产出的主题,首选 cy.get('@aliasName')。需要时,才使用 this.aliasName(配合 function())主要用于存储在 Mocha 上下文中的简单数据。