拓冰建站拓冰建站
首页 / 资讯中心 / 正文

electron-vue 测试体系完全指南:Karma + Mocha 单元测试与 Spectron 端到端测试实战

electron-vue 测试体系完全指南Karma Mocha 单元测试与 Spectron 端到端测试实战【免费下载链接】electron-vueAn Electron Vue.js quick start boilerplate with vue-cli scaffolding, common Vue plugins, electron-packager/electron-builder, unit/e2e testing, vue-devtools, and webpack.项目地址: https://gitcode.com/gh_mirrors/el/electron-vue导读本篇指南以 electron-vue 官方文档《测试》为核心系统讲解脚手架内置的两套测试体系基于 Karma Mocha 的 renderer 进程单元测试以及基于 Spectron Mocha 的端到端测试。读完本文你将掌握从npm run unit、npm run e2e到npm test的完整命令链理解test/unit与test/e2e目录结构中每个文件的职责并能结合仓库源码读懂 Karma 配置、Webpack 测试打包、Chai 全局断言与 CI 集成的底层原理最终在真实项目中独立编写与接入测试。electron-vue 为什么内置测试体系electron-vue 是一套基于 vue-cli 脚手架的 Electron Vue.js 快速启动样板工程其测试能力深受官方样板vuejs-templates/webpack的启发。在 template/package.json 的模板中可以看到测试相关依赖全部通过{{#if unit}}、{{#if e2e}}、{{#testing unit e2e}}等条件编译块按需注入也就是说在vue-cli交互式脚手架阶段你可以自行选择是否包含测试选择单元测试unit时会注入karma、karma-mocha、karma-chai、karma-webpack、karma-coverage、karma-electron、inject-loader等依赖见 template/package.json选择端到端测试e2e时会注入spectron、require-dir见 template/package.json只要选中了任一测试就会注入mocha、chai、babel-plugin-istanbul作为共享测试框架见 template/package.json。脚手架生成的package.json中测试命令与构建命令被串联为完整的脚本链见 template/package.jsone2e: npm run pack mocha test/e2e, test: npm run unit npm run e2e, unit: karma start test/unit/karma.conf.js, pack: npm run pack:main npm run pack:renderer这套脚本链揭示了 electron-vue 的测试设计哲学单元测试直接针对源码运行端到端测试则必须先打包出产品构建再让 Spectron 启动真实的应用进行黑盒验证。单元测试Karma Mocha 驱动 renderer 进程运行方式单元测试的入口是一条命令npm run unit底层执行的是karma start test/unit/karma.conf.js见 template/package.json即启动 Karma 并以项目内的 karma 配置文件运行。Karma 是测试运行器负责启动浏览器/宿主环境、调度用例执行与收集结果Mocha 是测试框架负责组织describe/it结构与断言Chai 提供断言 API。技术选型与集成原理electron-vue 单元测试的核心组合是Karma测试运行器负责管理测试环境与进程Mocha Chai测试框架与断言库通过karma-mocha与karma-chai两个适配器接入 Karmakarma-webpack karma-electron前者负责用 Webpack 打包测试代码后者让 Karma 直接运行在 Electron 渲染进程环境里而非浏览器这正是renderer 进程单元测试的由来。由于karma-chai的接入Chai 的所有 API如expect、should、assert都可以在测试文件中全局直接使用无需显式import。这在测试代码中有直观体现——template/test/unit/specs/LandingPage.spec.js 中直接使用了expectimport Vue from vue import LandingPage from /components/LandingPage describe(LandingPage.vue, () { it(should render correct contents, () { const vm new Vue({ el: document.createElement(div), render: h h(LandingPage) }).$mount() expect(vm.$el.querySelector(.title).textContent).to.contain(Welcome to your new project!) }) })这段模板测试展示了 Vue 组件单元测试的标准姿势通过new Vue(...)手动实例化组件并$mount()到内存中的div再对渲染出的 DOM 文本做断言。文件结构脚手架生成的test/unit目录结构如下my-project ├─ test │ ├─ unit │ │ ├─ specs/ │ │ ├─ index.js │ │ └─ karma.conf.js文档特别强调在大多数情况下可以忽略index.js和karma.conf.js只专注于编写specs/目录下的测试用例。三个文件的职责分工为specs/实际编写测试代码的地方。由于 karma-webpack 会将测试文件交由 Webpack 打包处理你可以完全依照 ES2015 语法以及 Webpack 支持的加载器loader来编写包括使用/等别名引入组件见 template/test/unit/specs/LandingPage.spec.js。index.jskarma-webpack使用的入口文件其目的是一次性收集加载所有的测试文件和源码见 template/test/unit/index.jsimport Vue from vue Vue.config.devtools false Vue.config.productionTip false // require all test files (files that ends with .spec.js) const testsContext require.context(./specs, true, /\.spec$/) testsContext.keys().forEach(testsContext) // require all src files except main.js for coverage. // you can also change this to match only the subset of files that // you want coverage for. const srcContext require.context(../../src/renderer, true, /^\.\/(?!main(\.js)?$)/) srcContext.keys().forEach(srcContext)这里使用了 Webpack 的require.context能力第一个上下文把./specs下所有以.spec结尾的文件递归加载进来作为测试用例第二个上下文把src/renderer下除main.js外的所有源码加载进来——这正是覆盖率统计的数据来源。注释还提示你可以调整正则只对关心的文件子集收集覆盖率。karma.conf.jsKarma 的实际配置文件见 template/test/unit/karma.conf.js与模板源码结合可拆解为以下几层Webpack 配置合并。Karma 配置基于.electron-vue/webpack.renderer.config合并出测试专用配置const baseConfig require(../../.electron-vue/webpack.renderer.config) const projectRoot path.resolve(__dirname, ../../src/renderer) // Set BABEL_ENV to use proper preset config process.env.BABEL_ENV test let webpackConfig merge(baseConfig, { devtool: #inline-source-map, plugins: [ new webpack.DefinePlugin({ process.env.NODE_ENV: testing }) ] }) // dont treat dependencies as externals delete webpackConfig.entry delete webpackConfig.externals delete webpackConfig.output.libraryTarget // apply vue option to apply isparta-loader on js webpackConfig.module.rules .find(rule rule.use.loader vue-loader).use.options.loaders.js babel-loader关键点在于delete webpackConfig.entry和delete webpackConfig.externals移除了生产构建的入口与外部依赖声明使 Webpack 能够从 Karma 的入口文件出发完整打包测试代码及其依赖BABEL_ENVtest让 Babel 使用测试环境预设NODE_ENV被定义为testing与生产环境的production、开发环境的development相区分便于代码在测试分支下做针对性处理。Karma 运行时配置。核心段落在config.set({...})中config.set({ browsers: [visibleElectron], client: { useIframe: false }, coverageReporter: { dir: ./coverage, reporters: [ { type: lcov, subdir: . }, { type: text-summary } ] }, customLaunchers: { visibleElectron: { base: Electron, flags: [--show] } }, frameworks: [mocha, chai], files: [./index.js], preprocessors: { ./index.js: [webpack, sourcemap] }, reporters: [spec, coverage], singleRun: true, webpack: webpackConfig, webpackMiddleware: { noInfo: true } })逐项解读frameworks: [mocha, chai]注册 Mocha 与 Chai 适配器实现全局断言 APIfiles: [./index.js]preprocessors把入口文件交给webpack与sourcemap预处理singleRun: true表示测试结束后自动退出 Karma 进程适合 CIcustomLaunchers.visibleElectron基于karma-electron的Electron启动器定制flags: [--show]会在测试时显示 Electron 窗口便于调试client.useIframe: falseKarma 测试页面不用 iframe 承载而是直接在主窗口上下文中运行这是karma-electron的推荐配置coverageReporter输出lcov格式覆盖率报告到./coverage目录同时以text-summary在终端汇总显示reporters: [spec, coverage]使用karma-spec-reporter输出可读的用例明细并叠加覆盖率报告。依赖 Mock 与inject-loaderelectron-vue 默认安装了inject-loader用于对模块依赖进行注入式 Mock。其典型场景是当组件依赖某个服务模块如 API 请求层时测试中可以通过 inject-loader 注入替身实现隔离外部副作用。由于它与 Vue 单文件组件.vue的配合方式与vue-loader的加载流程相关具体用法可参考 vue-loader 的测试与仿真Testing with Mocks文档——核心思路是把组件源码中import的模块替换为测试替身从而专注验证组件自身逻辑。端到端测试Spectron Mocha 驱动真实应用运行方式与前置条件端到端测试的命令是npm run e2e它实际执行的是npm run pack mocha test/e2e见 template/package.json。这里有一个重要的前置条件在运行端到端测试之前必须调用npm run pack来创建一个产品构建——因为 Spectron 需要以dist/electron/main.js作为应用入口来启动完整的 Electron 应用。pack命令内部又会依次执行pack:main与pack:renderer分别用 Webpack 生产模式打包主进程与渲染进程见 template/package.json。文件结构脚手架生成的test/e2e目录结构如下my-project ├─ test │ ├─ e2e │ │ ├─ specs/ │ │ ├─ index.js │ │ └─ utils.js同样地大多数情况下只需关注specs/。三个文件的职责为specs/编写实际端到端测试用例的地方。由于babel-register的支持测试文件可以使用完整的 ES2015 语法见 template/test/e2e/specs/Launch.spec.jsimport utils from ../utils describe(Launch, function () { beforeEach(utils.beforeEach) afterEach(utils.afterEach) it(shows the proper application title, function () { return this.app.client.getTitle() .then(title { expect(title).to.equal({{ name }}) }) }) })这是脚手架自带的第一个端到端用例启动应用后通过 WebDriverIO 的getTitle()获取窗口标题断言其与应用名一致模板中{{ name }}会在脚手架时替换为真实项目名。index.jsMocha 的入口文件负责收集加载specs/内的所有测试见 template/test/e2e/index.jsuse strict // Set BABEL_ENV to use proper env config process.env.BABEL_ENV test // Enable use of ES6 on required files require(babel-register)({ ignore: /node_modules/ }) // Attach Chai APIs to global scope const { expect, should, assert } require(chai) global.expect expect global.should should global.assert assert // Require all JS files in ./specs for Mocha to consume require(require-dir)(./specs)它与单元测试的index.js在机制上有所不同这里不是用 Webpack 打包而是通过babel-register在 Node 进程中实时转译 ES2015并通过require-dir把specs/下的全部测试文件装载给 Mocha。同时它把 Chai 的expect、should、assert三个 API显式挂载到全局作用域这就是端到端测试中这些断言 API 全局可用的原因。utils.js提供specs/中通用的生命周期工具函数核心是封装 Electron 应用的创建与销毁见 template/test/e2e/utils.jsimport electron from electron import { Application } from spectron export default { afterEach () { this.timeout(10000) if (this.app this.app.isRunning()) { return this.app.stop() } }, beforeEach () { this.timeout(10000) this.app new Application({ path: electron, args: [dist/electron/main.js], startTimeout: 10000, waitTimeout: 10000 }) return this.app.start() } }可以看到beforeEach创建 Spectron 的Application实例path指向 Electron 可执行文件args传入打包产物dist/electron/main.js作为应用入口然后调用this.app.start()启动应用afterEach在用例结束后检测应用是否仍在运行若在运行则调用this.app.stop()关闭应用避免进程残留startTimeout与waitTimeout均设置为 10000ms控制应用启动与元素等待的超时阈值。Spectron 的工作原理Spectron 是 Electron 官方的端到端测试框架其底层架构是通过ChromeDriver驱动 Electron 内的 Chromium 引擎并通过WebDriverIO提供的客户端 API 来操作 DOM 元素、窗口和应用状态。WebDriverIO API 的使用如 Spectron 官方文档所述你可以通过this.app.client访问完整的 WebDriverIO API例如getTitle()、click()、getText()、waitForVisible()等用于模拟用户操作并断言应用行为。this.app.client返回的是 Promise 链式接口所以测试中通常写成return this.app.client.getTitle() .then(title { ... })一个关键的 Mocha 注意事项慎用箭头函数由于 electron-vue 的 e2e 测试运行在 Mocha 中this会在beforeEach、afterEach和it之间共享——这正是utils.js能把app挂在this上、而Launch.spec.js能在用例中通过this.app.client取到它的原因。因此文档特别强调ES2015 的箭头函数arrow function在某些情况下不能使用因为箭头函数会覆盖this的语境lexicalthis导致this.app指向错误。这也是模板中describe与it的回调全部使用普通function () {}写法见 template/test/e2e/specs/Launch.spec.js而不是箭头函数的原因。在编写自己的 e2e 用例时务必沿用这一约定单元测试由于不依赖this共享状态使用箭头函数则没有问题参见 template/test/unit/specs/LandingPage.spec.js。一键运行所有测试当你同时选择了单元测试与端到端测试时可以使用单条命令串联运行npm test其等价于见 template/package.json 中的模板逻辑npm run unit npm run e2e注意的含义只有单元测试全部通过才会继续执行端到端测试。由于npm run e2e内部已包含npm run pack环节这条命令链会自动完成打包 → 单元测试 → 端到端测试的完整流程。CI 集成在 Travis CI 与 AppVeyor 上跑测试原理与适用范围如果在脚手架阶段选择了electron-builder作为构建工具那么你的项目可以在Travis CI构建linux与darwin/macOS和AppVeyor构建win32上轻松完成跨平台测试。在脚手架生成的.travis.yml与appveyor.yml中测试部分默认是被注释掉的你可以快速取消注释以启用测试。以仓库中自带的 template/appveyor.yml 为例version: 0.1.{build} branches: only: - master image: Visual Studio 2017 platform: - x64 cache: - node_modules - %APPDATA%\npm-cache - %USERPROFILE%\.electron - %USERPROFILE%\AppData\Local\Yarn\cache init: - git config --global core.autocrlf input install: - ps: Install-Product node 8 x64 - git reset --hard HEAD - yarn - node --version build_script: #- yarn test - yarn build test: off可以看到模板第 14 行的注释块会根据你是否选择了测试来包裹配置而build_script中被注释的#- yarn test就是预留的 CI 测试开关——取消注释即可让 AppVeyor 在构建前先运行整套测试。cache段对node_modules、npm 缓存、Electron 二进制缓存做了加速处理值得在真实 CI 配置中保留。启用 CI 测试的完整步骤结合 docs/cn/using-electron-builder.md 中使用 CI 的自动化部署一节的说明完整启用流程如下在 Travis CI 或 AppVeyor 上创建账户并添加你的仓库在 GitHub 的 Settings → Developer settings → Personal access tokens 中生成一个 token同一个 token 可同时用于 Travis CI 与 AppVeyor在 Travis CI 或 AppVeyor 的仓库设置中添加环境变量Environment Variable如GH_TOKEN取消.travis.yml/appveyor.yml中被注释的测试命令推送代码到master分支触发构建。CI 服务默认监听master分支的推送推送后它们会克隆仓库并在干净环境中依次执行安装依赖、跑测试启用后、构建应用的流程在部署场景下electron-builder读取到GH_TOKEN环境变量后还会把构建产物上传为 GitHub 发布草稿供人工编辑后发布。常见问题与实战建议单元测试与端到端测试如何取舍两条测试线的定位互补单元测试npm run unit速度快、粒度细直接运行在 Electron 渲染进程的测试环境里适合对 Vue 组件、工具函数、Vuex store 模块做纯逻辑验证端到端测试npm run e2e代价高但覆盖面完整启动真实 Electron 应用适合验证应用启动、窗口标题、路由跳转、关键用户流程等整体行为。从 template/test/unit/specs/LandingPage.spec.js 与 template/test/e2e/specs/Launch.spec.js 两个模板用例可以直观看出差异前者直接实例化 Vue 组件并断言渲染文本后者则启动完整应用并读取真实窗口标题。覆盖率数据的来源与定制单元测试的覆盖率来自karma.conf.js中babel-plugin-istanbul与karma-coverage的配合见 template/package.json 与 template/test/unit/karma.conf.js。index.js中require.context(../../src/renderer, ...)决定了哪些源码计入覆盖率你可以通过修改这个正则来缩小或扩大统计范围。报告输出在./coverage目录lcov 格式和终端text-summary 格式。测试环境变量约定整个测试体系中有一个贯穿始终的环境变量约定BABEL_ENV在单元测试配置见 template/test/unit/karma.conf.js与端到端入口见 template/test/e2e/index.js中均被设为test用于让 Babel 加载测试专用的 preset 配置同时单元测试通过DefinePlugin将process.env.NODE_ENV定义为testing。在编写组件代码时可以依据这些约定为测试环境准备专门的初始化逻辑而不会污染生产构建。小结electron-vue 的测试体系由三条命令构成完整闭环npm run unitKarma Mocha Chai 驱动 renderer 进程单元测试、npm run e2eSpectron Mocha 驱动真实应用端到端测试内部自动先npm run pack、npm testunit e2e串联全量回归。其工程化核心在于test/unit借助 karma-webpack 复用渲染进程的 Webpack 配置并实现覆盖率统计test/e2e借助 babel-register require-dir 收集用例并通过utils.js统一管理 Spectron 应用生命周期。启用测试后还可以在.travis.yml与appveyor.yml中取消注释相关配置把测试接入跨平台 CI 流水线。更多细节可进一步阅读仓库中的相关文档单元测试、端到端测试 与 使用 electron-builder并结合脚手架模板 template/test/unit 与 template/test/e2e 中的真实代码加深理解。【免费下载链接】electron-vueAn Electron Vue.js quick start boilerplate with vue-cli scaffolding, common Vue plugins, electron-packager/electron-builder, unit/e2e testing, vue-devtools, and webpack.项目地址: https://gitcode.com/gh_mirrors/el/electron-vue创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门