如何归一化测试重试的截图路径,让Argos对比同一基线?
Playwright重试时Argos视觉回归测试路径冲突问题
问题背景
使用Playwright进行端到端测试,搭配Argos CI做视觉回归测试,已启用测试重试(retries: 2)。但重试时Playwright会为测试输出目录添加-retry1、-retry2后缀,导致Argos将重试生成的截图视为独立测试,出现「新增截图」「移除截图」的误报:
首次尝试: test-results/my-test/argos/screenshot.png 重试1: test-results/my-test-retry1/argos/screenshot.png 重试2: test-results/my-test-retry2/argos/screenshot.png
需要让所有重试尝试的截图与首次尝试使用同一逻辑标识,确保Argos对比同一基线。
当前配置
playwright.config.ts
import { defineConfig } from "@playwright/test"; export default defineConfig({ testDir: "./e2e/tests", reporter: [ ["list"], ["@argos-ci/playwright/reporter", { uploadToArgos: false }] ], retries: process.env.CI ? 2 : undefined, // ... 其他配置 });
截图封装(e2e/fixtures.ts)
import { argosScreenshot as argosScreenshotBase } from "@argos-ci/playwright"; export async function argosScreenshot(page, name, options) { if (process.env.CI || process.env.SCREENSHOT) { await argosScreenshotBase(page, name, { fullPage: true, ...options }); } }
已尝试的无效方案
- 归一化
testInfo.outputDir:该属性为只读,无法修改 - 使用自定义
root选项:Argos Reporter内部依赖testInfo.outputPath(),该配置不生效 - 调用
DO_NOT_USE_setMetadataConfig:触发运行时错误"Unable to find any of the following packages"
核心疑问
- 如何归一化截图标识,让重试版本在Argos中对比同一基线?
- 是否可自定义Argos Playwright Reporter的路径生成逻辑?
解决方案
1. 归一化截图标识(推荐)
通过Playwright的testInfo对象提取统一的测试名称,剥离重试后缀,让Argos将重试的截图关联到同一基线:
修改e2e/fixtures.ts,扩展Playwright测试fixture并传入testInfo:
import { test as base } from "@playwright/test"; import { argosScreenshot as argosScreenshotBase } from "@argos-ci/playwright"; export const test = base.extend({ argosScreenshot: async ({ page, testInfo }, use) => { async function screenshot(name: string, options?: Parameters<typeof argosScreenshotBase>[2]) { if (process.env.CI || process.env.SCREENSHOT) { // 生成不带重试后缀的统一测试标识 const normalizedTestName = testInfo.titlePath.join(" > ").replace(/-retry\d+$/, ""); // 用统一标识作为截图名称的前缀 await argosScreenshotBase(page, `${normalizedTestName} > ${name}`, { fullPage: true, ...options, }); } } await use(screenshot); }, });
在测试文件中使用该fixture:
import { test } from "../fixtures"; test("示例测试", async ({ page, argosScreenshot }) => { await page.goto("/"); await argosScreenshot("首页截图"); });
此方法通过统一截图的名称标识,让Argos忽略路径中的重试后缀,将所有重试的截图关联到同一基线。
2. 复制重试截图到统一路径
在测试的afterEach钩子中,将重试生成的截图复制到首次尝试的目录,覆盖旧文件,确保Argos只读取最终的有效截图:
import { test as base } from "@playwright/test"; import fs from "fs/promises"; import path from "path"; export const test = base.extend({ // ... 其他fixture }); test.afterEach(async ({ testInfo }) => { if (testInfo.retry > 0) { // 提取无重试后缀的原始输出目录 const originalOutputDir = testInfo.outputDir.replace(/-retry\d+$/, ""); // 复制Argos截图到原始目录 const retryScreenshotPath = path.join(testInfo.outputDir, "argos"); const originalScreenshotPath = path.join(originalOutputDir, "argos"); try { await fs.rm(originalScreenshotPath, { recursive: true, force: true }); await fs.cp(retryScreenshotPath, originalScreenshotPath, { recursive: true }); } catch (err) { console.error("复制重试截图失败:", err); } } });
3. 关于自定义Argos Reporter路径生成逻辑
当前@argos-ci/playwright官方包未提供公开的路径生成自定义API,但可通过以下间接方式实现:
- 基于上述归一化标识的方法,绕过路径依赖,用统一的名称标识关联基线
- 自定义Playwright Reporter,包装Argos Reporter,在上传前修改截图的元数据(如测试ID、名称),去除重试后缀
内容的提问来源于stack exchange,提问作者Abu Sadaf
相关产品推荐
相关产品推荐

