前端测试工具一览

前端测试工具也和前端的框架一样纷繁复杂,其中常见的测试工具,大致可分为测试框架、断言库、测试覆盖率工具等几类。在正式开始本文之前,我们先来大致了解下它们:

测试框架

测试框架的作用是提供一些方便的语法来描述测试用例,以及对用例进行分组。
测试框架可分为两种: TDD (测试驱动开发)和 BDD (行为驱动开发)
常见的测试框架有 Jasmine, Mocha以及本文要介绍的 Jest。

断言库

断言库主要提供语义化方法,用于对参与测试的值做各种各样的判断。这些语义化方法会返回测试的结果,要么成功、要么失败。常见的断言库有 Should.js, Chai.js等。

测试覆盖率工具

用于统计测试用例对代码的测试情况,生成相应的报表,比如istanbul。

Jest

为什么选择 Jest

Jest 是 Facebook 出品的一个测试框架,相对其他测试框架,其一大特点就是就是内置了常用的测试工具,比如自带断言、测试覆盖率工具,实现了开箱即用。
而作为一个面向前端的测试框架, Jest 可以利用其特有的快照测试功能,通过比对 UI 代码生成的快照文件,实现对 React 等常见框架的自动测试。
此外, Jest 的测试用例是并行执行的,而且只执行发生改变的文件所对应的测试,提升了测试速度。目前在 Github 上其 star 数已经破万;而除了 Facebook 外,业内其他公司也开始从其它测试框架转向 Jest ,比如 Airbnb 的尝试,相信未来 Jest 的发展趋势仍会比较迅猛。

安装

Jest 可以通过 npm 或 yarn 进行安装。以 npm 为例,既可用npm install -g jest进行全局安装;也可以只局部安装、并在 package.json 中指定 test 脚本:

{
"scripts": {
"test": "jest"
}
}

Jest 的测试脚本名形如*.test.js,不论 Jest 是全局运行还是通过npm test运行,它都会执行当前目录下所有的*.test.js 或 *.spec.js 文件、完成测试。

基本使用

用例的表示

表示测试用例是一个测试框架提供的最基本的 API , Jest 内部使用了 Jasmine 2 来进行测试,故其用例语法与 Jasmine 相同。test()函数来描述一个测试用例,举个简单的例子:

// hello.js
module.exports = () => 'Hello world'
// hello.test.js
let hello = require('hello.js') test('should get "Hello world"', () => {
expect(hello()).toBe('Hello world') // 测试成功
// expect(hello()).toBe('Hello') // 测试失败
})

其中toBe('Hello world')便是一句断言( Jest 管它叫 “matcher” ,想了解更多 matcher 请参考文档)。写完了用例,运行在项目目录下执行npm test,即可看到测试结果:

若测试失败,会标识出失败的断言位置,结果如下:

用例的预处理或后处理

有时我们想在测试开始之前进行下环境的检查、或者在测试结束之后作一些清理操作,这就需要对用例进行预处理或后处理。对测试文件中所有的用例进行统一的预处理,可以使用 beforeAll() 函数;而如果想在每个用例开始前进行都预处理,则可使用 beforeEach() 函数。至于后处理,也有对应的 afterAll() 和 afterEach() 函数。

如果只是想对某几个用例进行同样的预处理或后处理,可以将先将这几个用例归为一组。使用 describe() 函数即可表示一组用例,再将上面提到的四个处理函数置于 describe() 的处理回调内,就实现了对一组用例的预处理或后处理:

describe('test testObject', () => {
beforeAll(() => {
// 预处理操作
}) test('is foo', () => {
expect(testObject.foo).toBeTruthy()
}) test('is not bar', () => {
expect(testObject.bar).toBeFalsy()
}) afterAll(() => {
// 后处理操作
})
})

测试异步代码

异步代码的测试,关键点在于告知测试框架测试何时完成,让其在恰当的时机进行断言。针对几种常见的异步代码形式, Jest 也提供了相应的异步测试语法。首先对于异步回调,向其传入并执行 done 函数, Jest 会等 done 回调执行结束后,结束测试:

// asyncHello.js
module.exports = (name, cb) => setTimeout(() => cb(`Hello ${name}`), 1000)
// asyncHello.test.js
let asyncHello = require('asyncHello.js') test('should get "Hello world"', (done) => {
asyncHello('world', (result) => {
expect(result).toBe('Hello world')
done()
})
})

此外,对于 Promise 控制的异步代码,可以直接在 then 回调中进行断言,只要保证在用例中返回该 Promise 对象即可:

// promiseHello.js
module.exports = (name) => {
return new Promise((resolve) => {
setTimeout(() => resolve(`Hello ${name}`), 1000)
})
}
// promiseHello.test.js
let promiseHello = require('promiseHello.js') it('should get "Hello world"', () => {
expect.assertions(1); // 确保至少有一个断言被调用,否则测试失败
return promiseHello('world').then((data) => {
expect(data).toBe('Hello world')
})
})

Jest 也支持 async/await 语法的测试,无需多余的操作,只要在 await 后进行断言即可,和同步测试的写法一致。

测试覆盖率

Jest 内置了测试覆盖率工具istanbul,要开启,可以直接在命令中添加 --coverage 参数,或者在 package.json 文件进行更详细的配置。

运行 istanbul 除了会再终端展示测试覆盖率情况,还会在项目下生产一个 coverage 目录,内附一个测试覆盖率的报告,让我们可以清晰看到分支的代码的测试情况。比如下面这个例子:

// branches.js
module.exports = (name) => {
if (name === 'Levon') {
return `Hello Levon`
} else {
return `Hello ${name}`
}
}
// branches.test.js
let branches = require('../branches.js') describe('Multiple branches test', ()=> {
test('should get Hello Levon', ()=> {
expect(branches('Levon')).toBe('Hello Levon')
});
// test('should get Hello World', ()=> {
// expect(branches('World')).toBe('Hello World')
// });
})

运行 jest --coverage 可看到产生的报告里展示了代码的覆盖率和未测试的行数:

如果我们把branches.test.js中的注释去掉,跑遍测试对象中的所有分支,测试覆盖率就是100%了:

在前端项目中使用

如果对软件测试、接口测试、自动化测试、面试经验交流。感兴趣可以加软件测试交流:1085991341,还会有同行一起技术交流。

搭配React和其它框架

针对前端框架的测试, Jest 的一大特色就是提供了快照测试功能。首次运行快照测试,会让 UI 框架生产一个可读的快照,再次测试时便会通过比对快照文件和新 UI 框架产生的快照判断测试是否通过。对于 React ,我们可以通过下面的方法生产一个快照:

import React from 'react';
import Link from '../Link.react';
import renderer from 'react-test-renderer'; it('renders correctly', () => {
const tree = renderer.create(
<Link page="http://www.facebook.com">Facebook</Link>
).toJSON();
expect(tree).toMatchSnapshot();
});

运行测试,我们可以看到生成一个快照文件如下:

exports[`renders correctly 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
Facebook
</a>
;

这个可读的快照文件以可读的形式展示了 React 渲染出的 DOM 结构。相比于肉眼观察效果的 UI 测试,快照测试直接由Jest进行比对、速度更快;而且由于直接展示了 DOM 结构,也能让我们在检查快照的时候,快速、准确地发现问题。

除了 React ,Jest 文档中也提供了针对其他框架进行测试的指南。

无缝迁移

如果你的项目中已经使用了别的测试框架,比如 Mocha,有一个第三方工具jest-codemods可以自动把用例迁移成 Jest 的用例,降低了迁移成本。

后记:前端自动化测试,值不值得?

近几年前端工程化的发展风起云涌,但是前端自动化测试这块内容大家却似乎不太重视。虽然项目迭代过程中会有专门的测试人员进行测试,但等他们来进行测试时,代码已经开发完成的状态。与之相比,如果我们在开发过程中就进行了测试(直接采用 TDD 开发模式、或者针对既有的模块写用例),会有如下的好处:

  • 保障代码质量和功能的实现的完整度
  • 提升开发效率,在开发过程中进行测试能让我们提前发现 bug ,此时进行问题定位和修复的速度自然比开发完再被叫去修 bug 要快许多
  • 便于项目维护,后续任何代码更新也必须跑通测试用例,即使进行重构或开发人员发生变化也能保障预期功能的实现

当然,凡事都有两面性,好处虽然明显,却并不是所有的项目都值得引入测试框架,毕竟维护测试用例也是需要成本的。对于一些需求频繁变更、复用性较低的内容,比如活动页面,让开发专门抽出人力来写测试用例确实得不偿失。

而那些适合引入测试场景大概有这么几个:

  • 需要长期维护的项目。它们需要测试来保障代码可维护性、功能的稳定性
  • 较为稳定的项目、或项目中较为稳定的部分。给它们写测试用例,维护成本低
  • 被多次复用的部分,比如一些通用组件和库函数。因为多处复用,更要保障质量

以上就是我对前端测试的一点浅见,欢迎斧正。
以上内容就是本篇的全部内容以上内容希望对你有帮助,有被帮助到的朋友欢迎点赞,评论。

前端测试框架 Jest的更多相关文章

  1. 前端测试框架Jest系列教程 -- 简介

    写在前面: 随着互联网日新月异的发展,用户对于页面的美观度,流畅度以及各方面的体验有了更高的要求,我们的网页不再是简单的承载文字,图片等简单的信息传递给用户,我们需要的是更加美观的页面展示,更快的浏览 ...

  2. 前端测试框架Jest系列教程 -- Asynchronous(测试异步代码)

    写在前面: 在JavaScript代码中,异步运行是很常见的.当你有异步运行的代码时,Jest需要知道它测试的代码何时完成,然后才能继续进行另一个测试.Jest提供了几种方法来处理这个问题. 测试异步 ...

  3. 前端测试框架Jest系列教程 -- Matchers(匹配器)

    写在前面: 匹配器(Matchers)是Jest中非常重要的一个概念,它可以提供很多种方式来让你去验证你所测试的返回值,本文重点介绍几种常用的Matcher,其他的可以通过官网api文档查看. 常用的 ...

  4. 前端测试框架Jest系列教程 -- Mock Functions

    写在前面: 在写单元测试的时候有一个最重要的步骤就是Mock,我们通常会根据接口来Mock接口的实现,比如你要测试某个class中的某个方法,而这个方法又依赖了外部的一些接口的实现,从单元测试的角度来 ...

  5. 前端测试框架Jest系列教程 -- Global Functions(全局函数)

    写在前面: Jest中定义了很多全局性的Function供我们使用,我们不必再去引用别的包来去实现类似的功能,下面将列举Jest中实现的全局函数. Jest Global Functions afte ...

  6. 前端测试框架Jest系列教程 -- Expect(验证)

    写在前面 在编写测试时,我们通常需要检查值是否满足某些条件,Jest中提供的expect允许你访问很多“Matchers”,这些“匹配器”允许您验证不同的东西. Expect 可以验证什么 Jest中 ...

  7. 前端测试框架Jest系列教程 -- Mock Functions(模拟器)

    写在前面: 在写单元测试的时候有一个最重要的步骤就是Mock,我们通常会根据接口来Mock接口的实现,比如你要测试某个class中的某个方法,而这个方法又依赖了外部的一些接口的实现,从单元测试的角度来 ...

  8. 前端测试框架jest 简介

    转自: https://www.cnblogs.com/Wolfmanlq/p/8012847.html 作者:Ken Wang 出处:http://www.cnblogs.com/Wolfmanlq ...

  9. 前端测试框架Jest——语法篇

    使用匹配器 使用不同匹配器可以测试输入输出的值是否符合预期.下面介绍一些常见的匹配器.普通匹配器最简单的测试值的方法就是看是否精确匹配.首先是toBe() test('two plus two is ...

随机推荐

  1. PDO::__construct

    PDO::__construct — 创建一个表示数据库连接的 PDO 实例(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0) 说明 语法 PDO::__constru ...

  2. Redis实现商品热卖榜

    Redis系列 redis相关介绍 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合 ...

  3. PHP+Redis实现高并发下商品超卖问题

    对于一些有一定用户量的电商网站,如果只是单纯的使用关系型数据库(如MySQL.Oracle)来做抢购,对数据库的压力是非常大的,而且如果不使用好数据库的锁机制,还会导致商品.优惠券超卖的问题.我所在的 ...

  4. Java助教工作总结

    很荣幸在步入在研究生之际,有机会能协助代老师完成面向对象程序设计(java)课程的教学工作.这也是我人生中第一次接触助教工作,好多东西不太清楚,也没经验,有什么做的不好的,还望老师同学及时指出. 上周 ...

  5. 移动物体监控系统-sprint2摄像头子系统开发

    一.摄像头使能驱动 1.1 摄像头软件系统构架 摄像头采集系统按照上图,硬件(摄像头)->摄像头驱动 ->V4L2接口规范 ->图像采集(应用).V4L2将不同类型的摄像头设备按照统 ...

  6. 使用MPI进行分布式内存编程(2)

    MPI的英文全称为message passing interface,中文名为消息传递接口,他不是一种新的语言,而是一个可以被C,C++,Fortran程序调用的库. 预备知识 1.编译与执行 使用类 ...

  7. 016_go语言中的递归

    代码演示 package main import "fmt" func fact(n int) int { if n == 0 { return 1 } return n * fa ...

  8. day24:多态&魔术方法__new__&单态模式

    目录 1.多态 2.__new__魔术方法 2.1 关于魔术方法__new__ 2.2 基本语法 2.3 __new__ 触发时机快于构造方法 2.4 __new__ 和 __init__ 参数一一对 ...

  9. Docker 快速搭建 MySQL8 开发环境

    使用 Docker 快速搭建一个 MySQL8 开发环境 步骤 获取镜像 docker pull mysql:8 启动容器,密码 123456,映射 3306 端口 docker run --name ...

  10. Python多进程队列间传递对象

    前言 在python 需要在队列中传递对象, 会出现进程不能正常退出的情况. 其原因是因为 在父进程 向子进程传入的Queue对象不对, Queue对象正常是子进程之间的信息传递, 而当我在父进程 创 ...