使用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 相关文章推荐
JavaScript DOM 学习第七章 表单的扩展
Feb 19 Javascript
JavaScript setTimeout和setInterval的使用方法 说明
Mar 25 Javascript
jQuery 学习第七课 扩展jQuery的功能 插件开发
May 17 Javascript
JQuery自适应窗口大小导航菜单附源码下载
Sep 01 Javascript
jQuery实现的精美平滑二级下拉菜单效果代码
Mar 28 Javascript
深入理解JavaScript中的并行处理
Sep 22 Javascript
浅谈Javascript中的Label语句
Dec 14 Javascript
数组Array的一些方法(总结)
Feb 17 Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
Jul 22 jQuery
JavaScript数组去重的多种方法(四种)
Sep 19 Javascript
JS实现移动端整屏滑动的实例代码
Nov 10 Javascript
简单了解JS打开url的方法
Feb 21 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
第六节 访问属性和方法 [6]
2006/10/09 PHP
VFP与其他应用程序的集成
2006/10/09 PHP
php实现mysql数据库分表分段备份
2015/06/18 PHP
Symfony核心类概述
2016/03/17 PHP
PHP设计模式之装饰器模式实例详解
2018/02/07 PHP
Laravel框架中队列和工作(Queues、Jobs)操作实例详解
2020/04/06 PHP
JavaScript时间操作之年月日星期级联操作
2016/01/15 Javascript
jstl中判断list中是否包含某个值的简单方法
2016/10/14 Javascript
AngularJS学习第二篇 AngularJS依赖注入
2017/02/13 Javascript
Vue.js@2.6.10更新内置错误处机制Fundebug同步支持相应错误监控
2019/05/13 Javascript
浅谈Vuex注入Vue生命周期的过程
2019/05/20 Javascript
jQuery实现点击滚动到指定元素上的方法分析
2020/03/19 jQuery
[54:45]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 Optic vs OG
2018/04/02 DOTA
python备份文件以及mysql数据库的脚本代码
2013/06/10 Python
在Python编程过程中用单元测试法调试代码的介绍
2015/04/02 Python
Python学习笔记整理3之输入输出、python eval函数
2015/12/14 Python
实例解析Python中的__new__特殊方法
2016/06/02 Python
Python用threading实现多线程详解
2017/02/03 Python
Python中异常重试的解决方案详解
2017/05/05 Python
python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)
2017/05/25 Python
Python之文字转图片方法
2018/05/10 Python
python实现ftp文件传输系统(案例分析)
2020/03/20 Python
django配置app中的静态文件步骤
2020/03/27 Python
django修改models重建数据库的操作
2020/03/31 Python
详解CSS3中Media Queries的相关使用
2015/07/17 HTML / CSS
意大利高端时尚买手店:Stefania Mode
2018/03/01 全球购物
武汉瑞得软件笔试题
2015/10/27 面试题
企业理念标语
2014/06/09 职场文书
家庭教育的心得体会
2014/09/01 职场文书
出生医学证明书
2014/09/15 职场文书
2014年民主评议党员个人总结
2014/09/24 职场文书
放假通知范文
2015/04/14 职场文书
总结几个非常实用的Python库
2021/06/26 Python
Python+tkinter实现高清图片保存
2022/03/13 Python
前端JS获取URL参数的4种方法总结
2022/04/05 Javascript
MySQL解决Navicat设置默认字符串时的报错问题
2022/06/16 MySQL