前文中,咱们探讨了karma的工做的一些基本过程。可是,我并无说起es6相关的内容, 本文来填这个坑。vue
在现有的karma + webpack项目里,咱们常常看到这样的配置,以vue-webpack生成的代码为例:node
// index.js // require all test files (files that ends with .spec.js) // const testsContext = require.context('./specs/serverVersion/', true, /tableAction.spec$/) // const testsContext = require.context('./specs/clientVersion/', true, /\.spec$/) 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', true, /^\.\/(?!main(\.js)?$)/) srcContext.keys().forEach(srcContext)
虽然有注释,可是在深刻研究以前我一直没有搞明白过,这段代码是什么意思?!!!vue
组件、es6
这些代码又是怎么被加载的呢?下面让咱们慢慢揭秘。webpack
本文代码: https://github.com/njleonzhan...git
咱们把上一篇文章的例子加工一下es6
// src/index.js function add(x, y) { return x + y } function sub(x, y) { return x - y + 1 } export { add, sub }
// test/add.spc.js import {add} from '../src' describe('add suit', _ => { it('test add', done => { add(1, 2).should.equal(3) done() }) })
// test/sub.spc.js import {sub} from '../src' describe('add suit', _ => { it('test sub', done => { sub(5, 2).should.equal(3) done() }) })
// karma.conf.js { files: [ 'test/add.spec.js', 'test/sub.spec.js' ], }
这里咱们把add
和sub
两个函数经过es6导出了,测试代码咱们也再也不本身写karma adapter了,而是用上了你们熟悉的mocha
。执行一下npm run test
试试,挂了:github
Uncaught SyntaxError: Unexpected token import
回顾上文的内容, karma会把全部karma.config里files
字段里描述的全部文件都加载到测试页面里执行. 也就是说import
和export
这样的语法,被直接加载到浏览器里面了,出错也就不免了。怎么办呢?常规方案啊:用webpack
把es6编译成es5,再执行嘛。web
karma
和webpack
是经过karma-webpack
这个karma preprocess
结合在一块儿的。至于什么是preprocess
,顾名思义就是预处理器,在karma加载files
到页面以前,karma会先对files
经过preprocess
进行处理。npm
咱们来配置一下:segmentfault
// karma.conf.js files: [ 'test/add.spec.js', 'test/sub.spec.js' ], // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { 'test/add.spec.js': ['webpack'], 'test/sub.spec.js': ['webpack'] }, webpack: { module: { loaders: [{ test: /\.js$/, exclude: [/node_modules/], loader: "babel-loader" }] } }
咱们用babel-loader
先对测试文件预处理一下。再执行下测试试试:api
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 2 of 2 SUCCESS (0.008 secs / 0.001 secs)
果真成功了。打开浏览器看一下add.spec.js
, 确实是被webpack
处理过
// 浏览器中的add.spec.js /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { ..... /***/ (function(module, exports, __webpack_require__) { "use strict"; var _src = __webpack_require__(1); describe('test suit', function (_) { it('test add', function (done) { (0, _src.add)(1, 2).should.equal(3); done(); }); }); /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function add(x, y) { return x + y; } function sub(x, y) { return x - y; } exports.add = add; exports.sub = sub; /***/ }) /******/ ]);
到这是否是就配置好了呢?固然不是啦,文章开头的提到的index.js
里的代码是什么意思的问题还没解释呢。仔细看一下karma-wepack
的文档Alternative Usage部分:
This configuration is more performant, but you cannot run single test anymore (only the complete suite).
The above configuration generates a webpack bundle for each test. For many testcases this can result in many big files. The alterative configuration creates a single bundle with all testcases.
再细看一下上面中贴出的浏览器中的add.spec.js
的代码,咱们会发现add
和sub
的代码都包含在了里面。一样浏览器中的sub.spec.js
的代码,也会包含add
和sub
的代码。实际上,karma-wepack
会把files
里的每个文件都当作webpack entry去编译一次,这样若是咱们有多个测试文件,就会屡次打包,不但测试速度慢了,并且打包可能会重复屡次,以致于包变大。
因此,karma-wepack
向咱们推荐使用文章开头提到的配置方式,就是把全部的测试代码都经过一个index
文件加载起来。这里利用的是webpack的require.context和context module API,你们自行看一下文档就明白了。
再次优化一下咱们的实例代码,添加一个test/index.js
文件,并修改karma.conf.js
的配置:
// karma.conf.js // list of files / patterns to load in the browser files: [ 'index.js' ], // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { 'index.js': ['webpack'] },
// test/index.js var testsContext = require.context("./test", true, /\.spec$/); testsContext.keys().forEach(testsContext);
再跑一下测试,观察一下,src和test里的代码确实都打到了一个文件里了!!
问题基本上都搞清楚了,可是细心的朋友可能发现了文章开头贴出的代码里,不只仅require了全部的测试代码,还把src
下的代码require了一遍?本例中src
下的代码都都经过import的方式引用了,webpack天然也就把它们打包了。这样对测试覆盖率的统计不会有什么影响。可是,若是咱们给一个库写测试用例,这个库有不少的组件,咱们颇有可能丢掉某个组件忘记写测试用例,这个时候若是咱们不把src
下的代码也加载进来,那么测试覆盖率的统计就会丢掉这部分代码,因此require src
下的代码有时候也是必要的。(这个问题,能够参考require all src files in unit/index.js useless?)
咱们接触计算机的技术的时候,通常都是先用起来,而后再深刻掌握。本文是我我的在使用karma + webpack时对一些细节问题的探索,我把详细的思考过程记录在这里,但愿对后来者全部帮助。