使用Karma做vue组件单元测试的实现


Posted in Javascript onJanuary 16, 2020

养成良好的编码习惯,一个合格的程序员需要掌握一些编写单元测试的能力。单元测试也可以整体上提升我们的代码质量,这里介绍下 VUE 组件的单元测试。

如果想直接通过 Demo 学习,可以跳过下面的内容,点击这里下载示例

技术栈

  • @vue/test-utils[1.0.0-beta.30]
  • istanbul-instrumenter-loader[3.0.1]
  • karma[4.4.1]
  • karma-chrome-launcher[3.1.0]
  • karma-mocha[1.3.0]
  • karma-sourcemap-loader[0.3.7]
  • karma-coverage-istanbul-reporter[2.1.1]
  • karma-webpack[4.0.2]
  • webpack[4.41.5]

定义配置文件

karma.conf.js 文件用于 karma 的配置,使用 node_modules/.bin/karma init 命令创建该文件,我们定义如下配置:

// Karma configuration

const webpackConfig = require('./config/webpack.test.config.js')

module.exports = function(config) {
 config.set({

  // base path that will be used to resolve all patterns (eg. files, exclude)
  basePath: '.',

  // frameworks to use
  // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
  frameworks: [ 'mocha' ],

  // list of files / patterns to load in the browser
  files: [
   'test/**/*.spec.js'
  ],

  // preprocess matching files before serving them to the browser
  // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
  preprocessors: {
   'test/**/*.spec.js': [ 'webpack', 'sourcemap' ]
  },

  // webpack config
  webpack: webpackConfig,

  webpackMiddleware: {
   stats: 'errors-only'
  },

  // web server port
  port: 9876,

  // enable / disable colors in the output (reporters and logs)
  colors: true,

  // level of logging
  // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
  logLevel: config.LOG_INFO,

  // enable / disable watching file and executing tests whenever any file changes
  autoWatch: true,

  // start these browsers
  // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
  browsers: [ 'Chrome' ],

  // Continuous Integration mode
  // if true, Karma captures browsers, runs the tests and exits
  singleRun: false,

  // Concurrency level
  // how many browser should be started simultaneous
  concurrency: Infinity
 })
}
  1. 设置 frameworks 为 ['mocha'],即使用 mocha 测试框架
  2. 设置 files 为 ['test/**/*.spec.js'],即对 test 目录下所有的后缀为 .spec.js 文件测试
  3. 设置 preprocessors 为 {'**/*.spec.js': ['webpack', 'sourcemap']},即使用 webpack,sourcemap 对所有的测试文件进行 webpack 打包
  4. 设置 browsers 为 Chrome,即使用 Chrome 浏览器作为测试浏览器

编写测试用例

详细的关于 @vue/test-utils 用法,查看 https://vue-test-utils.vuejs.org/zh/

import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import Header from '../src/components/Header'

describe('Header', () => {
 const wrapper = shallowMount(Header)
 const header = wrapper.find('header')
 const h1 = wrapper.find('h1')

 it('有 header 标签', () => {
  expect(header.exists()).to.be.true
 })

 it('有 h1 标签', () => {
  expect(h1.exists()).to.be.true
 })

 it('h1 的文案为“VUE 单页模版”', () => {
  expect(h1.text()).to.equal('VUE 单页模版')
 })

 it('h1 标签在 header 标签中', () => {
  expect(header.contains('h1')).to.be.true
 })
})

这里我引用 vue-single-page 的 Header 组件测试用例

  1. 首先通过 shallowMount 获取 wrapper
  2. 使用 chai 断言库编写相关的测试用例

运行结果

i 「wdm」: Compiled successfully.
15 01 2020 18:28:13.799:INFO [karma-server]: Karma v4.4.1 server started at http://0.0.0.0:9876/
15 01 2020 18:28:13.813:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
15 01 2020 18:28:13.820:INFO [launcher]: Starting browser Chrome
15 01 2020 18:28:17.075:INFO [Chrome 79.0.3945 (Windows 10.0.0)]: Connected on socket PUKPz4iBuFzeVNSsAAAA with id 91716917
TOTAL: 4 SUCCESS

可以看到我们的单元测试已经通过了

测试覆盖率报告

测试完成后,我们需要查看测试覆盖率报告。这需要在 webpack.test.config.js 和 karma.conf.js 中做一些配置修改

webpack.test.config.js

const merge = require('webpack-merge')
const path = require('path')
const webpackCommonConfig = require('./webpack.common.config')

const testConfig = {
 devtool: 'inline-source-map',
 mode: 'none',
 module: {
  rules: [
   {
    test: /\.spec.js$/i,
    enforce: 'pre',
    use: [
     {
      loader: 'istanbul-instrumenter-loader',
      options: {
       esModules: true
      }
     }
    ]
   }
  ]
 }
}

module.exports = merge(webpackCommonConfig, testConfig)

添加一个优先执行的编译 .spec.js 文件的 rules,loader 使用 istanbul-instrumenter-loader 并开启 esModules 模式

karma.conf.js

module.exports = function(config) {
 config.set({
 
  // ...
  
  coverageIstanbulReporter: {
   reports: [ 'html', 'text' ],
   fixWebpackSourcePaths: true
  },
  
  reporters: [ 'coverage-istanbul' ]

  //...
  
 })
}
  1. 设置 reporters 为 [ 'coverage-istanbul' ],即使用 coverage-istanbul reporters
  2. coverageIstanbulReporter 配置项用于设置 coverage-istanbul 的参数,详细的参数可以参考 这里

运行结果

再次执行单元测试,我们会看到测试覆盖率的相关信息

----------------|----------|----------|----------|----------|-------------------|
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files    |   100 |   100 |   100 |   100 |          |
 Header.spec.js |   100 |   100 |   100 |   100 |          |
----------------|----------|----------|----------|----------|-------------------|

也可以通过生成到 coverage 目录下的网页文件,在浏览器中查看

使用Karma做vue组件单元测试的实现

参考资料

https://vue-test-utils.vuejs.org/zh/
https://github.com/mattlewis92/karma-coverage-istanbul-reporter

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
slice函数的用法 之不错的应用
Dec 29 Javascript
javascript一元操作符(递增、递减)使用示例
Aug 07 Javascript
js整数字符串转换为金额类型数据(示例代码)
Dec 26 Javascript
JavaScript用JQuery呼叫Server端方法示例代码
Sep 03 Javascript
javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
Apr 01 Javascript
JavaScript实现的伸展收缩型菜单代码
Oct 14 Javascript
AngularJS中的过滤器filter用法完全解析
Apr 22 Javascript
BootStrap中按钮点击后被禁用按钮的最佳实现方法
Sep 23 Javascript
JSON创建键值对(key是中文或者数字)方式详解
Aug 24 Javascript
详解cordova打包成webapp的方法
Oct 18 Javascript
react 不用插件实现数字滚动的效果示例
Apr 14 Javascript
使用JS实现鼠标放上图片进行放大离开实现缩小功能
Jan 27 Javascript
js实现div色块拖动录制
Jan 16 #Javascript
微信小程序实现二维码签到考勤系统
Jan 16 #Javascript
解决vue+ element ui 表单验证有值但验证失败问题
Jan 16 #Javascript
JavaScript实现简单的计算器
Jan 16 #Javascript
js面向对象之实现淘宝放大镜
Jan 15 #Javascript
js实现简单的打印表格
Jan 15 #Javascript
js实现图片实时时钟
Jan 15 #Javascript
You might like
PHP中::、->、self、$this几种操作符的区别介绍
2013/04/24 PHP
基于PHP5魔术常量与魔术方法的详解
2013/06/13 PHP
深入extjs与php参数交互的详解
2013/06/25 PHP
浅谈php数组array_change_key_case() 函数和array_chunk()函数
2016/10/22 PHP
源码分析 Laravel 重复执行同一个队列任务的原因
2017/12/25 PHP
Ajax+PHP实现的分类列表框功能示例
2019/02/11 PHP
分别用marquee和div+js实现首尾相连循环滚动效果,仅3行代码
2011/09/21 Javascript
Jquery实现自定义弹窗示例
2014/03/12 Javascript
js设置cookie过期当前时间减去一秒相当于立即过期
2014/09/04 Javascript
JavaScript判断手机号运营商是移动、联通、电信还是其他(代码简单)
2015/09/25 Javascript
Javascript this 函数深入详解
2016/12/13 Javascript
jquery滚动条插件slimScroll使用方法
2017/02/09 Javascript
JavaScript中最常见的三个面试题解析
2017/03/04 Javascript
jQuery.Form实现Ajax上传文件同时设置headers的方法
2017/06/26 jQuery
es6中的解构赋值、扩展运算符和rest参数使用详解
2017/09/28 Javascript
详解如何构建一个Angular6的第三方npm包
2018/09/07 Javascript
JS实现求5的阶乘示例
2019/01/21 Javascript
vue-cli3 配置开发与测试环境详解
2019/05/17 Javascript
vue项目中定义全局变量、函数的几种方法
2019/11/08 Javascript
聊聊Vue中provide/inject的应用详解
2019/11/10 Javascript
[01:09]模型精美,特效酷炫!TI9不朽宝藏Ⅰ鉴赏
2019/05/10 DOTA
[02:10]三分钟回顾完美世界城市挑战赛
2019/01/24 DOTA
详解python并发获取snmp信息及性能测试
2017/03/27 Python
Python实现Linux中的du命令
2017/06/12 Python
python实现微信接口(itchat)详细介绍
2017/10/23 Python
python实现美团订单推送到测试环境,提供便利操作示例
2019/08/09 Python
Python requests.post方法中data与json参数区别详解
2020/04/30 Python
Python读取Excel数据并生成图表过程解析
2020/06/18 Python
使用anaconda安装pytorch的实现步骤
2020/09/03 Python
IE9对HTML5中部分属性不支持的原因分析
2014/10/15 HTML / CSS
linux下进程间通信的方式
2014/12/23 面试题
2014社区健康教育工作总结
2014/12/16 职场文书
防溺水安全教育主题班会
2015/08/12 职场文书
少年的你:世界上没有如果,要在第一次就勇敢的反抗
2019/11/20 职场文书
Python函数式编程中itertools模块详解
2021/09/15 Python
使用Mysql计算地址的经纬度距离和实时位置信息
2022/04/29 MySQL