测试 Electron 应用
本教程共 45 篇 · 第 37 篇 · 更新于 2026-08-03
37. 测试 Electron 应用
手动点一遍界面来验证功能,既慢又容易漏。自动化测试能让每次改动都被校验。Electron 没有官方维护的测试框架,但社区已形成成熟方案。本章以 Playwright 为主线讲端到端测试,并补充主进程单元测试,最后说明历史工具 Spectron 的归宿。
本节目标
- 用 Playwright 做端到端测试,覆盖主进程与渲染进程。
- 给主进程逻辑写单元测试。
- 理解如何测试
contextBridge暴露的 API 与 IPC。 - 知道 Spectron 已弃用,迁移到 WebdriverIO。
- 权衡不同测试方案的适用场景。
1-1 测试的三个层次
和网页测试类似,Electron 测试分三层。单元测试验证单个函数;集成测试验证模块协作;端到端(e2e)测试模拟真实用户操作整个应用。端到端最能体现「用户能不能用」,但跑得慢、易脆,应搭配少量单元测试。
主进程代码(窗口管理、IPC 处理)适合单元测试;渲染页面与用户交互适合端到端。两者结合才能既快又稳。
1-2 主进程单元测试
主进程本质是 Node.js 代码,用常规测试框架即可。以 vitest 或 jest 为例,直接引入待测模块断言结果:
// mathUtils.js(主进程模块)
function add(a, b) {
return a + b;
}
module.exports = { add };
// mathUtils.test.js
const { add } = require('./mathUtils');
test('add 应返回两数之和', () => {
expect(add(1, 2)).toBe(3);
});
运行 npx vitest。注意主进程测试在纯 Node 环境跑,不要引入依赖 electron 的渲染侧代码,否则会启动整个应用。把「纯逻辑」从「Electron 桥接代码」里抽出来,是让主进程可测的关键。
1-3 端到端测试:Playwright
Playwright 是微软出品的端到端框架,对 Electron 有实验性支持。它在底层用 Chrome DevTools 协议启动你的应用,能操作窗口、读取主进程状态、截屏。
先安装测试运行器:
npm install --save-dev @playwright/test
写一个最小测试。Playwright 用 _electron.launch 拉起开发态应用,参数 args 指向主进程入口(这里是 .):
// example.spec.js
import { test, expect, _electron as electron } from '@playwright/test';
test('应用能启动且未打包', async () => {
const electronApp = await electron.launch({ args: ['.'] });
// 在主进程里读取 app.isPackaged
const isPackaged = await electronApp.evaluate(async ({ app }) => {
return app.isPackaged;
});
expect(isPackaged).toBe(false);
// 抓取第一个窗口并截屏
const window = await electronApp.firstWindow();
await window.screenshot({ path: 'intro.png' });
await electronApp.close();
});
electronApp.evaluate 运行在主进程上下文,参数是 require('electron') 的结果,因此能访问 app、BrowserWindow 等主进程模块。而 firstWindow() 返回的是渲染进程的 Page 对象,可以像测网页一样用 window.click()、window.fill()。
运行测试:
npx playwright test
测试文件需匹配 .*(test|spec)\.(js|ts|mjs) 正则,也原生支持 TypeScript。Playwright 自动处理应用的启动与关闭,无需手写进程管理。
1-4 测试 IPC 与 contextBridge
你的渲染进程通过 preload 的 contextBridge.exposeInMainWorld 调用主进程能力。端到端测试可模拟真实路径:在渲染页触发按钮,验证主进程响应。
假设 preload 暴露了 window.api.getVersion(),测试这样写:
// ipc.spec.js
import { test, expect, _electron as electron } from '@playwright/test';
test('点击按钮能拿到版本号', async () => {
const electronApp = await electron.launch({ args: ['.'] });
const window = await electronApp.firstWindow();
// 渲染进程里的按钮 id 为 #get-version
await window.click('#get-version');
const text = await window.textContent('#version');
expect(text).toMatch(/\d+\.\d+\.\d+/);
await electronApp.close();
});
这样一次测试就穿过了「渲染点击 → IPC → 主进程处理 → 渲染更新」整条链路,价值远高于单独测某一端。
1-5 其他方案与 Spectron 的归宿
除 Playwright 外,还有 WebdriverIO(WDIO),它对 Electron 有一等支持,通过 services: ['electron'] 配置即可;以及基于 electron-chromedriver 的 Selenium 方案。它们思路相近,按团队熟悉度选择。
必须特别提醒:Spectron 已经停止维护。Spectron 曾是 Electron 官方的端到端测试工具,基于 WebDriverIO 封装。如今官方不再维护,Electron 文档明确建议迁移到 WebdriverIO 或 Playwright。新项目不要再引入 Spectron,老项目应规划迁移。
1-6 自定义测试驱动
若你有特殊需求(如跨进程 RPC),也可用 Node.js 的 child_process 自己拉起 Electron,通过 stdio: ['inherit','inherit','inherit','ipc'] 建立消息通道。这种方式开销低、可控性强,但需自己写驱动与协议,适合有经验的团队。绝大多数应用用 Playwright 即可。
1-7 测试策略建议
不要把所有测试都写成端到端。端到端跑得慢、易因 UI 微调而失败,应只占小比例。把可独立验证的逻辑(格式化、计算、状态机)抽成纯函数做单元测试,覆盖率高、速度快。端到端只保关键用户路径,例如「启动后主窗口出现」「点击按钮触发更新」。这样测试套件既快又稳,CI 里几分钟跑完。
常见误区
- 新项目仍用 Spectron。它已停止维护,应迁移到 Playwright 或 WebdriverIO。
- 主进程测试里引入
electron渲染侧代码。会意外启动整个应用,应只测纯逻辑模块。 - 端到端测试过度依赖具体文案。文案一改测试就红,宜用稳定的
id或data-testid定位元素。 - 忽视
app.isPackaged差异。开发态与打包态行为不同,测试需明确自己跑在哪种模式。
1-8 在 CI 中跑测试
本地通过的测试,必须在 CI 里复跑才能保证质量。Playwright 与 WebdriverIO 都可在无显示环境用 xvfb 提供虚拟显示后运行。CI 配置里先 npm ci 安装锁定依赖,再 npx playwright test。为加速,可缓存 node_modules 与浏览器二进制。
注意 CI 的运行环境(无 GPU、可能不同的系统版本)与本地不同,偶尔会出现本地绿、CI 红。此时应让测试对环境因素更鲁棒,例如用显式等待替代固定 sleep,避免因启动稍慢而误判失败。稳定的测试套件是持续交付的底气。
1-9 测试数据的隔离
端到端测试会真实读写应用数据,容易污染用户环境或相互干扰。测试前应重置应用数据目录,或在临时目录运行。Playwright 可在 launch 时传入隔离的 userData 路径,保证每次测试从干净状态开始。测试结束清理临时目录,可避免磁盘堆积与状态串扰。这点在涉及数据库或配置写入的用例上尤为关键,否则一次失败可能污染后续所有用例。
小结
本章你掌握了主进程单元测试与 Playwright 端到端测试,并知道如何验证 IPC 全链路。记住 Spectron 已弃用,新项目选 Playwright 或 WebdriverIO。测试保障正确性,性能则决定用户体验,下一章我们谈性能优化。