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

Playwright多Worker运行时钩子重复执行问题咨询

Playwright多Worker/多浏览器下beforeAll重复执行问题排查与解决

核心原因

  1. 多浏览器项目的隔离执行:你同时在4个浏览器环境(chromium、firefox、webkit、Mobile Safari)运行测试,Playwright会为每个浏览器创建独立的测试项目,每个项目会单独加载并执行你的测试文件。这意味着你的beforeAll/afterAll钩子会被每个浏览器项目各执行一次。
  2. 全并行模式的Worker分配:默认开启的fullyParallel: true会让每个测试用例被分配到独立的Worker执行。即便是同一个浏览器下的两个测试用例,也可能被分到不同Worker,每个Worker会重新加载测试文件,导致钩子重复触发。这就是为什么每条测试用例的日志前后都出现了beforeAll和afterAll。

针对性解决方案

方案1:每个浏览器项目仅执行一次钩子

如果需要每个浏览器环境下的所有测试用例共享一次钩子逻辑,确保同项目的测试用例在同一个Worker中执行:
在playwright.config.ts中配置workerPerProject: true,让每个浏览器项目独占一个Worker,该项目下的所有测试用例会共用这个Worker,钩子仅触发一次:

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
    { name: 'Mobile Safari', use: { ...devices['iPhone 14'] } },
  ],
  workerPerProject: true, // 每个项目分配独立Worker
  workers: 4, // 对应4个浏览器项目,刚好匹配Worker数量
});

方案2:全局所有浏览器仅执行一次钩子

如果需要跨所有浏览器共享全局初始化/清理逻辑(比如只启动一次后端服务),使用Playwright的globalSetup和globalTeardown:

  1. 在配置文件中指定全局脚本:
// playwright.config.ts
export default defineConfig({
  globalSetup: './global-setup.ts',
  globalTeardown: './global-teardown.ts',
  // 其他配置...
});
  1. 编写全局启动脚本:
// global-setup.ts
export default async () => {
  console.log("should be before all tests across all browsers");
  // 执行全局初始化:如启动测试服务、创建数据库连接等
};
  1. 编写全局清理脚本:
// global-teardown.ts
export default async () => {
  console.log('should be after all tests across all browsers');
  // 清理全局资源
};

注意:globalSetup/globalTeardown运行在Node.js环境,无法直接访问Playwright的browser等测试上下文。如果需要浏览器级的全局共享资源,使用自定义Worker级夹具:

// fixtures.ts
import { test as base } from '@playwright/test';

type SharedFixtures = {
  sharedBrowser: Browser;
};

export const test = base.extend<SharedFixtures>({
  sharedBrowser: [async ({ browser }, use) => {
    console.log("Initializing shared browser for worker");
    await use(browser);
    console.log("Cleaning up shared browser for worker");
  }, { scope: 'worker' }], // scope设为worker,每个Worker仅执行一次
});

在测试文件中导入这个自定义测试对象即可:

import { test } from './fixtures';

test.beforeEach(() => {
  console.log('should be before Each test');
});

test('test case', async ({ sharedBrowser }) => {
  // 测试逻辑
});

test('test case 2', async ({ sharedBrowser }) => {
  // 测试逻辑
});

预期效果

配置完成后,每个浏览器项目的Worker会仅执行一次钩子逻辑,日志会变为:

Running 8 tests using 4 workers
[chromium] › loginAndNavigate.spec.ts:60:5 › test case 1
should be before all tests
should be before Each test
[chromium] › loginAndNavigate.spec.ts:65:5 › test case 2
should be before Each test
should be after all tests
[firefox] › loginAndNavigate.spec.ts:60:5 › test case 1
should be before all tests
should be before Each test
[firefox] › loginAndNavigate.spec.ts:65:5 › test case 2
should be before Each test
should be after all tests
...(其他浏览器日志类似)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 00:07:55