Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

karma+mocha+webpack3 搭建 vue2 单元测试环境 #2

Open
huangshuwei opened this issue Sep 9, 2017 · 2 comments
Open

karma+mocha+webpack3 搭建 vue2 单元测试环境 #2

huangshuwei opened this issue Sep 9, 2017 · 2 comments

Comments

@huangshuwei
Copy link
Owner

huangshuwei commented Sep 9, 2017

这里我记录下搭建基于 karma+mocha+webpack3+vue2 的测试环境。因为之前折腾了一段时间,发现的坑挺深的,防止后面再次掉进坑里,留个笔记。如果这边文章能解决大家遇到的问题那就更好了😉

1、需要安装哪些包

以下列出来的包安装在项目中即可,还有几个包需要全局安装:
babel、mocha、karma

babel 相关的:

  • babel-core

  • babel-plugin-syntax-jsx // 支持 jsx 语法

  • babel-plugin-transform-runtime // 描述太晦涩, 官方文档: https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-runtime

  • 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 组件

<template>
   <div>msg</div>
</template>
<script>
export default {
  name: 'hello',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

然后在 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"
  }

输出结果:
2

同时在 test/unit/coverage 生成测试报告。以上就是一个简单的 vue 单元测试实例。最后奉上源代码

@MTTTM
Copy link

MTTTM commented May 9, 2018

是否可以针对XX.vue的script某个function功能来进行测试和对标签 变量 语法 是否合法进行一个测试,期待可以进一步完善下教程了.
或者是否有相关vue单元测试的资料推荐

Thanks♪(・ω・)ノ

@huangshuwei
Copy link
Owner Author

这方面的资料我倒是没有记录,但是很多开源项目都有单元测试用例,可以直接看那些项目的单元测试的处理方式。另外我后面准备再完善下 vue 相关的单元测试

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants