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

如何在Cypress每个it块中独立更新CSV文件

解决Cypress每个it块独立更新CSV文件的问题

问题描述

希望在Cypress测试的每个it块中独立更新CSV文件的orderId、日期等数据,但当前第一个it块更新后的CSV会被后续it块复用,无法实现独立更新。

相关代码

uploadOrders.cy.js

/// <reference types='Cypress'/>

import { ORDERS } from '../../selector/orders';
import BU from '../../fixtures/BU.json';
import Helper from '../../e2e/utils/Helper';
const helper = new Helper();

let getTodaysDate = helper.getTodaysDate(); 
let getTomorrowssDate = helper.getTomorrowsDate(); 
let getYesterdaysDate = helper.getYesterdaysDate(); 

describe('Upload Orders', () => {
    before(() => {
        cy.login(); 
        cy.get(ORDERS.ORDER_ICON).click();
    });

    beforeEach(() => {
        cy.writeFile('cypress/fixtures/finalCsvToBeUploaded.csv', ''); 
    });

    it('Upload orders and check its successful', () => {
        let csvData = {
            orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
            orderDate: getTomorrowssDate,
            homebaseExecutionDate: getTomorrowssDate,
            customerExecutionDate: getTomorrowssDate,
        }

        cy.readFile('cypress/fixtures/referenceCsvFile.csv')
            .then((data) => {
                cy.task('csvToJson', data)
                    .then(finalJsonArray => {
                        cy.task('updateCsvData', { csvData, finalJsonArray })
                            .then(finalUpdatedJsonArray => {
                                cy.log("Update JSON array: " + finalUpdatedJsonArray[0]['Order ID']);
                                cy.task('finalCsv', finalUpdatedJsonArray);
                            });
                    })
            })
        cy.get(ORDERS.ORDER_UPLOAD).click();
        cy.attachCsvFile('finalCsvToBeUploaded.csv');
        cy.validateToastMsg('Orders uploaded successfully');
        cy.log('Order is uploaded successfully  via csv file and orderId is ');
    });

    it('Upload orders and check validation for past customer execution date', () => {
        cy.wait(5000);
        let csvData = {
            orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
            orderDate: getTomorrowssDate,
            homebaseExecutionDate: getYesterdaysDate,
            customerExecutionDate: getYesterdaysDate,
        }
        cy.readFile('cypress/fixtures/finalCsvToBeUploaded.csv')
            .then((data) => {
                cy.task('csvToJson', data)
                    .then(finalJsonArray => {
                        cy.task('updateCsvData', { csvData, finalJsonArray })
                            .then(finalUpdatedJsonArray => {
                                cy.log("Update JSON array: " + finalUpdatedJsonArray);
                                cy.task('finalCsv', finalUpdatedJsonArray);
                            });
                    })
            })
        cy.get(ORDERS.ORDER_UPLOAD).click();
        cy.attachCsvFile('finalCsvToBeUploaded.csv');
        cy.validateToastMsg('Orders uploaded successfully');
        cy.log('Order is uploaded successfully  via csv file and orderId is');
    });

    after(() => {
        cy.clearCookies();
        cy.clearLocalStorage();
    });
});

cypress.config.js

const { defineConfig } = require("cypress");
const converter = require('json-2-csv');
const csv = require('csv-parser');
const fs = require('fs');
const { default: Helper } = require("./cypress/e2e/utils/Helper");
const csvToJson1 = require('convert-csv-to-json');
const helper = require("csvtojson");

module.exports = defineConfig({
  chromeWebSecurity: false,
  watchFileForChanges: false,
  defaultCommandTimeout: 10000,
  pageLoadTimeout: 50000,
  viewportWidth: 1280,
  viewportHeight: 800,
  video: false,
  screenshotOnRunFailure: true,
  "reporter": "mochawesome",
  "reporterOptions": {
    "charts": true,
    "overwrite": false,
    "html": false,
    "json": true,
    "timestamp": 'dd_mm_yy_HH_MM_ss',
    "reportDir": "cypress/reports/mochawesome-report"
  },

  e2e: {
    specPattern: 'cypress/e2e/**/*.cy.js',

    setupNodeEvents(on, config) {
      require('@cypress/code-coverage/task')(on, config)

      on('before:browser:launch', (browser = {}, launchOptions) => {
        console.log(launchOptions.args);
        if (browser.family === 'chromium' && browser.name !== 'electron') {
          launchOptions.args.push('--start-fullscreen');
        }
        if (browser.name === 'electron') {
          launchOptions.preferences.fullscreen = true;
        }
        return launchOptions;
      });

      on('task', {
        csvToJson(data) {
          var lines = data.split("\n");
          var result = [];
          var headers = lines[0].split(",");
          for (var i = 1; i < (lines.length); i++) {
            var obj = {};
            var currentline = lines[i].split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
            for (var j = 0; j < headers.length; j++) {
              obj[headers[j]] = currentline[j].replace(/["']/g, "");
            }
            result.push(obj);
          }
          console.log(result);
          return result;
        }
      })

      on('task', {
        finalCsv(updatedJSON) {
          converter.json2csvAsync(updatedJSON).then(updatedCsv => {
            fs.writeFileSync('cypress/fixtures/finalCsvToBeUploaded.csv', updatedCsv);
          }).catch(err => console.log(err));
          return null;
        }
      });

      on('task', {
        log(message) {
          console.log(message);
          return null;
        },
      });

      on('task', {
        updateCsvData({ csvData, finalJsonArray }) {
          let updatedJSON,orderIds = [];
          for (let i = 0; i < (finalJsonArray.length); i++) {
            if ('orderId' in csvData) {
              orderIds[i] = csvData.orderId;
              finalJsonArray[i]['Order ID'] = csvData.orderId;
            }
            else {
              orderIds[i] = 'OrderId_' + Date.now();
              finalJsonArray[i]['Order ID'] = orderIds[i];
            }

            if ('orderDate' in csvData) {
              finalJsonArray[i]['Order Date'] = csvData.orderDate;
            }
            if ('homebaseExecutionDate' in csvData) {
              finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
            }
            if ('customerExecutionDate' in csvData) {
              finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
            }
          }
          updatedJSON = finalJsonArray;
          return updatedJSON;
        }
      })

      on('task', {
        updateCsvFile(csvData) {
          const finalJsonArray = [];
          let updatedJSON, orderIds = [];

          fs.createReadStream('cypress/fixtures/referenceCsvFile.csv')
            .pipe(csv())
            .on('data', (data) => finalJsonArray.push(data))
            .on('end', () => {
              console.log(finalJsonArray); 

              for (let i = 0; i < (finalJsonArray.length); i++) {
                if ('orderId' in csvData) {
                  orderIds[i] = csvData.orderId;
                  finalJsonArray[i]['Order ID'] = csvData.orderId;
                }
                else {
                  orderIds[i] = 'OrderId_' + this.getCurrentDateAndTimeInMiliseconds();
                  finalJsonArray[i]['Order ID'] = orderIds[i];
                }

                if ('orderDate' in csvData) {
                  finalJsonArray[i]['Order Date'] = csvData.orderDate;
                }
                if ('homebaseExecutionDate' in csvData) {
                  finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
                }
                if ('customerExecutionDate' in csvData) {
                  finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
                }
              }

              updatedJSON = finalJsonArray;
              converter.json2csvAsync(updatedJSON).then(csvFile => {
                fs.writeFileSync('cypress/fixtures/' + fileName, csvFile)
              }).catch(err => console.log(err));
            })
          return orderIds;
        }
      })
      return config;
    }
  }
});

问题原因分析

  1. 第二个测试用例读取错误文件:第二个it块中读取的是被beforeEach清空的finalCsvToBeUploaded.csv,而非原始模板referenceCsvFile.csv,导致无法基于模板生成新的测试数据。
  2. 异步文件写入未等待完成:finalCsv任务中使用converter.json2csvAsync异步生成CSV,但任务直接返回null,没有等待写入完成,导致后续上传操作可能读取到未更新完成的旧文件。

解决方案

1. 修正第二个测试用例的文件读取逻辑

将第二个it块中的文件读取路径改为原始模板文件,确保每次测试都从干净的模板生成数据:

// 第二个it块修改后
it('Upload orders and check validation for past customer execution date', () => {
    let csvData = {
        orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
        orderDate: getTomorrowssDate,
        homebaseExecutionDate: getYesterdaysDate,
        customerExecutionDate: getYesterdaysDate,
    }
    // 改为读取reference模板文件
    cy.readFile('cypress/fixtures/referenceCsvFile.csv')
        .then((data) => {
            cy.task('csvToJson', data)
                .then(finalJsonArray => {
                    cy.task('updateCsvData', { csvData, finalJsonArray })
                        .then(finalUpdatedJsonArray => {
                            cy.log("Update JSON array: " + finalUpdatedJsonArray[0]['Order ID']);
                            cy.task('finalCsv', finalUpdatedJsonArray);
                        });
                })
        })
    cy.get(ORDERS.ORDER_UPLOAD).click();
    cy.attachCsvFile('finalCsvToBeUploaded.csv');
    cy.validateToastMsg('Orders uploaded successfully');
    cy.log('Order is uploaded successfully via csv file and orderId is ' + csvData.orderId);
});

2. 修复finalCsv任务的异步等待问题

修改cypress.config.js中的finalCsv任务,使用async/await等待异步操作完成,确保Cypress等待文件写入后再执行后续命令:

// 修正后的finalCsv任务
on('task', {
    async finalCsv(updatedJSON) {
        try {
            const updatedCsv = await converter.json2csvAsync(updatedJSON);
            fs.writeFileSync('cypress/fixtures/finalCsvToBeUploaded.csv', updatedCsv);
            return null;
        } catch (err) {
            console.error(err);
            throw err; // 抛出错误让Cypress捕获并终止测试
        }
    }
});

3. 优化测试流程,确保命令顺序执行

将上传操作放在cy.task('finalCsv')的回调中,确保文件完全写入后再执行上传,避免异步命令顺序问题:

// 第一个it块优化后
it('Upload orders and check its successful', () => {
    let csvData = {
        orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
        orderDate: getTomorrowssDate,
        homebaseExecutionDate: getTomorrowssDate,
        customerExecutionDate: getTomorrowssDate,
    }

    cy.readFile('cypress/fixtures/referenceCsvFile.csv')
        .then((data) => {
            cy.task('csvToJson', data)
                .then(finalJsonArray => {
                    cy.task('updateCsvData', { csvData, finalJsonArray })
                        .then(finalUpdatedJsonArray => {
                            cy.log("Update JSON array: " + finalUpdatedJsonArray[0]['Order ID']);
                            return cy.task('finalCsv', finalUpdatedJsonArray);
                        })
                        .then(() => {
                            // 文件写入完成后执行上传操作
                            cy.get(ORDERS.ORDER_UPLOAD).click();
                            cy.attachCsvFile('finalCsvToBeUploaded.csv');
                            cy.validateToastMsg('Orders uploaded successfully');
                            cy.log('Order is uploaded successfully via csv file and orderId is ' + csvData.orderId);
                        });
                })
        })
});

额外建议

移除第二个it块中的cy.wait(5000),Cypress的异步命令会自动等待前序操作完成,硬编码等待时间会降低测试稳定性和效率。

内容的提问来源于stack exchange,提问作者Chethan CP

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 04:24:46