热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mochachaimysql_详解Vue单元测试Karma+Mocha学习笔记

在使用vue-cli创建项目的时候,会提示要不要安装单元测试和e2e测试。既然官方推荐我们使用这两个测试框架,那么我们就动手去学习实践一下他们吧。简介K

在使用vue-cli创建项目的时候,会提示要不要安装单元测试和e2e测试。既然官方推荐我们使用这两个测试框架,那么我们就动手去学习实践一下他们吧。

简介

Karma

Karma是一个基于Node.js的Javascript测试执行过程管理工具(Test Runner)。该工具在Vue中的主要作用是将项目运行在各种主流Web浏览器进行测试。

换句话说,它是一个测试工具,能让你的代码在浏览器环境下测试。需要它的原因在于,你的代码可能是设计在浏览器端执行的,在node环境下测试可能有些bug暴露不出来;另外,浏览器有兼容问题,karma提供了手段让你的代码自动在多个浏览器(chrome,firefox,ie等)环境下运行。如果你的代码只会运行在node端,那么你不需要用karma。

Mocha

Mocha是一个测试框架,在vue-cli中配合chai断言库实现单元测试。

而Chai断言库可以看Chai.js断言库API中文文档,很简单,多查多用就能很快掌握。

我对测试框架的理解

npm run unit 执行过程

执行 npm run unit 命令

开启Karma运行环境

使用Mocha去逐个测试用Chai断言写的测试用例

在终端显示测试结果

如果测试成功,karma-coverage 会在 ./test/unit/coverage 文件夹中生成测试覆盖率结果的网页。

Karma

对于Karma,我只是了解了一下它的配置选项。

下面是Vue的karma配置,简单注释了下:

var webpackConfig = require('../../build/webpack.test.conf')

module.exports = function (config) {

config.set({

// 浏览器

browsers: ['PhantomJS'],

// 测试框架

frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],

// 测试报告

reporters: ['spec', 'coverage'],

// 测试入口文件

files: ['./index.js'],

// 预处理器 karma-webpack

preprocessors: {

'./index.js': ['webpack', 'sourcemap']

},

// Webpack配置

webpack: webpackConfig,

// Webpack中间件

webpackMiddleware: {

noInfo: true

},

// 测试覆盖率报告

// https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md

coverageReporter: {

dir: './coverage',

reporters: [

{ type: 'lcov', subdir: '.' },

{ type: 'text-summary' }

]

}

})

}

Mocha和chai

我们看下官方的例子(都用注释来解释代码意思了):

import Vue from 'vue' // 导入Vue用于生成Vue实例

import Hello from '@/components/Hello' // 导入组件

// 测试脚本里面应该包括一个或多个describe块,称为测试套件(test suite)

describe('Hello.vue', () => {

// 每个describe块应该包括一个或多个it块,称为测试用例(test case)

it('should render correct contents', () => {

const Constructor = Vue.extend(Hello) // 获得Hello组件实例

const vm = new Constructor().$mount() // 将组件挂在到DOM上

//断言:DOM中class为hello的元素中的h1元素的文本内容为Welcome to Your Vue.js App

expect(vm.$el.querySelector('.hello h1').textContent)

.to.equal('Welcome to Your Vue.js App')

})

})

需要知道的知识点:

测试脚本都要放在 test/unit/specs/ 目录下。

脚本命名方式为  [组件名].spec.js。

所谓断言,就是对组件做一些操作,并预言产生的结果。如果测试结果与断言相同则测试通过。

单元测试默认测试 src 目录下除了 main.js 之外的所有文件,可在 test/unit/index.js 文件中修改。

Chai断言库中,to be been is that which and has have with at of same 这些语言链是没有意义的,只是便于理解而已。

测试脚本由多个  descibe 组成,每个 describe 由多个 it 组成。

了解异步测试

it('异步请求应该返回一个对象', done => {

request

.get('https://api.github.com')

.end(function(err, res){

expect(res).to.be.an('object');

done();

});

});

了解一下 describe 的钩子(生命周期)

describe('hooks', function() {

before(function() {

// 在本区块的所有测试用例之前执行

});

after(function() {

// 在本区块的所有测试用例之后执行

});

beforeEach(function() {

// 在本区块的每个测试用例之前执行

});

afterEach(function() {

// 在本区块的每个测试用例之后执行

});

// test cases

});

实践

上面简单介绍了单元测试的用法,下面来动手在Vue中进行单元测试!

util.js

从Vue官方的demo可以看出,对于Vue的单元测试我们需要将组件实例化为一个Vue实例,有时还需要挂载到DOM上。

const Constructor = Vue.extend(Hello) // 获得Hello组件实例

const vm = new Constructor().$mount() // 将组件挂载到DOM上

以上写法只是简单的获取组件,有时候我们需要传递props属性、自定义方法等,还有可能我们需要用到第三方UI框架。所以以上写法非常麻烦。

这里推荐Element的单元测试工具脚本Util.js,它封装了Vue单元测试中常用的方法。下面demo也是根据该 Util.js来写的。

这里简单注释了下各方法的用途。

/**

* 回收 vm,一般在每个测试脚本测试完成后执行回收vm。

* @param {Object} vm

*/

exports.destroyVM = function (vm) {}

/**

* 创建一个 Vue 的实例对象

* @param {Object|String} Compo - 组件配置,可直接传 template

* @param {Boolean=false} mounted - 是否添加到 DOM 上

* @return {Object} vm

*/

exports.createVue = function (Compo, mounted = false) {}

/**

* 创建一个测试组件实例

* @param {Object} Compo - 组件对象

* @param {Object} propsData - props 数据

* @param {Boolean=false} mounted - 是否添加到 DOM 上

* @return {Object} vm

*/

exports.createTest = function (Compo, propsData = {}, mounted = false) {}

/**

* 触发一个事件

* 注: 一般在触发事件后使用 vm.$nextTick 方法确定事件触发完成。

* mouseenter, mouseleave, mouseover, keyup, change, click 等

* @param {Element} elm - 元素

* @param {String} name - 事件名称

* @param {*} opts - 配置项

*/

exports.triggerEvent = function (elm, name, ...opts) {}

/**

* 触发 “mouseup” 和 “mousedown” 事件,既触发点击事件。

* @param {Element} elm - 元素

* @param {*} opts - 配置选项

*/

exports.triggerClick = function (elm, ...opts) {}

示例一

示例一中我们测试了 Hello 组件的各种元素的数据,学习  util.js 的 destroyVM 和 createTest 方法的用法以及如何获取目标元素进行测试。获取DOM元素的方式可查看DOM 对象教程。

Hello.vue

{{ msg }}

{{ content }}

export default {

name: 'hello',

props: {

content: String

},

data () {

return {

msg: 'Welcome!'

}

}

}

Hello.spec.js

import { destroyVM, createTest } from '../util'

import Hello from '@/components/Hello'

describe('Hello.vue', () => {

let vm

afterEach(() => {

destroyVM(vm)

})

it('测试获取元素内容', () => {

vm = createTest(Hello, { content: 'Hello World' }, true)

expect(vm.$el.querySelector('.hello h1').textContent).to.equal('Welcome!')

expect(vm.$el.querySelector('.hello h2').textContent).to.have.be.equal('Hello World')

})

it('测试获取Vue对象中数据', () => {

vm = createTest(Hello, { content: 'Hello World' }, true)

expect(vm.msg).to.equal('Welcome!')

// Chai的语言链是无意义的,可以随便写。如下:

expect(vm.content).which.have.to.be.that.equal('Hello World')

})

it('测试获取DOM中是否存在某个class', () => {

vm = createTest(Hello, { content: 'Hello World' }, true)

expect(vm.$el.classList.contains('hello')).to.be.true

const title = vm.$el.querySelector('.hello h1')

expect(title.classList.contains('hello-title')).to.be.true

const content = vm.$el.querySelector('.hello-content')

expect(content.classList.contains('hello-content')).to.be.true

})

})

输出结果

Hello.vue

√ 测试获取元素内容

√ 测试获取Vue对象中数据

√ 测试获取DOM中是否存在某个class

示例二

示例二中我们使用 createTest 创建测试组件测试点击事件,用 createVue 创建Vue示例对象测试组件 Click 的使用。这里主要可以看下到 createVue 方法的使用。

Click.vue

初始值为{{ InitNum }}

点击了{{ ClickNum }}次

最终结果为{{ ResultNum }}

累加{{ AddNum }}

export default {

name: 'Click',

props: {

AddNum: {

type: Number,

default: 1

},

InitNum: {

type: Number,

default: 1

}

},

data () {

return {

ClickNum: 0,

ResultNum: 0

}

},

mounted () {

this.ResultNum = this.InitNum

},

methods: {

add () {

this.ResultNum += this.AddNum

this.ClickNum++

this.$emit('result', {

ClickNum: this.ClickNum,

ResultNum: this.ResultNum

})

}

}

}

Click.spec.js

import { destroyVM, createTest, createVue } from '../util'

import Click from '@/components/Click'

describe('click.vue', () => {

let vm

afterEach(() => {

destroyVM(vm)

})

it('测试按钮点击事件', () => {

vm = createTest(Click, {

AddNum: 10,

InitNum: 11

}, true)

let buttonElm = vm.$el.querySelector('button')

buttonElm.click()

buttonElm.click()

buttonElm.click()

// setTimeout 的原因

// 在数据改变之后,界面的变化会有一定延时。不用timeout有时候会发现界面没有变化

setTimeout(done => {

expect(vm.ResultNum).to.equal(41)

expect(vm.$el.querySelector('.init-num').textContent).to.equal('初始值为11')

expect(vm.$el.querySelector('.click-num').textContent).to.equal('点击了3次')

expect(vm.$el.querySelector('.result-num').textContent).to.equal('最终结果为41')

done()

}, 100)

})

it('测试创建Vue对象', () => {

let result

vm = createVue({

template: `

`,

props: {

AddNum: 10,

InitNum: 11

},

methods: {

handleClick (obj) {

result = obj

}

},

components: {

Click

}

}, true)

vm.$el.click()

vm.$nextTick(done => {

expect(result).to.be.exist

expect(result.ClickNum).to.equal(1)

expect(result.ResultNum).to.be.equal(21)

done()

})

})

输出结果

click.vue

√ 测试按钮点击事件

√ 测试创建Vue对象

其他

所有示例代码都放Github仓库中便于查看。如果想查看更多好的测试用例,建议配合 Util.js 看一下 Element 的单元测试脚本的写法,里面有很多测试脚本可以供我们学习。作为被广大Vue用户使用的UI组件库,测试脚本肯定也写很很不错的~甚至可以将这些脚本照抄一遍,相信这会对学习Vue组件的单元测试有很大帮助。

下面是本人看Element单元测试的笔记,供参考。

Util.js 方法包含了大多数Vue组件化的测试需求。

vm.$el vm.$nextTick 和 vm.$ref 都是在测试过程中比较常用的一些Vue语法糖。

需要注意: vm.$nextTick 方法是异步的,所以需要在里面使用done方法。

异步断言,方法参数需要是 _ 或者 done

大多数时候查询元素通过 querySelector 方法查询class获得

vm.$el.querySelector('.el-breadcrumb').innerText

大多数情况下查询是否存在某个Class通过 classList.contains 方法获得,查找的结果为 true 或 false

vm.$el .classList.contains('el-button--primary')

异步测试必须以 done() 方法结尾。setTimeout 和 vm.$nextTick 是常用的异步测试。

实现按钮点击:通过获取按钮元素 btn,执行 btn.click() 方法实现。

由于 Vue 进行异步更新DOM的情况,一些依赖DOM更新结果的断言必须在 Vue.nextTick 回调中进行。

triggerEvent(vm.$refs.cascader.$el, 'mouseenter');

vm.$nextTick(_ => {

vm.$refs.cascader.$el.querySelector('.el-cascader__clearIcon').click();

vm.$nextTick(_ => {

expect(vm.selectedOptions.length).to.be.equal(0);

done();

});

});

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



推荐阅读
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
  • 本文介绍了在使用vue和webpack进行异步组件按需加载时可能出现的报错问题,并提供了解决方法。同时还解答了关于局部注册组件和v-if指令的相关问题。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
  • 本文介绍了Sencha Touch的学习使用心得,主要包括搭建项目框架的过程。作者强调了使用MVC模式的重要性,并提供了一个干净的引用示例。文章还介绍了Index.html页面的作用,以及如何通过链接样式表来改变全局风格。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 本文讨论了在使用PHP cURL发送POST请求时,请求体在node.js中没有定义的问题。作者尝试了多种解决方案,但仍然无法解决该问题。同时提供了当前PHP代码示例。 ... [详细]
  • loader资源模块加载器webpack资源模块加载webpack内部(内部loader)默认只会处理javascript文件,也就是说它会把打包过程中所有遇到的 ... [详细]
  • npmrunbuild后dist文件夹下面直接浏览器打开index.html,css和js的路径都不正确。放到跟目录下就正常了,iis上同样只能在根目录下。我项目的目录如下: ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 【前端工具】nodejs+npm+vue 安装(windows)
    预备先看看这几个是干嘛的,相互的关系是啥。nodejs是语言,类比到php。npm是个包管理,类比到composer。vue是个框架&# ... [详细]
  • python+selenium十:基于原生selenium的二次封装fromseleniumimportwebdriverfromselenium.webdriv ... [详细]
  • 前言:原本纠结于Web模板,选了Handlebars。后来发现页面都是弱逻辑的,不支持复杂逻辑表达式。几乎要放弃之际,想起了Javascript中ev ... [详细]
author-avatar
潮爆啊--_317
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有