搭建现代的 Karma 测试环境

也能够在这里看:https://leozdgao.me/modern-karma/前端

以前写过的测试都是针对简单的工具方法,用的 mocha + chai 写,最近在研究前端路由,想写写测试代码,遇到 window.location,忽然意识到先后端的差别问题,须要一个浏览器环境,因而想到以前用过的 Karma + phamtonjs 环境,搭的过程当中遇到一些坑,由于涉及到了 Babel 和 commonjs 模块系统,因而这里记录分享下。node

开始搭环境

因为 Karma 只是一个 Test Runner,我们的测试框架和断言库仍是须要的,因而先装这些东西:webpack

> npm install --save-dev karma karma-mocha karma-chai

对于 npm 版本 >=3.0 的话,这几个 peerDependencies:web

> npm install --save-dev mocha chai

这些装完后,利用 karma-cli 来初始化一份配置文件:shell

> ./node_modules/.bin/karma init

按照提示填写配置便可,完成后生成一份 karma.config.js,把里面 singleRun 设成 false,结束。npm

接下来给 Karma 准备 Browsers 了,我这里选择 PhantomJS(在上面初始化 Karma 配置的时候就能够选了),不过这东西的安装过程是真的纠结:后端

> npm install --save-dev karma-phantomjs-launcher phantomjs-prebuilt

在安装的过程当中,发现 PhantomJS 须要从 https://bitbucket.org/ariya/phantomjs/downloads/ 下载,速度很是慢,反正我是没有成功下载下来过。好在有淘宝镜像,哈哈,太棒了!cnode 帖子的连接在这里浏览器

> PHANTOMJS_CDNURL=https://npm.taobao.org/dist/phantomjs npm install phantomjs-prebuilt --registry=https://registry.npm.taobao.org --no-proxy

而后贴出一部分配置:babel

module.exports = function (config) {
  config.set({
    basePath: './',
    frameworks: [ 'mocha', 'chai' ],
    files: [
      'src/**/*.js',
      'test/**/*.js'
    ],
    plugins: [
      'karma-mocha',
      'karma-chai',
      'karma-mocha-reporter',
      'karma-phantomjs-launcher'
    ],
    reporters: [ 'mocha' ],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: [ 'PhantomJS' ],
    singleRun: true,
    concurrency: Infinity
  })
}

这些顺利安装完后,而且你的配置文件正确配置的状况下,理应是能够跑了,然而我如今的工做流已经深度依赖于 Babel + commonjs 模块系统,因此若是你和我同样的话,那么咱们的环境还没搭好。框架

Babel 加入

这边我用的 Babel 版本是 v6.0+,根据 Babel 官网 说的:

> npm install --save-dev karma-babel-preprocessor

并在配置里添加预处理配置:

plugins: [
  ...
  'karma-babel-preprocessor',
  ...
],
preprocessors: {
  "src/**/*.js": [ "babel" ],
  "test/**/*.js": [ "babel" ]
},

然而即使是这样也仍是不行,考虑到 Babel 是将 ES6 的模块系统转换为 commonjs 的模块系统,而 Karma 是直接把匹配到的脚本放在浏览器环境里跑的,浏览器环境里确定没有 requiremodule.exports 这种东西,因此在看了几个例子以后,发现还须要 karma-commonjs 这个东西。

> npm install --save-dev karma-commonjs

完整的配置文件以下:

module.exports = function(config) {
  config.set({
    basePath: './',
    frameworks: [ 'mocha', 'chai', 'commonjs' ],
    files: [
      'src/**/*.js',
      'test/**/*.js'
    ],
    exclude: [
    ],
    preprocessors: {
      'src/**/*.js': [ 'babel', 'commonjs' ],
      'test/**/*.js': [ 'babel', 'commonjs' ]
    },
    plugins: [
      'karma-mocha',
      'karma-chai',
      'karma-mocha-reporter',
      'karma-commonjs',
      'karma-babel-preprocessor',
      'karma-phantomjs-launcher'
    ],
    reporters: [ 'mocha' ],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: [ 'PhantomJS' ],
    singleRun: true,
    concurrency: Infinity
  })
}

好了,如今只须要在 npm scripts 里加上一条:

scripts: {
  test: 'karma start'
}

Webpack 加入

上面的 karma-commonjs 有个问题,它只能加载配置里 files 选项匹配的模块,这一点很不方便,因而想到 webpack 是否能够和 karma 协同工做,果真是有的,因而找我最终使用了这个方式。

> npm install --save-dev karma-webpack

karma-webpack 提供了两种方式加载测试文件,配置以下:

files: [
  'test/*_test.js',
  'test/**/*_test.js'
],
preprocessors: {
  'test/*_test.js': ['webpack'],
  'test/**/*_test.js': ['webpack']
},
webpack: {
  module: {
    loaders: [
      { test: /\.js$/, exclude: /node_modules/, loader: 'babel' }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('test')
    })
  ]
}

此时,被加入 files 配置匹配的文件都被认为是入口点(entry),并加上 webpack 的预处理配置便可(有了 webpack 结合 commonjs 的模块系统,就不须要手动加入项目源码了,仅引入测试代码就行)。不过下面这种方式更加简单,只须要一个文件:

// tests.webpack.js
// require all modules ending in ".spec.js" from the
// current directory and all subdirectories
var testsContext = require.context("./test", true, /\.spec\.js$/)
testsContext.keys().forEach(testsContext)

本质上就是把全部匹配到的文件都 require 一遍,好比我上面就把全部 test 文件夹下的 .spec.js 结尾的文件都跑了一遍,Karma 的配置也稍微精简了点。

files: [
  'tests.webpack.js'
],
preprocessors: {
  'tests.webpack.js': [ 'webpack' ]
},
webpack: {
  module: {
    loaders: [
      { test: /\.js$/, exclude: /node_modules/, loader: 'babel' }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('test')
    })
  ]
}

项目若是比较大,代码量较多的时候,webpack 打包会比较慢(对于打开 watch 选项的同窗,可能会比较崩溃),你们本身取舍吧。

最后

大功告成,这里推荐你们写个 yo generator 来减小重复工做,以前写过 一篇文章 来介绍。

好了,结束,水文一篇,不过仍是但愿对你们有帮助。 :)

相关文章
相关标签/搜索