1. 单元测试
指对软件中的最小可测试单元进行检查和验证
长期以来,前端开发的单元测试并不是在前端的开发过程中所必须的,也不是每个前端开发工程师所注意和重视的,甚至扩大到软件开发过程中单元测试这一环也不是在章程上有书面规定所要求的。但是随着每个工程的复杂化、代码的高复用性要求和前端代码模块之间的高内聚低耦合的需求,前端工程中的单元测试流程就显得很有其必要。
前端单元测试是什么
首先我们要明确测试是什么:
为检测特定的目标是否符合标准而采用专用的工具或者方法进行验证,并最终得出特定的结果。
对于前端开发过程来说,这里的特定目标就是指我们写的代码,而工具就是我们需要用到的测试框架(库)、测试用例等。检测处的结果就是展示测试是否通过或者给出测试报告,这样才能方便问题的排查和后期的修正。
单元测试的意义以及为什么需要单元测试
单元测试的意义
对于现在的前端工程,一个标准完整的项目,测试是非常有必要的。很多时候我们只是完成了项目而忽略了项目测试的部分,测试的意义主要在于下面几点:
- TDD(测试驱动开发) 被证明是有效的软件编写原则,它能覆盖更多的功能接口。
- 快速反馈你的功能输出,验证你的想法。
- 保证代码重构的安全性,没有一成不变的代码,测试用例能给你多变的代码结构一个定心丸。
- 易于测试的代码,说明是一个好的设计。做单元测试之前,肯定要实例化一个东西,假如这个东西有很多依赖的话,这个测试构造过程将会非常耗时,会影响你的测试效率,怎么办呢?要依赖分离,一个类尽量保证功能单一,比如视图与功能分离,这样的话,你的代码也便于维护和理解。
为什么需要单元测试
- 首先是一个前端单元测试的根本性原由:JavaScript 是动态语言,缺少类型检查,编译期间无法定位到错误; JavaScript 宿主的兼容性问题。比如 DOM 操作在不同浏览器上的表现。
- 正确性:测试可以验证代码的正确性,在上线前做到心里有底。
- 自动化:当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到保证。通过编写测试用例,可以做到一次编写,多次运行。
- 解释性:测试用例用于测试接口、模块的重要性,那么在测试用例中就会涉及如何使用这些API。其他开发人员如果要使用这些API,那阅读测试用例是一种很好地途径,有时比文档说明更清晰。
- 驱动开发,指导设计:代码被测试的前提是代码本身的可测试性,那么要保证代码的可测试性,就需要在开发中注意API的设计,TDD将测试前移就是起到这么一个作用。
- 保证重构:互联网行业产品迭代速度很快,迭代后必然存在代码重构的过程,那怎么才能保证重构后代码的质量呢?有测试用例做后盾,就可以大胆的进行重构。
如何写单元测试用例
原则
- 测试代码时,只考虑测试,不考虑内部实现
- 数据尽量模拟现实,越靠近现实越好
- 充分考虑数据的边界条件
- 对重点、复杂、核心代码,重点测试
- 利用AOP(beforeEach、afterEach),减少测试代码数量,避免无用功能
- 测试、功能开发相结合,有利于设计和代码重构
中心思想
- given 准备数据
- when 触发测试动作
- then 验证结果
2. jest
-
介绍
Jest是Facebook开源的一套JavaScript测试框架, 它集成了断言、JSDom、覆盖率报告等开发者所需要的所有测试工具。
官方简介:一个令人愉快的javascript测试框架。 我的理解是,不用加班改bug了,可以提前下班.
-
安装
# 项目中使用 yarn init -y yarn add --dev jest # 或者全局安装,随时随地使用 yarn global add jest
-
hello,word
// hello.js module.exports = function(){ return "hello world"; } // hello.test.js const hello = require('../hello'); it('should ', () => { expect(hello()).toBe('hello world'); });
-
基础知识
-
测试函数 test/it
test("测试用列描述信息",()=>{}) // or it("测试用例描述信息",()=>{})
-
断言函数
测试运行结果是否与我们预期结果一致,断言函数用来验证结果是否正确
exspect(运行结果).toBe(期望的结果); //常见断言方法 expect({a:1}).toBe({a:1})//判断两个对象是否相等 expect(1).not.toBe(2)//判断不等 expect({ a: 1, foo: { b: 2 } }).toEqual({ a: 1, foo: { b: 2 } })// 判断是否为两个相同的对象 expect(n).toBeNull(); //判断是否为null expect(n).toBeUndefined(); //判断是否为undefined expect(n).toBeDefined(); //判断结果与toBeUndefined相反 expect(n).toBeTruthy(); //判断结果为true expect(n).toBeFalsy(); //判断结果为false expect(value).toBeGreaterThan(3); //大于3 expect(value).toBeGreaterThanOrEqual(3.5); //大于等于3.5 expect(value).toBeLessThan(5); //小于5 expect(value).toBeLessThanOrEqual(4.5); //小于等于4.5 expect(value).toBeCloseTo(0.3); // 浮点数判断相等 expect('Christoph').toMatch(/stop/); //正则表达式判断 expect(['one','two']).toContain('one'); //不解释
-
分组函数 describe
describe("关于每个功能的测试信息",()=>{ // 不同的测试单元测试 test() it() })
-
常见命令
"nocache": "jest --no-cache", //清除缓存 "watch": "jest --watchAll", //实时监听 "coverage": "jest --coverage", //生成覆盖测试文档 "verbose": "npx jest --verbose" //显示测试描述
-
3. vue-test-utils
为什么使用 vue-test-utils
vue-test-utils是vue官方的单元测试框架,提供了一系列非常方便的工具,使我们更轻松地为vue构建的应用来编写单元测试。主流的JavaScript测试运行器有很多,但vue-test-utils都能支持。它是测试运行器无关的。
为什么选择jest
因为 jest 包含了 karma + mocha + chai + sinon 的所有常用功能,零配置开箱即用
Vue官方是这样描述的:
Jest 是功能最全的测试运行器。它所需的配置是最少的,默认安装了 JSDOM,内置断言且命令行的用户体验非常好。不过你需要一个能够将单文件组件导入到测试中的预处理器。我们已经创建了 vue-jest 预处理器来处理最常见的单文件组件特性,但仍不是 vue-loader 100% 的功能。
vue-test-utils在Vue和Jest之间提供了一个桥梁,暴露出一些接口,让我们更加方便地通过Jest为Vue应用编写单元测试
安装
-
Vue-cli中使用
- 自定义安装选测试
-
单独使用
安装: npm install --save-dev jest @vue/test-utils
- props
- 用户交互
- slots
4. 测试异步组件逻辑
- 普通的异步测试
- axios模式数据
- flushPromise库