Cypress测试批量写入数据库仅最后一条生效,求正确异步处理方案
Cypress多产品创建仅最后一个成功的问题解决
问题现象
编写Cypress测试时,尝试向数据库写入多个产品,但仅最后一个产品成功写入数据库。
相关代码
测试代码(my_test.cy.js)
// my_test.cy.js import CreateProductPage from "../pages/CreateProductPage"; describe('product detail page', () => { beforeEach(() => { cy.login('admin', 'shop') }) it('should print typed product', () => { cy.createProduct(null, 'Component Product 0', '0') CreateProductPage.elements.productDetailTabs().should('exist') // 用于检测实体是否写入 cy.createProduct('combinable', 'Combined Test Product', '0') CreateProductPage.elements.productDetailTabs().should('exist') // 用于检测实体是否写入 }) })
自定义命令(commands.js)
// commands.js Cypress.Commands.add('createProduct', (type, name, grossPrice) => { cy.visit('/#/sw/product/create') CreateProductPage.elements.productDetailTabs().should('not.exist').then(() => { if(type === 'combinable') { CreateProductPage.elements.radioBtnCombinableProduct().click() } CreateProductPage.elements.inputProductName().clear().type(name) CreateProductPage.elements.inputPriceFieldGross().type(grossPrice) SwPageHeader.elements.btnProductSave().click() }) })
临时解决代码(添加cy.wait)
// my_test.cy.js describe('product detail page', () => { beforeEach(() => { cy.login('admin', 'shop') }) it('should print typed product', () => { cy.createProduct(null, 'Component Product 0', '0') CreateProductPage.elements.productDetailTabs().should('exist') cy.wait(300) cy.createProduct('combinable', 'Combined Test Product', '0') CreateProductPage.elements.productDetailTabs().should('exist') }) })
页面元素定义(CreateProductPage.js)
// pages/CreateProductPage.js class CreateProductPage { elements = { productDetailTabs: () => cy.get('div.sw-product-detail-page__tabs'), radioBtnCombinableProduct: () => cy.get('.sw-product-detail-base__info input#type_combinable_product-0'), radioBtnUnCombinableProduct: () => cy.get('.sw-product-detail-base__info input#type_combinable_product-1'), inputProductName: () => cy.get('input#sw-field--product-name'), inputPriceFieldGross: () => cy.get('div.sw-list-price-field__price input#sw-price-field-gross'), } } module.exports = new CreateProductPage();
疑问
- 该问题是否由Cypress的异步特性导致?
- 若是,如何正确处理该异步问题?使用
then()链式调用后问题依旧,添加cy.wait(300)可临时解决,但想寻求正确的实现方式。
解答
1. 问题根源
确实和Cypress的异步特性相关,但核心原因是未正确等待第一个产品的创建流程完全结束,就启动了第二个产品的创建操作。
原自定义命令createProduct中,点击保存按钮后没有等待保存完成(包括API请求结束、页面跳转完成)就结束了命令,导致测试代码提前执行第二个createProduct的cy.visit,覆盖了第一个产品的保存请求或打乱了页面状态,最终只有最后一个产品的创建流程完整执行。
2. 正确处理方式
要让每个产品创建的异步流程完全结束后,再执行下一个操作,最可靠的方式是在自定义命令内部完成所有必要的等待逻辑,确保命令执行完毕时,产品已经成功写入数据库且页面状态稳定。
方案一:等待页面状态稳定
修改自定义命令,在点击保存后等待产品详情页的标签栏(productDetailTabs)出现,确保页面跳转完成、产品创建成功:
// commands.js Cypress.Commands.add('createProduct', (type, name, grossPrice) => { cy.visit('/#/sw/product/create') // 等待创建页面加载完成(详情标签栏不存在) CreateProductPage.elements.productDetailTabs().should('not.exist') if(type === 'combinable') { CreateProductPage.elements.radioBtnCombinableProduct().click() } CreateProductPage.elements.inputProductName().clear().type(name) CreateProductPage.elements.inputPriceFieldGross().type(grossPrice) SwPageHeader.elements.btnProductSave().click() // 等待保存完成,详情标签栏出现,确保产品创建成功 CreateProductPage.elements.productDetailTabs().should('exist') })
对应的测试代码可以简化,无需额外断言:
// my_test.cy.js import CreateProductPage from "../pages/CreateProductPage"; describe('product detail page', () => { beforeEach(() => { cy.login('admin', 'shop') }) it('should print typed product', () => { cy.createProduct(null, 'Component Product 0', '0') cy.createProduct('combinable', 'Combined Test Product', '0') }) })
方案二:结合API拦截(更可靠)
如果页面元素的判断不够稳定,可以拦截产品保存的API请求,等待请求成功后再确认页面状态,双重保障:
// commands.js Cypress.Commands.add('createProduct', (type, name, grossPrice) => { // 拦截产品保存的POST请求,根据实际API路径调整 cy.intercept('POST', '/api/product').as('saveProduct') cy.visit('/#/sw/product/create') CreateProductPage.elements.productDetailTabs().should('not.exist') if(type === 'combinable') { CreateProductPage.elements.radioBtnCombinableProduct().click() } CreateProductPage.elements.inputProductName().clear().type(name) CreateProductPage.elements.inputPriceFieldGross().type(grossPrice) SwPageHeader.elements.btnProductSave().click() // 等待API请求完成,确保数据写入数据库 cy.wait('@saveProduct').its('response.statusCode').should('eq', 200) // 再等待页面跳转完成 CreateProductPage.elements.productDetailTabs().should('exist') })
为什么之前的then()无效?
原代码中then()只是包裹了表单填写和保存操作,但没有在then()内部等待保存完成的状态,命令依然会在点击保存后立即结束,无法阻止后续测试代码提前执行。
内容的提问来源于stack exchange,提问作者rammi22
相关产品推荐
相关产品推荐

