Cypress 12+实现全测试流程仅登录一次的问题排查
如何在Cypress 12.9.0中实现全测试流程仅登录一次?
问题描述
我希望在整个测试运行流程中仅执行一次登录操作,为此配置了如下代码,但执行第一个测试用例时,页面处于未登录状态:
配置代码
// commands.js const commands = { login(data = {}) { let { username, password } = data; username = username || 'example@email.com'; password = password || 'testtest'; cy.session( username, () => { cy.visit('/'); cy.contains('Sign In').trigger('mouseover'); cy.contains('Sign in with NBA ID').click(); cy.get('[data-testid=email]').type('example@email.com'); cy.get('[data-testid=password]').type('testtest'); cy.get('[data-testid=submit]').click(); }, { cacheAcrossSpecs: true, }, ); }, };
// e2e.js // Session created beforeEach(() => { cy.login(); });
// user-profile.cy.js describe('User profile', () => { // Session is restored here beforeEach(() => { cy.visit('/'); }); it('Open user profile', () => { // Here the site is open but not logged in. cy.get('#nav-controls').trigger('mouseover'); cy.contains('My NBA ID', { timeout: 10000, }).click(); }); it('Check profile data', () => { cy.contains('First Name').next().should('have.text', 'Test'); cy.contains('Last Name').next().should('have.text', 'Test'); cy.contains('Birthdate').next().should('have.text', '10/1994'); cy.contains('Country').next().should('have.text', 'Bosnia and Herzegovina'); }); });
解决方案
1. 确保Cypress配置支持跨测试文件会话缓存
在cypress.config.js中开启experimentalSessionAndOrigin(Cypress 12+该特性已稳定,部分版本需显式配置):
module.exports = { e2e: { experimentalSessionAndOrigin: true, // 其他e2e配置项... }, };
2. 修正登录命令的硬编码问题
将登录逻辑中的硬编码账号密码改为使用变量,同时添加登录成功断言确保会话有效:
// commands.js const commands = { login(data = {}) { let { username, password } = data; username = username || 'example@email.com'; password = password || 'testtest'; cy.session( username, () => { cy.visit('/'); cy.contains('Sign In').trigger('mouseover'); cy.contains('Sign in with NBA ID').click(); cy.get('[data-testid=email]').type(username); cy.get('[data-testid=password]').type(password); cy.get('[data-testid=submit]').click(); // 断言登录成功,确保会话创建有效 cy.contains('My NBA ID').should('be.visible'); }, { cacheAcrossSpecs: true, }, ); }, }; // 注册自定义命令 Cypress.Commands.add('login', commands.login);
3. 确保测试前正确恢复会话
有两种可行的配置方式:
方式一:复用全局beforeEach
移除测试文件中的beforeEach,让全局beforeEach里的cy.login()负责会话恢复和页面加载:
// e2e.js beforeEach(() => { cy.login(); // 包含会话恢复/登录+页面访问逻辑 }); // user-profile.cy.js describe('User profile', () => { it('Open user profile', () => { cy.get('#nav-controls').trigger('mouseover'); cy.contains('My NBA ID', { timeout: 10000 }).click(); }); it('Check profile data', () => { cy.contains('First Name').next().should('have.text', 'Test'); cy.contains('Last Name').next().should('have.text', 'Test'); cy.contains('Birthdate').next().should('have.text', '10/1994'); cy.contains('Country').next().should('have.text', 'Bosnia and Herzegovina'); }); });
方式二:在测试文件中显式调用登录命令
在测试文件的beforeEach中先恢复会话,再访问页面:
// user-profile.cy.js describe('User profile', () => { beforeEach(() => { cy.login(); // 先恢复会话,仅第一次执行登录流程 cy.visit('/'); }); it('Open user profile', () => { cy.get('#nav-controls').trigger('mouseover'); cy.contains('My NBA ID', { timeout: 10000 }).click(); }); it('Check profile data', () => { cy.contains('First Name').next().should('have.text', 'Test'); cy.contains('Last Name').next().should('have.text', 'Test'); cy.contains('Birthdate').next().should('have.text', '10/1994'); cy.contains('Country').next().should('have.text', 'Bosnia and Herzegovina'); }); });
关键说明
cy.session的cacheAcrossSpecs: true参数确保会话在多个测试文件间共享,整个测试运行仅执行一次登录操作。- 每次调用
cy.login()时,Cypress会检查是否存在对应标识的会话:存在则直接恢复,不存在才执行登录回调。 - 添加登录成功断言可以提前验证会话有效性,避免后续测试因登录失败而报错。
内容的提问来源于stack exchange,提问作者Darko Riđić
相关产品推荐
相关产品推荐

