如何在Cypress中通过字符串插值指定所有子目录读取截图文件?
解决Cypress中读取多级目录下测试截图的问题
问题原因
cy.readFile() 不支持glob模式的通配符(比如**),只能接收具体的文件路径,所以直接在路径中添加**无法匹配多级子目录。
解决方案
我们需要先通过Node.js的文件系统工具递归查找目标截图的准确路径,再传入cy.readFile()进行读取。以下是两种可行实现方式:
方式1:使用原生Node.js fs模块(无额外依赖)
首先在cypress.config.js中注册一个自定义任务,用于递归查找文件:
const { defineConfig } = require('cypress'); const fs = require('fs').promises; const path = require('path'); module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { on('task', { // 查找指定的测试截图 findScreenshot: async ({ screenshotsFolder, specName, screenshotFileName }) => { // 递归遍历所有子目录,找到包含specName目录且文件名匹配的文件 const allFiles = await fs.readdir(screenshotsFolder, { recursive: true }); const targetFileRelativePath = allFiles.find(file => file.includes(`${specName}/`) && file.endsWith(screenshotFileName) ); if (!targetFileRelativePath) { throw new Error(`未找到截图:${screenshotFileName}`); } return path.join(screenshotsFolder, targetFileRelativePath); } }); }, }, });
然后在测试的afterEach钩子中调用该任务,获取路径后读取文件:
afterEach(() => { const screenshotsFolder = 'test-results/screenshots'; const screenshotFileName = `${testState.feature.name} -- ${testState.currentScenario.name} (failed).png`; cy.task('findScreenshot', { screenshotsFolder, specName: Cypress.spec.name, screenshotFileName }).then((screenshotPath) => { cy.readFile(screenshotPath, "base64").then((imgData) => { stepResult.attachment = { data: imgData, media: { type: "image/png" }, index: testState.currentStep, testCase: testState.formatTestCase(testState.currentScenario), }; }); }).catch(err => { // 处理未找到截图的情况,避免影响后续流程 console.log(err.message); }); });
方式2:使用glob包(更简洁,需额外安装)
如果希望用glob语法快速匹配路径,可以先安装glob包:
npm install glob --save-dev
然后在cypress.config.js中注册任务:
const { defineConfig } = require('cypress'); const glob = require('glob'); module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { on('task', { findScreenshot: ({ screenshotsFolder, specName, screenshotFileName }) => { const pattern = `${screenshotsFolder}/**/${specName}/${screenshotFileName}`; const matchedFiles = glob.sync(pattern); if (matchedFiles.length === 0) { throw new Error(`未找到截图:${screenshotFileName}`); } // 返回第一个匹配的文件路径 return matchedFiles[0]; } }); }, }, });
测试中的afterEach代码和方式1完全一致。
内容的提问来源于stack exchange,提问作者user9847788
相关产品推荐
相关产品推荐

