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

如何归一化测试重试的截图路径,让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"

核心疑问

  1. 如何归一化截图标识,让重试版本在Argos中对比同一基线?
  2. 是否可自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 21:13:11