Cypress flaky测试:仅特定租户加购2件商品后购物车数量偶现为1
问题背景
我正在使用Cypress测试线上商城的前端,目前遇到一个flaky测试问题:站点共有5个对应不同国家的租户,该测试仅在当前德语区租户偶发失败,其余租户均正常运行,暂时无法定位问题根源。
测试预期执行流程
- 访问首页
- 进入商品详情页
- 选择一个有库存的尺码
- 将商品加入购物车
- 重复进入商品页、选尺码、加购的步骤,添加第二个商品
- 校验购物车商品总数为2
问题表现
- 购物车商品总数偶现仅为1,无法稳定复现失败场景
猜测原因
- 访问第二个商品详情页时,购物车数据丢失
- 与未接受Cookie策略有关(测试要求不能主动接受Cookie)
备注
- 除语言差异外,所有租户的功能逻辑完全一致
测试用例代码
describe('[anon] add to cart ' + baseUrl, () => { if (!features.shoppingCartFeature) return; const homepage = new Homepage(); const productpage = new ProductPage(); const shoppingCartPage = new ShoppingCartPage(); const testProduct = Cypress.env('testProduct'); const testProduct2 = Cypress.env('testProduct2'); beforeEach(() => { homepage.visit(); }); it('add to cart as anomymous user for 2 products', () => { productpage.visitProduct(testProduct.productID); productpage.add2Cart(true); productpage.visitProduct(testProduct2.productID); productpage.add2Cart(true); shoppingCartPage.checkCartAmount(2); }); });
ProductPage类实现代码
class ProductPage extends BasePage { visitProduct(id) { // intercept this api call, bc after the response the size selection is available cy.intercept(personalizeUrl).as('sizes'); cy.visit(baseUrl + `/p/` + id); cy.wait('@sizes'); return this; } add2Cart(has_size) { if (has_size) { this.pickSize(); cy.get(selectors.pdp_add2CartBtn).click(); } else { cy.get(selectors.pdp_add2CartBtn).click(); } cy.checkForPopup(); } /** * iterate over the dropdown menu and choose the first size that is not sold out */ pickSize() { cy.get(selectors.pdp_chooseSizeBtn).click(); cy.get(selectors.pdp_sizes).each(($size_elem) => { if ( !$size_elem.text().includes(Cypress.env('soldOutText')) && !$size_elem.text().includes(Cypress.env('onlyInShopText')) ) { cy.wrap($size_elem).click(); return false; // has to return false to stop iterating } }); } }
根因分析
- 加购请求未完成就跳转:当前
add2Cart方法点击加购按钮后仅执行了弹窗检查,没有等待加购接口返回成功就直接跳转第二个商品页,德语区接口响应速度慢于其他地区时,第一个加购请求还未落库就跳转,导致数据丢失。 - 尺码匹配逻辑偶发失效:
pickSize方法直接用原始文本判断库存,德语区的soldOutText、onlyInShopText存在特殊字符、前后空格差异时,会偶发匹配不到可用尺码,未选尺码就点击加购,加购失败但无报错抛出。 - 匿名购物车存储逻辑差异:未接受Cookie时,德语区匿名用户购物车可能用localStorage/sessionStorage存储,跳转页面时存在数据清空逻辑,和其他租户的存储逻辑不一致。
- 购物车计数校验提前:校验购物车数量时没有等待第二个加购请求完成,直接读取旧数据导致计数错误。
修复方案
- 等待加购接口响应:在
add2Cart方法中拦截加购接口,等待接口返回200后再执行后续操作
add2Cart(has_size) { cy.intercept('POST', '*/api/cart/add').as('addCart') if (has_size) { this.pickSize(); cy.get(selectors.pdp_add2CartBtn).click(); } else { cy.get(selectors.pdp_add2CartBtn).click(); } cy.wait('@addCart').its('response.statusCode').should('eq', 200) cy.checkForPopup(); }
- 优化尺码匹配逻辑:增加文本trim处理,同时断言可用尺码存在,避免无意义的加购操作
pickSize() { cy.get(selectors.pdp_chooseSizeBtn).click(); let sizeSelected = false cy.get(selectors.pdp_sizes).each(($size_elem) => { const sizeText = $size_elem.text().trim() if ( !sizeText.includes(Cypress.env('soldOutText').trim()) && !sizeText.includes(Cypress.env('onlyInShopText').trim()) ) { cy.wrap($size_elem).click(); sizeSelected = true return false; } }).then(() => { expect(sizeSelected).to.eq(true, '未找到可用尺码,加购终止') }) }
- 校验购物车数量前增加等待逻辑:拦截购物车查询接口,等待接口返回后再校验数量,或者给
checkCartAmount方法增加重试机制。 - 排查德语区匿名购物车存储逻辑:确认未接受Cookie时购物车的存储介质和读写逻辑,和其他租户对齐,避免跨页面数据丢失。
内容的提问来源于stack exchange,提问作者Florian Laßnig
相关产品推荐
相关产品推荐

