并发测试需精准控制资源隔离:playwright 应用 launchpersistentcontext() 配 userdatadir 实现网络层隔离,puppeteer 需显式配置 headless: "new" 与沙箱参数,并动态分配调试端口;调试须按工具适配专用模式,日志需打标区分。

并发测试不是简单地多开几个 browser.launch() 就完事——它直接暴露环境配置、上下文隔离和资源竞争的真实问题。Playwright 和 Puppeteer 都支持并发,但默认行为差异大,稍不注意就会出现端口冲突、Cookie 串扰、内存爆满或断点全部失效。
Playwright 多浏览器并发:用 BrowserType.launchPersistentContext() 还是 browser.newContext()?
多数人直接用 browser.newContext() 启动多个上下文,这没错,但它只隔离 Cookie 和 Storage,不隔离网络栈和渲染进程。真实并发压测时,你会发现所有上下文共享同一套 DNS 缓存、代理设置,甚至某些 iframe 加载会互相干扰。
-
browser.newContext()适合功能测试并行(比如同时跑 Chrome/Firefox 测试用例),轻量、启动快,但不适合高负载压力场景 - 真正需要隔离网络层的并发(如模拟 100 个独立用户行为),必须用
BrowserType.launchPersistentContext()+ 指定userDataDir,每个上下文独占 Chromium 实例和磁盘缓存 - 注意:Playwright 的
launchPersistentContext()不支持无头模式下自动清理userDataDir,必须手动rimraf或用临时目录,否则第二次运行会因锁文件报错Target closed
Puppeteer 并发卡死在 browser.launch()?检查 headless 和 args 组合
Puppeteer 默认并发启动多个无头 Chromium 实例时,常卡在 browser.launch() 不返回,根本原因不是代码问题,而是 Chromium 的资源限制被触发——尤其在 macOS 或 Docker 容器里。
下载 Comet AI 浏览器,体验由 Perplexity AI 驱动的革命性上网方式。内置 AI 助手可实时总结网页、跨标签页对比信息、自动执行任务。告别繁琐操作,让 AI 成为你的浏览副驾,大幅提升研究与工作效率。支持 Windows、macOS、Android 和 iOS。
- 必须显式传参:
{ headless: "new", args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"] },旧版headless: true在新版 Chromium 上已弃用且不稳定 - 并发数超过 4 个时,建议加
--remote-debugging-port=0(让系统自动分配空闲端口),否则容易遇到Address already in use - 别用
puppeteer.launch({ executablePath })指向全局 Chrome —— 多实例会争抢同一个可执行文件锁,应改用puppeteer.executablePath()动态获取 Playwright 自带的 Chromium 路径
VSCode 调试并发测试脚本:断点只停在一个线程上?
VSCode 默认调试器无法感知多线程异步上下文,你设了 10 个 page.goto() 断点,结果只在第一个 page 上生效,其余全跳过——这不是 bug,是调试器没关联到对应 CDP 会话。
- Playwright:用官方插件
Playwright Test for VSCode,右键测试用例选 “Debug” 即可,它会为每个 test case 自动注入独立调试会话,test.setTimeout(60000)避免超时中断 - Puppeteer:必须放弃
type: "node",改用"type": "pwa-chrome"+"request": "attach",并在每个browser.launch()里加args: ["--remote-debugging-port=9223"](递增端口),然后 launch.json 里配多个 configuration - 关键细节:每个并发 browser 实例的
wsEndpoint必须单独捕获并打印出来,手动填进 launch.json 的webSocketDebuggerUrl字段,否则调试器连不上
并发的本质不是“开更多浏览器”,而是控制资源边界。Playwright 的 test.use({ launchOptions: { timeout: 30000 } }) 和 Puppeteer 的 browser.process().kill() 手动回收,比盲目增加并发数更能稳定跑通 50+ 用户模拟。最容易被忽略的是日志输出重定向——所有 page 的 console.log 会混在一起,必须用 page.on('console', msg => console.log(`[Page-${id}]`, msg.text())) 打标。










