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

Playwright集成Browserstack测试日志不全及浏览器重启问题

解决Playwright集成Browserstack Automate时测试结果不完整的问题

问题原因

默认情况下Playwright会复用浏览器实例/上下文以提升测试效率,但Browserstack Automate的每个会话对应一个独立浏览器实例。当多个测试复用同一个Browserstack会话时,仅第一个测试的结果会被正确记录,后续测试结果会被覆盖或忽略——这就是你看到仅2个测试结果(对应默认2个worker)的原因。

而手动在每个测试中启动/关闭浏览器,相当于为每个测试创建独立的Browserstack会话,因此所有结果都能被正确记录。

正确实现每个测试独立启停浏览器的方法

方法1:自定义Playwright Fixture(推荐)

通过自定义fixture让每个测试自动获取独立的浏览器和页面实例,避免重复代码,同时确保实例正确传递和销毁:

import { test as base, Browser, Page } from '@playwright/test';
import { chromium } from '@playwright/test';

// 定义自定义fixture类型
type CustomFixtures = {
  bsBrowser: Browser;
  bsPage: Page;
};

// 扩展base测试,添加自定义fixture
export const test = base.extend<CustomFixtures>({
  // 每个测试创建独立浏览器实例,测试结束后自动关闭
  bsBrowser: async ({}, use) => {
    const browser = await chromium.launch();
    await use(browser);
    await browser.close();
  },
  // 基于上述浏览器实例创建页面,提前跳转目标URL
  bsPage: async ({ bsBrowser }, use) => {
    const page = await bsBrowser.newPage();
    await page.goto(`${url}`); // 替换为你的目标URL
    await use(page);
    await page.close();
  },
});

测试用例中使用自定义的bsPage:

test('test1', async ({ bsPage }) => {
  test.setTimeout(240000);
  try {
    // 你的测试逻辑
    await bsPage.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({
      action: 'setSessionStatus',
      arguments: { name: 'test1', status: 'passed', reason: '' }
    })}`);
  } catch (e) {
    console.error(e);
    await bsPage.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({
      action: 'setSessionStatus',
      arguments: { name: 'test1', status: 'failed', reason: e.message }
    })}`);
  }
});

test('test2', async ({ bsPage }) => {
  // 第二个测试逻辑
});

方法2:配置Playwright强制每个测试使用独立浏览器

在playwright.config.ts中配置,让Playwright不为测试复用浏览器实例:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  // 启用完全并行,每个测试独立运行
  fullyParallel: true,
  // 禁用上下文复用,每个测试创建全新上下文
  use: {
    contextOptions: {
      storageState: undefined, // 不保留存储状态
      permissions: [], // 不保留权限
    },
  },
  projects: [
    {
      name: 'chromium',
      use: {
        // 根据你的Browserstack配置填写launch参数,比如通过环境变量传递
        launchOptions: {},
      },
    },
  ],
});

若需要统一前置操作(如跳转URL),可配合beforeEach钩子,但需确保操作的是当前测试的上下文/页面。

为什么之前的钩子写法失败?

你之前的beforeEach中创建的browser和page是局部变量,未传递给测试用例。测试用例使用的page是Playwright默认提供的、属于复用浏览器实例的页面,而afterEach中关闭的browser也是默认实例,导致测试未完成时浏览器就被提前关闭,从而抛出"浏览器被意外关闭"的错误。

额外注意事项

  • 确保每个测试无论成功失败,都调用browserstack_executor的setSessionStatus方法,否则Browserstack可能将会话标记为超时或未完成。
  • 使用多worker时,确保Browserstack账号允许的并发会话数不低于worker数量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:40:43