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

Cypress数据库初始化优化:解决超时与提前执行需求

解决方案与优化实现

一、解决SQL执行超时问题

1. 修正异步执行逻辑(核心修复)

原代码用forEach遍历文件时,Cypress不会等待每个异步的cy.task完成,导致命令提前结束或超时。改用cy.wrap()+cy.each组合,确保每一步SQL操作完成后再执行下一个:

Cypress.Commands.add('seedDB', (customerFlag) => {
  // 用const声明变量,避免全局污染
  const deleteDataSQLFile = 'cypress/database/delete_data.sql';
  const sqlFileLocation = 'cypress/database/reset/'

  // 执行删除数据SQL,单独设置超时
  cy.readFile(deleteDataSQLFile, { timeout: 10000 })
    .then((sql) => {
      cy.task("runSQLDB", {
        dbConfig: Cypress.config('dbConfig'),
        sqlQuery: sql
      }, { timeout: 30000 }) // 数据库操作超时设为30秒
    })

  // 遍历执行所有重置SQL文件
  cy.task('countFiles', sqlFileLocation, { timeout: 10000 })
    .then((fileArray) => {
      cy.wrap(fileArray).each((fileName) => {
        cy.readFile(`${sqlFileLocation}${fileName}`, { timeout: 10000 })
          .then((sql) => {
            cy.task("runSQLDB", {
              dbConfig: Cypress.config('dbConfig'),
              sqlQuery: sql
            }, { timeout: 30000 })
          })
      })
    })
})

2. 调整全局超时配置

在cypress.config.js中提升全局超时阈值,避免默认4秒超时限制:

module.exports = defineConfig({
  e2e: {
    defaultCommandTimeout: 10000, // 全局命令超时设为10秒
    taskTimeout: 30000, // Task操作超时设为30秒
    // 其他配置...
  },
})

3. 合并SQL减少执行次数

将reset目录下的所有SQL文件合并为一个,减少数据库连接和IO开销:

# Linux/macOS终端执行
cat cypress/database/reset/*.sql > cypress/database/reset/all_reset.sql

# Windows终端执行
copy cypress/database/reset/*.sql cypress/database/reset/all_reset.sql

修改seedDB命令直接读取合并后的文件:

// 替换原遍历文件的逻辑
cy.readFile(`${sqlFileLocation}all_reset.sql`, { timeout: 10000 })
  .then((sql) => {
    cy.task("runSQLDB", {
      dbConfig: Cypress.config('dbConfig'),
      sqlQuery: sql
    }, { timeout: 60000 }) // 合并后SQL更长,超时设为60秒
  })

二、实现测试前全局初始化(解耦测试文件)

不要在每个测试文件的before中调用seedDB,而是在整个测试套件启动前执行一次,推荐两种方式:

方式1:Node端beforeRun钩子执行(推荐,更高效)

直接在cypress.config.js的Node环境中执行数据库初始化,脱离浏览器环境,不受Cypress超时限制:

  1. 先安装数据库依赖(以PostgreSQL为例,MySQL用mysql2):
npm install pg --save-dev
  1. 修改cypress.config.js:
const { defineConfig } = require('cypress')
const fs = require('fs')
const { Pool } = require('pg')

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      // 注册beforeRun钩子,所有测试启动前执行
      on('before:run', async () => {
        console.log('开始全局数据库初始化...')
        const dbConfig = config.dbConfig
        const pool = new Pool(dbConfig)

        try {
          // 执行删除数据SQL
          const deleteSql = fs.readFileSync('cypress/database/delete_data.sql', 'utf8')
          await pool.query(deleteSql)
          
          // 执行合并后的重置SQL
          const resetSql = fs.readFileSync('cypress/database/reset/all_reset.sql', 'utf8')
          await pool.query(resetSql)
          
          console.log('数据库初始化完成')
        } catch (error) {
          console.error('数据库初始化失败:', error)
          throw error // 终止测试运行
        } finally {
          await pool.end() // 关闭连接池
        }
      })

      // 保留原有runSQLDB task(若其他场景需要)
      on('task', {
        runSQLDB: async ({ dbConfig, sqlQuery }) => {
          const pool = new Pool(dbConfig)
          try {
            await pool.query(sqlQuery)
            return null
          } catch (error) {
            throw error
          } finally {
            await pool.end()
          }
        }
      })
    },
    // 配置数据库连接信息
    dbConfig: {
      user: 'your_user',
      host: 'your_host',
      database: 'your_db',
      password: 'your_password',
      port: 5432
    },
  },
})

方式2:全局支持文件的before钩子执行

若不想在Node端处理,可在cypress/support/e2e.js中添加全局before钩子,仅执行一次:

// cypress/support/e2e.js
before(() => {
  cy.seedDB() // 调用优化后的seedDB命令
})

额外优化建议

  • 事务回滚替代全量重置:若数据库支持事务,可在每个测试用例开始时开启事务,测试结束后回滚,大幅减少初始化时间。
  • Jenkins环境优化:确保Jenkins服务器与数据库网络连接稳定,必要时进一步提升超时时间,或在Jenkins构建前提前合并SQL文件。

内容的提问来源于stack exchange,提问作者James Dudley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 13:40:03