You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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      
      }    
    });  
  }
}

根因分析

  1. 加购请求未完成就跳转:当前add2Cart方法点击加购按钮后仅执行了弹窗检查,没有等待加购接口返回成功就直接跳转第二个商品页,德语区接口响应速度慢于其他地区时,第一个加购请求还未落库就跳转,导致数据丢失。
  2. 尺码匹配逻辑偶发失效:pickSize方法直接用原始文本判断库存,德语区的soldOutText、onlyInShopText存在特殊字符、前后空格差异时,会偶发匹配不到可用尺码,未选尺码就点击加购,加购失败但无报错抛出。
  3. 匿名购物车存储逻辑差异:未接受Cookie时,德语区匿名用户购物车可能用localStorage/sessionStorage存储,跳转页面时存在数据清空逻辑,和其他租户的存储逻辑不一致。
  4. 购物车计数校验提前:校验购物车数量时没有等待第二个加购请求完成,直接读取旧数据导致计数错误。

修复方案

  1. 等待加购接口响应:在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();
}
  1. 优化尺码匹配逻辑:增加文本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, '未找到可用尺码,加购终止')
  })
}
  1. 校验购物车数量前增加等待逻辑:拦截购物车查询接口,等待接口返回后再校验数量,或者给checkCartAmount方法增加重试机制。
  2. 排查德语区匿名购物车存储逻辑:确认未接受Cookie时购物车的存储介质和读写逻辑,和其他租户对齐,避免跨页面数据丢失。

内容的提问来源于stack exchange,提问作者Florian Laßnig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 20:42:01