这里我记录下搭建基于 karma+mocha+webpack3+vue2 的测试环境。因为之前折腾了一段时间,发现的坑挺深的,防止后面再次掉进坑里,留个笔记。如果这边文章能解决大家遇到的问题那就更好了?
1、需要安装哪些包
以下列出来的包安装在项目中即可,还有几个包需要全局安装:
babel、mocha、karma
babel 相关的:
- babel-core
- babel-plugin-syntax-jsx // 支持 jsx 语法
- babel-plugin-transform-runtime // 描述太晦涩, 官方文档: https://github.com/babel/babe...
- babel-plugin-transform-vue-jsx // 支持 vue2.x jsx 语法
- babel-preset-env // 可以根据您所支持的环境自动确定您需要的Babel插件和polyfills(.babelrc 配置)
- babel-preset-es2015
- babel-preset-stage-2
- babel-runtime
- babel-polyfill // 支持老版本浏览器
karma、mocha、断言 包
- karma
- mocha
- chai // BDD 、TDD 断言框架
- chalk // 终端里可以给输出内容添加颜色
- karma-mocha
- karma-coverage // 生成代码覆盖率
- karma-phantomjs-launcher // phantomjs 启动器
- karma-phantomjs-shim // 可以支持 phantomjs 默认不支持的功能,如
Object.assign
等... - karma-sinon-chai
- karma-spec-reporter // 终端里输出测试结果
- karma-webpack // karma 支持 webpack 插件,有了它就不会报
找不到requirejs
的错误信息了 - phantomjs-prebuilt // phantomjs 通过 npm 安装的版本
- sinon // 测试辅助工具,提供 spy、stub、mock 三种测试手段,模拟特定场景
- sinon-chai
webpack 相关
- webpack
- babel-loader
- css-loader
- istanbul-instrumenter-loader // 代码覆盖率统计工具
- karma-sourcemap-loader
- style-loader
- url-loader
- vue-loader
- vue-style-loader
- extract-text-webpack-plugin
vue 核心包
- vue
- vue-template-compiler
- vue-router
2、如何配置
上面那么一大坨包安装好了,接下来该配置。配置主要是两个,一是 karma 的配置文件,另一个是 karma 需要的webpack 配置文件。webpack 的配置文件是为了解析那些需要测试的源文件的,说白了就是 vue 相关的文件,然后再给karma 的单元测试用例去识别。
webpack3 配置文件
我是手动创建一个webpack.test.config.js 文件,然后内容配置如下
webpack 相关知识可以参考我之前写的一篇
var path = require("path")
var webpack = require("webpack")
var ExtractTextPlugin = require('extract-text-webpack-plugin')
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
var webpackConfig = {
module: {
rules: [
// babel-loader
{
test: /\.js$/,
use: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
// 为了统计代码覆盖率,对 js 文件加入 istanbul-instrumenter-loader
{
test: /\.(js)$/,
exclude: /node_modules/,
include: /src|packages/,
enforce: 'post',
use: [{
loader: "istanbul-instrumenter-loader",
options: {
esModules: true
},
}]
},
// vue loader
{
test: /\.vue$/,
use: [{
loader: 'vue-loader',
options: {
// 为了统计代码覆盖率,对 vue 文件加入 istanbul-instrumenter-loader
preLoaders: {
js: 'istanbul-instrumenter-loader?esModules=true'
}
}
}]
},
// css loader
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
})
},
// img loader
{
test: /\.(png|gif|jpe?g)(\?\S*)?$/,
use: [{loader: 'url-loader'}]
},
// font loader
{
test: /\.(eot|woff|woff2|ttf|svg)(\?\S*)?$/,
use: [{loader: 'url-loader'}]
},
]
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'), // 调用组件的时候方便点
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
})
]
}
module.exports = webpackConfig
karma配置文件
直接 cd
到你的项目,然后执行下面命令,会提示你是否使用 require.js、浏览器环境、测试脚本存放位置等等。
$ karma init
之后就会生成一个karma.config.js 文件,配置形式我是直接仿照vue-cli 官方的例子:
var webpackConfig = require('../../build/webpack.test.config');
module.exports = function (config) {
config.set({
// to run in additional browsers:
// 1. install corresponding karma launcher
// http://karma-runner.github.io/0.13/config/browsers.html
// 2. add it to the `browsers` array below.
browsers: ['PhantomJS'],
frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
reporters: ['spec', 'coverage'],
files: ['index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpackMiddleware: {
noInfo: true
},
// 不显示 `webpack` 打包日志信息
webpackServer: {
noInfo: true
},
webpack: webpackConfig,
coverageReporter: {
dir: './coverage',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' }
]
}
})
}
3、搭建目录结构
├─build
│ webpack.test.config.js
│
├─src
│
├─package.json
│
└─test
└─unit
│ index.js
│ karma.config.js
│
├─coverage
│
└─specs
*.spec.js
测试文件相关都放置在 test/unit 下,入口文件为 index.js,每个vue 组件对应的测试用例名为组件名称.spec.js
,根据 istanbul-instrumenter-loader
文档的说明,测试总入口文件 index.js 内容如下:
import Vue from 'vue'
Vue.config.productionTip = false
// 测试所有以 .spec.js 名称结尾的文件
// require all test files (files that ends with .spec.js)
const testsContext = require.context('./specs', true, /\.spec$/)
testsContext.keys().forEach(testsContext)
// 要求除main.js之外的所有src文件进行覆盖
// 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)
4、简单的 vue 组件单元测试
我们在 src 目录下创建一个 Hello.vue
组件
msg
然后在 test/unit/specs 下创建一个 Hello.spec.js
文件,再写个简单的单元测试用例:
import Vue from 'vue'
import Hello from '@/components/Hello'
describe('Hello.vue', () => {
it('should render correct contents', () => {
const Constructor = Vue.extend(Hello)
const vm = new Constructor().$mount()
expect(vm.$el.querySelector('.hello h1').textContent)
.to.equal('Welcome to Your Vue.js App')
})
})
5、测试输出
在 package.json 中配置命令:
// package.json
"scripts": {
"test": "karma start test/unit/karma.config.js --single-run"
}
输出结果:
同时在 test/unit/coverage 生成测试报告。以上就是一个简单的 vue 单元测试实例。最后奉上源代码
首发于我的个人博客