我创建了一个 Cypress 脚本,用于在 SAP Hybris 内部测试促销项目。在考虑单个测试用例时,它通常可以正常工作。但是当我添加多个测试用例时...
我创建了一个 Cypress 脚本,用于在 SAP Hybris 内部测试促销项目。在考虑单个测试用例时,它通常可以正常工作。但是,当我添加多个测试用例(每个测试促销项目添加 1 个)时,它会成功完成测试用例 1,并在测试用例 2 启动时立即收到阻止程序。原因是,一旦测试用例 1 完成,Cypress 就会显示空白页,因此它无法找到测试用例 2 所请求的元素。
Cypress.on('uncaught:exception', (err, runnable) => {
return false;
});
describe('Promotions test', () => {
const loginPageUrl = 'https://backoffice.stg.iqos.com/backoffice/login.zul';
const username = 'USERNAME HERE';
const password = 'PASSWORD HERE';
const promotionEditorRole = 'Promotion Editor';
const proceedButtonText = 'PROCEED';
const marketingMenuText = 'Marketing';
const promotionRulesText = 'Promotion Rules';
before(() => {
// Login process that runs once before all test cases
cy.visit(loginPageUrl, { failOnStatusCode: false }).wait(1000);
cy.get('input[placeholder="Enter user name"]:visible')
.type(username, { force: true }).wait(300);
cy.get('input[placeholder="Enter password"]:visible')
.type(password, { force: true });
cy.get('.login_btn').click({ force: true }).wait(30000);
// Select Promotion Editor Role
cy.get('.z-listcell-content').contains(promotionEditorRole)
.should('exist').click({ force: true }).wait(2000);
cy.get('.yw-selector-btn').contains(proceedButtonText)
.should('exist').click({ force: true }).wait(15000);
});
beforeEach(() => {
// Navigation process before each test case
cy.get('.yw-navigationNode-level1').contains(marketingMenuText)
.should('exist').click({ force: true }).wait(3000);
cy.get('span.z-label').contains(promotionRulesText)
.should('exist').click({ force: true }).wait(5000);
});
it('Check Promotion 1', () => {
const promotionCode = 'CR_PMI_MGM_Godfather_Discount_01_More';
const promotionName = 'MGM GODFATHER Reward';
const websiteEnv = 'Costa Rica_Promotion_Group';
const promotionVersion = '4';
searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion);;
cy.get('.z-tab-content')
.contains('Rule Properties')
.scrollIntoView()
.click({ force: true });
cy.get('.ye-input-text.ye-com_hybris_cockpitng_editor_defaulttext.z-textbox.z-textbox-readonly')
.should('have.value', 'CR_PMI_MGM_Godfather_Discount_01_More');
cy.wait(10000);
});
it('Check Promotion 2', () => {
const promotionCode = 'UK_15_Off_First_Order';
const promotionName = '15% off first ZYN Order';
const websiteEnv = 'PUBLISHED';
const promotionVersion = '0';
searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion);;
cy.get('.z-tab-content')
.contains('Rule Properties')
.scrollIntoView()
.click({ force: true });
cy.get('.ye-input-text.ye-com_hybris_cockpitng_editor_defaulttext.z-textbox.z-textbox-readonly')
.should('have.value', 'UK_15_Off_First_Order');
});
it('Check Promotion 3', () => {
const promotionCode = 'UK_ZYN_Free_Sample';
const promotionName = 'ZYN Free Sample';
const websiteEnv = 'PUBLISHED';
const promotionVersion = '0';
searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion);;
cy.get('.z-tab-content')
.contains('Rule Properties')
.scrollIntoView()
.click({ force: true });
cy.get('.ye-input-text.ye-com_hybris_cockpitng_editor_defaulttext.z-textbox.z-textbox-readonly')
.should('have.value', 'UK_ZYN_Free_Sample');
});
});
function searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion) {
cy.get('.z-bandbox-input')
.eq(6)
.should('exist')
.clear()
.type(promotionCode, { force: true })
.wait(300);
cy.get('.yw-textsearch-searchbutton.z-button')
.eq(1)
.click({ force: true })
.wait(10000);
cy.log("Promotion Code: " + promotionCode);
cy.log("Promotion Name: " + promotionName);
cy.log("Website Environment: " + websiteEnv);
cy.log("Promotion Version: " + promotionVersion);
const selector = "tr.yw-coll-browser-hyperlink:has(.yw-listview-cell-label.z-label:contains(\"" + promotionCode + "\")):has(.yw-listview-cell-label.z-label:contains(\"" + promotionName + "\")):has(.yw-listview-cell-label.z-label:contains(\"" + websiteEnv + "\")):has(.yw-listview-cell-label.z-label:contains(\"" + promotionVersion + "\"))";
function checkPage() {
cy.get('body').then($body => {
if ($body.find(selector).length > 0) {
cy.get(selector).within(() => {
cy.get(".yw-listview-cell-label.z-label:contains(\"" + promotionVersion + "\")")
.click({ force: true })
.wait(10000);
});
} else {
cy.get('button.z-paging-button.z-paging-next[title="Next Page"]').eq(2).then($button => {
cy.log('Button found:', $button.length > 0 ? 'Yes' : 'No');
cy.log('Button visibility:', $button.is(':visible') ? 'Visible' : 'Not Visible');
cy.log('Button disabled attribute:', $button.attr('disabled') ? 'Disabled' : 'Enabled');
if ($button.is(':visible') && !$button.attr('disabled')) {
cy.log('Clicking the next page button');
cy.wrap($button).click({ force: true }).wait(5000);
checkPage();
} else {
cy.log('Promotion not found or next page button is not clickable');
}
});
}
});
}
checkPage();
}
我发现实际上完成所有测试用例的解决方案是这样的:
beforeEach(() => {
// Login process that runs once before all test cases
cy.visit(loginPageUrl, { failOnStatusCode: false }).wait(1000);
cy.get('input[placeholder="Enter user name"]:visible')
.type(username, { force: true }).wait(300);
cy.get('input[placeholder="Enter password"]:visible')
.type(password, { force: true });
cy.get('.login_btn').click({ force: true }).wait(30000);
// Select Promotion Editor Role
cy.get('.z-listcell-content').contains(promotionEditorRole)
.should('exist').click({ force: true }).wait(2000);
cy.get('.yw-selector-btn').contains(proceedButtonText)
.should('exist').click({ force: true }).wait(15000);
// Navigation process before each test case
cy.get('.yw-navigationNode-level1').contains(marketingMenuText)
.should('exist').click({ force: true }).wait(3000);
cy.get('span.z-label').contains(promotionRulesText)
.should('exist').click({ force: true }).wait(5000);
});
基本上,我在测试的最开始添加了一个 beforeEach() 命令。这样,对于每个测试用例,Cypress 都会重复所有步骤,包括登录、选择角色选项等。
因此,从功能角度来看,该解决方案是有效的,但我相信,如果它不会对每个测试用例从头开始重复所有步骤,则测试会更加高效(因为为每个测试用例再次登录是没有意义的)。
您观察到的页面开始空白的行为称为 测试隔离 ,它通常被认为是最佳实践,因为早期测试的状态可能会在第二次测试中产生意外的假阳性结果。
一些可供参考的文档:
这 beforeEach()
是遵守测试隔离原则的最简单方法,并且可以 通过 将其代码包装在 cy.session() 命令中来改进。
此命令接受参数, cy.session(id, setup)
其中 setup
是一个函数,它将包含您的 beforeEach()
.
该 setup
函数 仅在第一次测试时调用 ,最后将保存在浏览器 cookie、localstorage 和 sessionstorage 中找到的任何值。
浏览器清除后 会恢复保存的值 。理论上,您的网页会看到这些值,并被“欺骗”,认为该页面已经执行了登录。
这是使用它的模式:
beforeEach(() => {
cy.session('login', () => {
// code to perform to perform login
// which will only be run during the first test
})
})