pikabo - 一个可以自动化浏览器插件测试的工具
做浏览器扩展的日常循环大概是这样:改一行代码 → `chrome://extensions` 点刷新 → 点开弹窗 → 再点进选项页 → 同时盯三个 DevTools 窗口看有没有报错。我自己维护几个扩展,这套流程走了几年,一直没写自动化测试——不是懒,是常规工具够不着扩展真正会坏的地方。
**Playwright / Puppeteer 驱动的是「页面」,而扩展大部分不是页面:**
- 点图标弹出来的那个弹窗属于浏览器 UI,不在自动化能寻址的页面树里,选择器写得再巧也点不到;
- MV3 的后台是 Service Worker,没有 tab、没有 DOM、没有 window,`page.evaluate()` 没有附着点,而且它空闲就被回收;
- 内容脚本和页面共享 DOM 但 JS 上下文隔离,在页面里读它设的变量拿到的是 `undefined`。
以前的办法是 `--load-extension` 启动浏览器再驱动。Chrome 137 把这个开关从 Chrome 品牌版本里删了(理由也算合理,这参数长期被拿来静默装恶意扩展)。但公告里关键的一句是:**该变更只作用于 Chrome 品牌版本,Chromium、Chrome for Testing 照常工作。** 所以门没焊死,只是官方 Chrome 关了。
顺带说两个实测结论,省得有人踩:
- 网上说加 `--disable-features=DisableLoadExtensionCommandLineSwitch` 能强行恢复的,别信。Chrome 150.0.7871.187 上加不加都装不上,`--enable-unsafe-extension-debugging` 也不管用。
- **Edge 可以**,它是微软品牌的 Chromium,没继承这条限制,`--browser-channel msedge`,CI 里 Linux/Windows 都跑通了。
### 于是有了 pikabo
一句话:`manifest.json` 里其实已经写好半套测试了。弹窗、选项页、内容脚本的匹配规则、有没有 Service Worker——这些都是声明好的,足够推导出一套真能跑的冒烟测试。
```
npx pikabo explore --ext ./my-extension
```
它读 manifest,在真实 Chromium 里把每个声明的界面打开,检查弹窗是不是渲染出了实际内容(而不是一个空壳),按内容脚本的匹配规则访问对应网址确认注入成功,再断言 Worker 干净启动。生成的 YAML 套件落盘,你可以接着改,不是黑盒。
```
my-extension smoke tests
✓ service worker starts without errors 12ms
✓ popup renders 431ms
✓ options page renders 318ms
✓ content script injects on github.com 772ms
4 passed · 3.8s
```
一行手写测试都没有。
### 我自己最受用的一个功能
MV3 Service Worker 的控制台,只在你打开它的 Inspector 期间才存在,Chrome 不替你缓冲。所以后台脚本第一行就抛异常(拼错变量名、少 import、用了没声明权限的 API),你看到的是一个空白弹窗,页面控制台干干净净,完全意识不到出过事——Worker 在你开始看之前就已经死了。
pikabo 的做法是在 Worker 启动**之前**通过 DevTools 协议挂上去,等它抛的时候缓冲区已经在收:
```
✗ service worker starts without errors
assertNoConsoleErrors: 2 console error(s):
[worker] ReferenceError: initialise is not defined
at chrome-extension://abc…/background.js:4:1
```
文件行号都在,而这个脚本根本没活到能给你打印一次堆栈。
### 其他
- **按名字寻址每个界面。** `in: worker` 在 Service Worker 里执行(`chrome.storage`、`chrome.runtime` 都在那),`in: popup` 把弹窗当真实文档,还有 `sidepanel`、`devtools`、`offscreen`、MV2 的 `background`。
- **权限审计。** 对比代码实际碰过的 `chrome.*` 命名空间和 manifest 声明。声明了没用到的容易卡商店审核;反过来「用了没声明」更糟,正式安装里那个命名空间就是 `undefined`,只对用户报错不对你报错。报告写的是 not observed 而不是 unused——只开过弹窗的套件证明不了什么,这个区别我在文档里专门说了。
- **导出文件校验。** `assertPdf` 直接读文件:页数、页面尺寸、体积、生成器。Worker 里调 `chrome.downloads.download()` 产生的下载也抓得到,这种全程没有页面事件。
- **已有 Playwright 套件不用重写**,给自己的 `test` 加几个 fixture 就行,locator/断言/重试/reporter 全保留。
- 还有 `record` 录制、HTML 报告(截图内联,可以直接丢进 issue)、MCP server 和 agent skill。
### 做不到的也说清楚
只支持未打包目录,不支持商店装的 `.crx`。浏览器自身 UI(工具栏图标菜单、拼图溢出菜单、原生权限弹窗)点不了,不过这些界面能触发的功能都能从弹窗文档、选项页或 Worker 走到。`manifest.commands` 里的快捷键没法作为真实按键发送,得通过 Worker 派发处理函数。需要 Node 22+(20/21 没有全局 `WebSocket`,Worker 控制台捕获依赖它)。
MIT,0.1.0,刚发出来不久,能用但肯定还有坑。
[项目地址](https://github.com/sonic0002/pikabo)
npm 上包名就是 `pikabo`。如果你也在维护扩展、一直因为没趁手工具把测试往后拖,这个补的正好是那块;有跑不通的场景欢迎来提 issue。
---
原文链接:[点击查看](https://www.v2ex.com/t/1235461)
**Playwright / Puppeteer 驱动的是「页面」,而扩展大部分不是页面:**
- 点图标弹出来的那个弹窗属于浏览器 UI,不在自动化能寻址的页面树里,选择器写得再巧也点不到;
- MV3 的后台是 Service Worker,没有 tab、没有 DOM、没有 window,`page.evaluate()` 没有附着点,而且它空闲就被回收;
- 内容脚本和页面共享 DOM 但 JS 上下文隔离,在页面里读它设的变量拿到的是 `undefined`。
以前的办法是 `--load-extension` 启动浏览器再驱动。Chrome 137 把这个开关从 Chrome 品牌版本里删了(理由也算合理,这参数长期被拿来静默装恶意扩展)。但公告里关键的一句是:**该变更只作用于 Chrome 品牌版本,Chromium、Chrome for Testing 照常工作。** 所以门没焊死,只是官方 Chrome 关了。
顺带说两个实测结论,省得有人踩:
- 网上说加 `--disable-features=DisableLoadExtensionCommandLineSwitch` 能强行恢复的,别信。Chrome 150.0.7871.187 上加不加都装不上,`--enable-unsafe-extension-debugging` 也不管用。
- **Edge 可以**,它是微软品牌的 Chromium,没继承这条限制,`--browser-channel msedge`,CI 里 Linux/Windows 都跑通了。
### 于是有了 pikabo
一句话:`manifest.json` 里其实已经写好半套测试了。弹窗、选项页、内容脚本的匹配规则、有没有 Service Worker——这些都是声明好的,足够推导出一套真能跑的冒烟测试。
```
npx pikabo explore --ext ./my-extension
```
它读 manifest,在真实 Chromium 里把每个声明的界面打开,检查弹窗是不是渲染出了实际内容(而不是一个空壳),按内容脚本的匹配规则访问对应网址确认注入成功,再断言 Worker 干净启动。生成的 YAML 套件落盘,你可以接着改,不是黑盒。
```
my-extension smoke tests
✓ service worker starts without errors 12ms
✓ popup renders 431ms
✓ options page renders 318ms
✓ content script injects on github.com 772ms
4 passed · 3.8s
```
一行手写测试都没有。
### 我自己最受用的一个功能
MV3 Service Worker 的控制台,只在你打开它的 Inspector 期间才存在,Chrome 不替你缓冲。所以后台脚本第一行就抛异常(拼错变量名、少 import、用了没声明权限的 API),你看到的是一个空白弹窗,页面控制台干干净净,完全意识不到出过事——Worker 在你开始看之前就已经死了。
pikabo 的做法是在 Worker 启动**之前**通过 DevTools 协议挂上去,等它抛的时候缓冲区已经在收:
```
✗ service worker starts without errors
assertNoConsoleErrors: 2 console error(s):
[worker] ReferenceError: initialise is not defined
at chrome-extension://abc…/background.js:4:1
```
文件行号都在,而这个脚本根本没活到能给你打印一次堆栈。
### 其他
- **按名字寻址每个界面。** `in: worker` 在 Service Worker 里执行(`chrome.storage`、`chrome.runtime` 都在那),`in: popup` 把弹窗当真实文档,还有 `sidepanel`、`devtools`、`offscreen`、MV2 的 `background`。
- **权限审计。** 对比代码实际碰过的 `chrome.*` 命名空间和 manifest 声明。声明了没用到的容易卡商店审核;反过来「用了没声明」更糟,正式安装里那个命名空间就是 `undefined`,只对用户报错不对你报错。报告写的是 not observed 而不是 unused——只开过弹窗的套件证明不了什么,这个区别我在文档里专门说了。
- **导出文件校验。** `assertPdf` 直接读文件:页数、页面尺寸、体积、生成器。Worker 里调 `chrome.downloads.download()` 产生的下载也抓得到,这种全程没有页面事件。
- **已有 Playwright 套件不用重写**,给自己的 `test` 加几个 fixture 就行,locator/断言/重试/reporter 全保留。
- 还有 `record` 录制、HTML 报告(截图内联,可以直接丢进 issue)、MCP server 和 agent skill。
### 做不到的也说清楚
只支持未打包目录,不支持商店装的 `.crx`。浏览器自身 UI(工具栏图标菜单、拼图溢出菜单、原生权限弹窗)点不了,不过这些界面能触发的功能都能从弹窗文档、选项页或 Worker 走到。`manifest.commands` 里的快捷键没法作为真实按键发送,得通过 Worker 派发处理函数。需要 Node 22+(20/21 没有全局 `WebSocket`,Worker 控制台捕获依赖它)。
MIT,0.1.0,刚发出来不久,能用但肯定还有坑。
[项目地址](https://github.com/sonic0002/pikabo)
npm 上包名就是 `pikabo`。如果你也在维护扩展、一直因为没趁手工具把测试往后拖,这个补的正好是那块;有跑不通的场景欢迎来提 issue。
---
原文链接:[点击查看](https://www.v2ex.com/t/1235461)
评论
暂无评论。