https://www.w3ctech.com/topic/2052

如何为 Vue 项目写单元测试

  • 明非
  • 2017-07-18
  • 4685 访问
  • 1
  • 分享
  • 微信分享

译者:明非

链接:https://fanmingfei.com/posts/A_Vue_Unit_Text_Tutorial.html

原文:https://scotch.io/amp/tutorials/how-to-write-a-unit-test-for-vuejs?from=timeline&isappinstalled=0

众所周知,Vue.js 是一个非常牛逼的 JavaScript 框架,对于创建复杂功能的前端项目是非常有用的。不管是什么项目,检查应用是否正常工作,运行是否为预期,是尤为重要的。然而,为了保证业务正常运行,我们的项目,每做一次更新,都要对所有功能做一次回归测试,随着项目的增大,重复的测试工作越来越多,越来越乏味,手工测试将变成一个恶心的事情。正因如此,自动化测试诞生了,它可以随时监测我们的代码是否正常工作,运行结果是否符合预期。在这个教程中,我们将创建一个简单的VueJS项目,并为其写一个简单的单元测试。

我们创建一个基本的 to-do list 组件进行测试。我们将要测试的是,列表展示是否正确,用户是否可以正常添加到 to-do list。通过这个教程,你将学会如何去为你的组件写一个测试,测试包括HTML展示是否正确以及用户的操作是否能正常进行。

这个git库是这篇文章的所有代码。

创建项目

创建 JavaScript 项目可能是一个复杂的过程。琳琅满目的依赖库供我们选择。不过还好,我们可以使用vue-cli来创建VueJS项目,它帮我们包办一切。运行 npm install 来安装依赖:

npm install -g vue-cli
vue init webpack project-name

在这个过程中,你可能会遇到几个提示。大多数提示比较简单易懂,你可以直接选择默认选项。需要注意的是,我们需要是否安装 vue-routerKarmaMocha的提示后输入YES来引入这些工具。然后开始安装依赖:

cd project-name
npm install

接下来我们执行下面的命令,这个命令将会在本地运行你的应用并在浏览器中打开。

npm run dev

如果你的网络好的话,一会就装好了。

依赖

Webpack (2.3) 是一个打包器,它可以合并打包JavaScript,CSS,HTML文件,并且提供给应用运行。Bable (v6.22) 是一个编译器,用来把ES6编译成ES5。目前有很多 JavaScript 标准在许多浏览器中还没有被支持,所以需要将ES6转成ES。

测试依赖

Karma (v1.4) 是一个运行时,它产生一个 Web 服务环境来运行项目代码,并且执行测试。Mocha (v3.2) 是一个 JavaScript 测试框架。Chai (v3.5) 是一个 Mocha 可以使用的断言库。

在你的项目中,你可以找到下面这些目录:buildconfignode_modulessrcstatic 和 test。对于本教程来说最重要的是src,它包括我们应用的代码,用来测试。

第一次测试

从最基本的开始去做一般都没错。我们将从创建简单的列表组件开始。在 src/components 里创建一个新文件叫做 List.vue 并且将下面代码写进去。

    <template>
<div>
<h1>My To Do List</h1>
</br>
<!--displays list -->
<ul>
<li v-for="item in listItems">{{ item }}</li>
</ul>
</div>
</template> <script>
export default {
name: 'list',
data () {
return {
listItems: ['buy food', 'play games', 'sleep'],
}
}
}
</script>

在这个组件中,列表项被储存在数组(listItems)里面。数据被传递到模板,然后被遍历(v-for),然后展现在页面上。

当然,我们需要看到刚刚创建的列表,我们可以创建一个新的路由来展示这个组件。在src/router/index.js中创建一个路由,添加完了代码应该是下面这样的:

    import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
import List from '@/components/List' Vue.use(Router) export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello
},
{
path: '/to-do',
name: 'ToDo',
component: List
},
]
})

现在,访问localhost:8080/#/to-do,可以看到我们做的应用。

首先,我们要测试的是数据的正确性。在test/unit/specs目录下创建一个List.spec.js,并且写入下面的代码:

    import List from '@/components/List';
import Vue from 'vue'; describe('List.vue', () => { it('displays items from the list', () => {
// our test goes here
})
})

在这个文件中,我们describingList.vue组件,并且我们创建了一个空的测试,他将要检查这个组件的列表展示。这是一个基本的 Mocha 测试文件。

我们首先要安装我们的Vue组件。复制下面代码放在测试文件的'our test goes here'下面:

    // build component
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount();

我们继承了Vue组件并且安装这个组件。安装组件很重要,只有这样我们才能将通过模板来渲染HTML。也就是说,HTML已经被创建,并且我们模板中的变量(比如 item)已经被填充内容,这样我们就可以获取HTML了(使用$el)。

我们的组件准备好了,我们可以写第一个断言。在这个例子中,我们使用Chai 断言库提供的 'expect' 模式,还有 'should' 和 'assert'模式。将下面的代码放到,启动组件的后面。

    // assert that component text contains items from the list
expect(ListComponent.$el.textContent).to.contain('play games');

之前提到过,我们可以使用ListComponent.$el来获取组件的HTML,如果想去获取HTML内的内容(比如 文本),我们可以使用ListComponent.$el.textContent。这个断言用来检查HTML列表中的文本是否和组件的data里的数据列表吻合。

为了检查所有的事情都符合我们的预期,我们可以运行测试!通过 vue-cli 创建的项目,我们可以简单的使用npm run unit来运行cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run

    npm run unit

如果测试都通过了,将会有一个绿色的列表来显示测试报告,让你了解测试都覆盖了哪些代码。

模拟用户输入

虽然前面的功能赞赞哒,但没有多少应用只是用来展示数据。下一步我们要做到是添加新的项目到to-do list中。看这里,我们创建了一个input框来输入内容,然后创建一个button用来提交内容。下面是更新后的 List.vue:

    <template>
<div>
<h1>My To Do List</h1>
</br>
<input v-model="newItem" >
<button @click="addItemToList">Add</button>
<!-- displays list -->
<ul>
<li v-for="item in listItems">{{ item }}</li>
</ul>
</div>
</template> <script>
export default {
name: 'test',
data () {
return {
listItems: ['buy food', 'play games', 'sleep'],
newItem: ''
}
},
methods: {
addItemToList() {
this.listItems.push(this.newItem);
this.newItem = '';
}
}
}
</script>

使用v-model,输入框里面的内容将和newItem进行双向绑定。当按钮被点击后,执行addItemToList,将newItem添加到to-do list数组里面,并且清空newItem里面的内容,新的项目将会被添加到列表中。

可以为新功能写测试文件了,创建List.spec.js,并且添加以下测试代码。

    it('adds a new item to list on click', () => {
// our test goes here
})

第一步,我们需要创建我们的组件,并且模拟一个用户在输入框的输入行为。因为 VueJs 将输入框和 newItem 变量进行了绑定,我们可以给newItem设置内容。

    // build component
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount(); // set value of new item
ListComponent.newItem = 'brush my teeth';

下一步,我们需要点击按钮。我们需要在HTML中找到按钮,在$el中即可找到。这是,我们可以使用querySelector,像选择真是元素一样选择这个按钮。也可以使用class(.buttonClass)、ID(#buttonID)或者标签名(button)来选择。

    // find button
const button = ListComponent.$el.querySelector('button');

为了模拟点击,我们需要给按钮一个新的事件对象。在测试环境中,List组件不会监听任何事件,因此我们需要手动运行watcher

    // simulate click event
const clickEvent = new window.Event('click');
button.dispatchEvent(clickEvent);
ListComponent._watcher.run();

最后,我们需要检查我们添加的新项目是否显示在HTML中,这个在前面已经介绍过。我们也需要检查newItem是否被存储在了数组里面。

    //assert list contains new item
expect(ListComponent.$el.textContent).to.contain('brush my teeth');
expect(ListComponent.listItems).to.contain('brush my teeth');

下面是整个测试文件的内容:

    import List from '@/components/List';
import Vue from 'vue'; describe('List.vue', () => {
it('displays items from the list', () => {
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount();
expect(ListComponent.$el.textContent).to.contain('play games');
}) it('adds a new item to list on click', () => {
// build component
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount(); // set input value
ListComponent.newItem = 'brush my teeth'; // simulate click event
const button = ListComponent.$el.querySelector('button');
const clickEvent = new window.Event('click');
button.dispatchEvent(clickEvent);
ListComponent._watcher.run(); // assert list contains new item
expect(ListComponent.$el.textContent).to.contain('brush my teeth');
expect(ListComponent.listItems).to.contain('brush my teeth');
})
})

现在跑一次这个测试,应该全是绿色的。

希望你读这些代码的时候思路能够清晰,不过它对于刚刚开始接触VueJs单元测试的人来说可读性并不是很高。有一个VueJS实用程序库,它将一些复杂的代码进行了封装。如果想使用它,可以在项目的根目录下输入以下命令安装。

    npm install avoriaz

下面这个测试实际上和上面测试相同,只不过写法上有些不同。我们使用了mount()法来安装Vue组件,使用find()获取按钮,使用dispatch()来触发点击。

    import { mount } from 'avoriaz';
import List from '@/components/List';
import Vue from 'vue'; describe('List.vue', () => {
// previous tests .. it('adds new item to list on click with avoriaz', () => {
// build component
const ListComponent = mount(List); // set input value
ListComponent.setData({
newItem: 'brush my teeth',
}); // simulate click event
const button = ListComponent.find('button')[0];
button.dispatch('click'); // assert list contains new item
expect(ListComponent.text()).to.contain('brush my teeth');
expect(ListComponent.data().listItems).to.contain('brush my teeth');
})
})

总结

在日常工作以及JavaScript开发中,尤其是VueJS项目,测试是非常重要的。因为刚开始接触测试的时候,我遇到了一些问题,所以总结出一篇文章供大家参考。希望这篇文章能够帮到所有像我一样的人。

这个git库是这次教程所有的代码。

如何为 Vue 项目写单元测试的更多相关文章

  1. Vue 项目添加单元测试发现的问题及解决

    用 Jest 测试单文件组件 1.安装 Jest 和 Vue Test Utils npm install --save-dev jest @vue/test-utils 2.配置 package.j ...

  2. 前端单元测试,以及给现有的vue项目添加jest + Vue Test Utils的配置

    文章原址:https://www.cnblogs.com/yalong/p/11714393.html 背景介绍: 以前写的公共组件,后来需要添加一些功能,添加了好几次,每次修改我都要测试好几遍保证以 ...

  3. Vue项目用webpack打包后,预览时资源路径出错(文末有vue项目链接分享)

    最近用vue写了一些项目,项目写完之后需要打包之后才能放到网上展示,所以在这里记录一下项目打包的过程以及遇到的一些问题. --------------------------------------- ...

  4. 如何为我的VUE项目编写高效的单元测试--Jest

    Unit Testing(单元测试)--Jest 一个完整的测试程序通常由几种不同的测试组合而成,比如end to end(E2E)测试,有时还包括整体测试.简要测试和单元测试.这里要介绍的是Vue中 ...

  5. VSCode 初次写vue项目并一键生成.vue模版

    VSCode 写vue项目一键生成.vue模版 1.新建代码片段 文件-->首选项-->用户代码片段-->点击新建代码片段--取名vue.json 确定 2.配置快捷生成的vue模板 ...

  6. Vue项目搭建完整剖析全过程

    Vue项目搭建完整剖析全过程 项目源码地址:https://github.com/ballyalex 有帮助的话就加个星星呗~!  项目技术栈:vue+webpack+bower+sass+axios ...

  7. vue项目的骨架及常用组件介绍

    vue项目基础结构 一个vue的项目,我觉得最小的子集其实就是{vue,vue-router,component},vue作为基础库,为我们提供双向绑定等功能.vue-router连接不同的" ...

  8. 手把手教你用vue-cli搭建vue项目

    手把手教你用vue-cli搭建vue项目 本篇主要是利用vue-cli来搭建vue项目,其中前提是node和npm已经安装好,文章结尾将会简单提到一个简单的例子.使用vue-cli搭建项目最开始我也是 ...

  9. 搭建vue项目环境

    前言 在开发本项目之前,我对vue,react,angular等框架了解,仅限于知道它们是什么框架,他们的核心是什么,但是并没有实际使用过(angular 1.0版本用过,因为太难用,所以对这类框架都 ...

随机推荐

  1. Apache mod_rewrite规则重写的标志说明

    1.R[=code](force redirect) 强制外部重定向,强制在替代字符串加上http://thishost[:thisport]/前缀重定向到外部的URL.如果code不指定,将用缺省的 ...

  2. spring mvc注解@RequestMapping

    1.url路径映射 基本功能 2.窄化请求映射 根路径+子路径 注意setViewName的路径. 3.限制http请求方法 get和 post 如果是get

  3. 用JAVA实现无等待数据库连接池

    我们都知道数据库连接是一种有限和非常昂贵的应用资源,怎样对这些资源进行高效的管理,能有效的改善整个系统的性能和健壮性.数据库连接池正是针对这个问题而提出来的. 数据库连接负责分配.释放和管理数据库连接 ...

  4. DNS被污染后

    如果有条件,自已DNS还是非常必要的,至少有一亩三分地的净土. 但是DNS污染是无处不在的,特别是 Forwarding的记录, 一旦 IPv6 Tunnel连接失败,DNS Server  瞬间就被 ...

  5. Delphi 10.1.2 berlin开发跨平台APP的几点经验

    1.ios不允许app有退出功能,所以不能调用Application.Terminate. 2.info.plist文件的自定义:info.plist文件是由info.plist.TemplateiO ...

  6. Data Base Oracle 常用命令

    Data Base  Oracle 常用命令 1.登录:(不需要密码,属于管理员权限) conn /as sysdba; 2.查看数据库存储位置: select name from v$datafil ...

  7. 从零开始用 Flask 搭建一个网站(四)

    前言 从零开始用 Flask 搭建一个网站(三) 介绍了网页前端与后端.前端与前端之间数据的交流.本节主要介绍一下如何应用 Flask-OAuthlib, 使用 Flask-OAuthlib 就可以轻 ...

  8. ubuntu15.04下安装jdk8

    前几天手贱,删掉了ubuntu自带的java,最后安装时遇到了Picked up JAVA_TOOL_OPTIONS的问题,经过网上各种找,终于被我弄成功了.下面将经验下载下面供大家方便: jdk8的 ...

  9. [译文]casperjs使用说明-使用命令行

    使用命令行 Casperjs使用内置的phantomjs命令行解析器,在cli模块里,它传递参数位置的命名选项 但是不要担心不能熟练操控CLI模块的API,一个casper实例已经包含了cli属性,允 ...

  10. 在iOS7中修改键盘Return键的类型

    今天将之前运行在iOS7之前的一段代码拿出来,在iOS7的机器上运行,发现键盘上的ReturnKeyType不能被修改了. 经过几番查找资料,了解到iOS7中UISearchBar的结构发生了变化,将 ...