使用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 相关文章推荐
jquery 学习笔记 传智博客佟老师附详细注释
Sep 12 Javascript
JavaScript 原型链学习总结
Oct 29 Javascript
jquery无缝向上滚动实现代码
Mar 29 Javascript
让网页跳转到指定位置的jquery代码非书签
Sep 06 Javascript
js判断undefined类型示例代码
Feb 10 Javascript
jquery常用操作小结
Jul 21 Javascript
javascript查询字符串参数的方法
Jan 28 Javascript
ES6中Generator与异步操作实例分析
Mar 31 Javascript
js每隔两秒输出数组中的一项(实例)
May 28 Javascript
jquery无缝图片轮播组件封装
Nov 25 jQuery
jQuery实现简单的Ajax调用功能示例
Feb 15 jQuery
Vue组件简易模拟实现购物车
Dec 21 Vue.js
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学习笔记 (1) 环境配置与代码调试
2011/06/19 PHP
php中使用临时表查询数据的一个例子
2013/02/03 PHP
php封装db类连接sqlite3数据库的方法实例
2017/12/19 PHP
HTTP状态代码以及定义(解释)
2007/02/02 Javascript
JavaScipt基本教程之前言
2008/01/16 Javascript
理解JavaScript的caller,callee,call,apply
2009/04/28 Javascript
jquery控制背景音乐开关与自动播放提示音的方法
2015/02/06 Javascript
开启Javascript中apply、call、bind的用法之旅模式
2015/10/28 Javascript
JS函数的几种定义方式分析
2015/12/17 Javascript
jQuery树形控件zTree使用小结
2016/08/02 Javascript
Javascript数组循环遍历之forEach详解
2016/11/07 Javascript
三种方式实现瀑布流布局
2017/02/10 Javascript
js/jq仿window文件夹框选操作插件
2017/03/08 Javascript
Angular.js中上传指令ng-upload的基本使用教程
2017/07/30 Javascript
layui中layer前端组件实现图片显示功能的方法分析
2017/10/13 Javascript
JS实现的简单折叠展开动画效果示例
2018/04/28 Javascript
微信小程序购物车、父子组件传值及calc的注意事项总结
2018/11/14 Javascript
vue-cli随机生成port源码的方法
2019/09/02 Javascript
微信小程序实现分享商品海报功能
2019/09/30 Javascript
vue学习笔记之给组件绑定原生事件操作示例
2020/02/27 Javascript
[01:48]完美圣典齐天大圣至宝宣传片
2016/12/17 DOTA
简单上手Python中装饰器的使用
2015/07/12 Python
Python实现定时任务
2017/02/08 Python
详解python中的 is 操作符
2017/12/26 Python
Python中 传递值 和 传递引用 的区别解析
2018/02/22 Python
Python 文本文件内容批量抽取实例
2018/12/10 Python
对python3标准库httpclient的使用详解
2018/12/18 Python
Python Matplotlib 基于networkx画关系网络图
2019/07/10 Python
关于HTML5的安全问题开发人员需要牢记的
2012/06/21 HTML / CSS
canvas绘制树形结构可视图形的实现
2020/04/03 HTML / CSS
视光学专业毕业生推荐信
2013/10/28 职场文书
医学专业应届生的自我评价
2014/02/28 职场文书
检讨书范文
2015/01/27 职场文书
MySQL 角色(role)功能介绍
2021/04/24 MySQL
pytorch Dropout过拟合的操作
2021/05/27 Python
Python 使用 Frame tkraise() 方法在 Tkinter 应用程序中的Frame之间切换
2022/04/24 Python