如何在Cypress中判断操作完成?解决测试不稳定问题
Cypress E2E测试不稳定问题的解决方案
一、拦截API请求,确保操作完成
你的购物车操作依赖upsertOrder GraphQL mutation,固定等待时间不稳定的核心原因是网络请求耗时不可控。Cypress的cy.intercept可以精准捕获请求,等待响应完成后再执行后续步骤,这是最可靠的方案。
实现方式:
- 提前定义拦截规则,给目标请求起别名
- 触发操作后,用
cy.wait(别名)等待请求完成 - 后续操作无需固定等待
购物车测试代码修改:
context("user adds two items of this same type", () => { // 拦截upsertOrder请求,精准匹配operationName cy.intercept('POST', '/graphql', (req) => { if (req.body.operationName === 'upsertOrder') { req.alias = 'upsertOrder'; } }); cy.visit("/products"); // 第一次添加商品 cy.getByData("add-to-cart-button").first().click(); cy.wait('@upsertOrder'); // 等待请求响应完成 cy.getByData("cart-icon").first().should("contain.text", "1"); // 第二次添加商品 cy.getByData("add-to-cart-button").first().click(); cy.wait('@upsertOrder'); cy.visit("/cart"); cy.getByData("cart-item-quantity").should("contain.text", "2"); });
登录测试优化(解决重定向偶尔失败):
context("User logs in to make a purchase", () => { // 拦截登录接口 cy.intercept('POST', '/auth/login').as('login'); cy.visit("/auth/login"); cy.getByData("email").type(Cypress.env("login")); cy.getByData("password").type(Cypress.env("password")); cy.get("form").find("button").click(); cy.wait('@login'); // 确保登录请求完成后再检查重定向 cy.location().should((loc) => { expect(loc.pathname).to.eq("/auth/dashboard"); }); cy.get("section").should("contain.text", Cypress.env("login")); });
二、通过UI或前端状态判断操作完成
你提到的两种方式都可行,适合无法拦截请求的场景:
1. 等待按钮重新启用
按钮在请求期间处于禁用状态,请求完成后恢复可用。直接等待按钮的disabled属性移除:
cy.getByData("add-to-cart-button").first().click(); // 等待按钮不再禁用 cy.getByData("add-to-cart-button").first().should('not.be.disabled'); cy.getByData("cart-icon").first().should("contain.text", "1");
2. 等待clickedItemSlug变为空字符串
如果是React组件内部state,需要先将状态暴露到全局window对象(仅测试环境添加,避免影响生产):
// 在你的React组件中添加(测试环境) if (process.env.NODE_ENV === 'test') { window.clickedItemSlug = clickedItemSlug; }
然后在测试中等待状态变为空:
cy.getByData("add-to-cart-button").first().click(); // 等待状态清空 cy.window().its('clickedItemSlug').should('eq', ''); cy.getByData("cart-icon").first().should("contain.text", "1");
三、完整优化后测试代码
describe("Logged in user journey", () => { it("customer is able to do the full journey from login to purchase", () => { context("User logs in to make a purchase", () => { cy.intercept('POST', '/auth/login').as('login'); cy.visit("/auth/login"); cy.getByData("email").type(Cypress.env("login")); cy.getByData("password").type(Cypress.env("password")); cy.get("form").find("button").click(); cy.wait('@login'); cy.location().should((loc) => { expect(loc.pathname).to.eq("/auth/dashboard"); }); cy.get("section").should("contain.text", Cypress.env("login")); }); context("user adds two items of this same type", () => { cy.intercept('POST', '/graphql', (req) => { if (req.body.operationName === 'upsertOrder') { req.alias = 'upsertOrder'; } }); cy.visit("/products"); cy.getByData("add-to-cart-button").first().click(); cy.wait('@upsertOrder'); cy.getByData("cart-icon").first().should("contain.text", "1"); cy.getByData("add-to-cart-button").first().click(); cy.wait('@upsertOrder'); cy.visit("/cart"); cy.getByData("cart-item-quantity").should("contain.text", "2"); }); }); });
内容的提问来源于stack exchange,提问作者seven
相关产品推荐
相关产品推荐

