目前开发大型应用,测试是一个很是重要的环节,可是大多数前端开发者对测试相关的知识是比较缺少的。由于可能项目开发周期短根本没有机会写,因此你没有办法体会到前端自动化测试的重要性。javascript
来讲说为何前端自动化测试如此重要!前端
先看看前端常见的问题:java
增长自动化测试后:node
单元测试(Unit Testing)
es6
单元测试是指对程序中最小可测试单元进行的测试,例如测试一个函数
、一个模块
、一个组件
...web
集成测试(Integration Testing)
npm
将已测试过的单元测试函数进行组合集成暴露出的高层函数或类的封装,对这些函数或类进行的测试json
端到端测试(E2E Testing)
打开应用程序模拟输入,检查功能以及界面是否正确浏览器
TDD是测试驱动开发(Test-Driven Development)
bash
TDD的原理是在开发功能代码以前,先编写单元测试用例代码
BDD是行为驱动开发(Behavior-Driven Development)
系统业务专家、开发者、测试人员一块儿合做,分析软件的需求,而后将这些需求写成一个个的故事。开发者负责填充这些故事的内容,保证程序实现效果与用户需求一致。
小结:
TDD是先写测试再开发 (通常都是单元测试,白盒测试);而BDD则是按照用户的行为来开发,再根据用户的行为编写测试用例 (通常都是集成测试,黑盒测试)
看到这里Facebook
都在推Jest,你还不学吗? Jest也有一些缺陷就是不能像Karma
这样直接跑在浏览器上,它采用的是jsdom
,优点是简单、0配置! 后续咱们经过Jest来聊聊前端自动化测试。
在说Jest
测试以前,先来看看之前咱们是怎样测试的
const parser = (str) =>{ const obj = {}; str.replace(/([^&=]*)=([^&=]*)/g,function(){ obj[arguments[1]] = arguments[2]; }); return obj; } const stringify = (obj) =>{ const arr = []; for(let key in obj){ arr.push(`${key}=${obj[key]}`); } return arr.join('&'); } // console.log(parser('name=webyouxuan')); // {name:'webyouxuan'} // console.log(stringify({name:'webyouxuan'})) // name=webyouxuan
咱们每写完一个功能,都先须要手动测试功能是否正常,测试后可能会将测试代码注释起来,这样会产生一系列问题。由于会污染源代码,全部的测试代码和源代码混合在一块儿。若是删除掉,下次测试还须要从新编写。
因此测试框架就帮咱们解决了上述的问题
Jest是基于模块
的,咱们须要将代码包装成模块的方式,分别使用 export
将 parser
、stringify
这两个方法导出。
安装jest
npm init -y # 初始化pacakge.json npm i jest
咱们创建一个qs.test.js
来专门编写测试用例,这里的用例你能够认为就是一条测试功能 (后缀要以.test.js结尾,这样jest测试时默认会调用这个文件)。
import {parser,stringify} from './qs'; it('测试 parser 是否能正常解析结果',()=>{ // expect 断言,判断解析出来的结果是否和 {name:'webyouxuan'}相等 expect(parser(`name=webyouxuan`)).toEqual({name:'webyouxuan'}); })
jest
默认自带断言功能,断言的意思就是判断是否是这个样子,我判定你今天没吃饭~,结果你吃了,说明此次断言就失败了,测试就没法经过。
经过配置scripts
来执行命令
"scripts": { "test": "jest" }
执行 npm run test
,惋惜的是默认在node
环境下不支持es6模块
的语法,须要babel
转义,固然你也能够直接使用commonjs规范来导出方法,由于大多数如今开发都采用es6模块,因此安装一下便可。
# core是babel的核心包 preset-env将es6转化成es5 npm i @babel/core @babel/preset-env --save-dev
而且须要配置.babelrc
文件,告诉babel用什么来转义
{ "presets":[ [ "@babel/preset-env",{ "targets": {"node":"current"} } ] ] }
默认Jest中集成了babel-jest
,运行时默认会调用.babelrc
进行转义,能够直接将es6转成es5语法。
运行 npm run test
出现:
继续编写第二个用例
import {parser,stringify} from './qs'; describe('测试qs 库',()=>{ it('测试 parser 是否能正常解析结果',()=>{ expect(parser(`name=webyouxuan`)).toEqual({name:'webyouxuan'}); }); it('测试 stringify 是否正常使用stringify',()=>{ expect(stringify({name:'webyouxuan'})).toEqual(`name=webyouxuan`) }) });
describe的功能是给用例分组,这样能够更好的给用例分类,其实这就是咱们所谓的单元测试,对某个具体函数和功能进行测试。
在写第一个测试用例时,咱们一直在使用toEqual
其实这就是一个匹配器,那咱们来看看jest
中经常使用的匹配器有哪些?由于匹配器太多了,因此我就讲些经常使用的!
为了方便理解,我把匹配器分为三类:判断相等、不等、是否包含。
it('判断是否相等',()=>{ expect(1+1).toBe(2); // 至关于 js中的=== expect({name:'webyouxuan'}).toEqual({name:'webyouxuan'}); // 比较内容是否相等 expect(true).toBeTruthy(); // 是否为 true / false 也能够用toBe(true) expect(false).toBeFalsy(); }); it('判断不相等关系',()=>{ expect(1+1).not.toBe(3); // not取反 expect(1+1).toBeLessThan(5); // js中的小于 expect(1+1).toBeGreaterThan(1); // js中的大于 }); it('判断是否包含',()=>{ expect('hello world').toContain('hello'); // 是否包含 expect('hello world').toMatch(/hello/); // 正则 });
说了半天,咱们本身来写个功能测试一下!
export const removeNode = (node) => { node.parentNode.removeChild(node) };
核心就是测试传入一个节点,这个节点是否能从DOM
中删除
import { removeNode } from './dom' it('测试删除节点',()=>{ document.body.innerHTML = `<div><button data-btn="btn"></button</div>` let btn = document.querySelector('[data-btn="btn"]') expect(btn).not.toBeNull() removeNode(btn); btn = document.querySelector('[data-btn="btn"]'); expect(btn).toBeNull() })
这个就是咱们所说的jsdom
,在node中操做DOM元素
咱们但愿每次更改测试后,自动从新执行测试,修改执行命令:
"scripts": { "test": "jest --watchAll" }
从新执行 npm run test
,这时就会监控用户的修改
提示咱们按下w
,显示更多信息
这里我把每一个命令的含义都列好了,有须要能够本身尝试一下~
想要知道如何测试异步逻辑,如何mock接口数据,如何深度使用Jest吗?敬请期待下期文章!