karma如何與測試框架合做2之webpack

前文中,咱們探討了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'
    ],
}

這裏咱們把addsub兩個函數經過es6導出了,測試代碼咱們也再也不本身寫karma adapter了,而是用上了你們熟悉的mocha。執行一下npm run test試試,掛了:github

Uncaught SyntaxError: Unexpected token import

回顧上文的內容, karma會把全部karma.config裏files字段裏描述的全部文件都加載到測試頁面裏執行. 也就是說importexport這樣的語法,被直接加載到瀏覽器裏面了,出錯也就不免了。怎麼辦呢?常規方案啊:用webpack把es6編譯成es5,再執行嘛。web

karma-webpack

karmawebpack是經過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的代碼,咱們會發現addsub的代碼都包含在了裏面。一樣瀏覽器中的sub.spec.js的代碼,也會包含addsub的代碼。實際上,karma-wepack會把files裏的每個文件都當作webpack entry去編譯一次,這樣若是咱們有多個測試文件,就會屢次打包,不但測試速度慢了,並且打包可能會重複屢次,以致於包變大。

因此,karma-wepack向咱們推薦使用文章開頭提到的配置方式,就是把全部的測試代碼都經過一個index文件加載起來。這裏利用的是webpack的require.contextcontext 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時對一些細節問題的探索,我把詳細的思考過程記錄在這裏,但願對後來者全部幫助。

相關文章
相關標籤/搜索