0


前端单元测试

什么是前端单元测试?

  1. 为检测特定的目标是否符合标准而采用专用的工具或者方法进行验证,并最终得出特定的结果。
  2. 对于前端开发过程来说,这里的特定目标就是指我们写的代码,通过写的测试用例检查的结果展示测试是否通过或者给出测试报告,这样才能方便问题的排查和后期的修正
  3. 对于给定的输入,单元测试检查结果。通过及早发现问题并避免 bug 回归,它可以帮助我们确保代码的各个部分按预期工作。

为什么需要单元测试?

前端的单元测试在很多人看来都是一个可有可无的东西,理由一般有下面几条:

  • 写单测比较费时,有这个时间不如多做几个需求
  • 测试在验收的时候对页面的功能都会操作一遍,写单测相当于做无用功
  • 后端提供给前端的接口需要保证质量,因此需要做单测,但前端很少需要提供接口给其他人

其实,我大体上是同意以上观点的。在大部分的情况下,如果公司的业务不复杂,是完全没必要做单测的。但如果涉及到以下几个方面,就要考虑是否有必要引入单测了:

  • 业务比较复杂,前端参与的人员超过3人
  • 公司非常注重代码质量,想尽一切办法杜绝线上出bug
  • 你是跨项目组件的提供方 你在做一个开源项目

单测的好处:减少bug,提升代码可读性可维护性,为系统重构做铺垫。

单元测试覆盖率

含义:软件测试中的一种度量指标,指在所有功能代码中,完成了单元测试的代码所占的比例。具体分为行级、分支级、方法级等不同级别。它可以从一定程度上衡量我们对代码测试的充分性。原则上我们追求的单元测试覆盖率目标是100%,但业务场景多的情况几乎是不可能。
平台类项目,核心复杂功能尽量覆盖率做到最高,业务类的酌情处理。
目标覆盖率
行覆盖率(line coverage):表示是否每一行都执行 80%
函数覆盖率(function coverage):表示是否每个函数都调用 100%
分支覆盖率(branch coverage):表示是否每个if代码块都执行 80%
语句覆盖率(statement coverage):表示是否每个语句都执行 80%

前端单测规范

在单测工作开展前,需要先约定好单测相应的一系列规范:

1.测试文件统一在 src/tests 目录中维护 或者 与组件同级目录 如 button.test.tsx 跟button.tsx 文件同级。
2.测试文件命名与React组件命名保持一致,后面以.test.tsx结尾
3.测试用例使用

it("功能描述",()=>{})

函数描述用例单元
针对最小功能单元的测试用例主要集中在该函数内 尽量一个测试用例只做一件事情(每个测试用例一个it函数代表)。字符串代表测试用例名称:常用命名模式“被测对象在什么情况下是什么行为”
4.一组功能集合测试使用

describe("功能集合描述",()=>{})

函数描述功能集合
一个测试文件只能描述一个功能集合,这个功能集合可以是一个React组件,也可以是一个公共模块,公共函数,公共配置。尽量每次编写测试用例都用describe包裹进行分块。

  • UI测试套件统一使用enzyme 使用enzyme可以借助jquery like的选择器方便的对DOM渲染结果做校验

React组件测试用例必须包含:

  • Snapshot快照比对
  • Props是否正确传入
  • 组件分支渲染
  • 事件调用和参数传递
  • 函数调用,state状态值的改变
  • 页面跳转回应

针对这一点我们可以根据这些维度来对我们的代码进行测试:

  • 某个子组件,标签,CSS class类 在组件中的个数,长度
  • 某个标签下文本内容是否一致
  • 标签类型
  • 组件中函数调用是否符合预期,模拟调用该函数给定参数能否与预期结果一致
  • 针对公共js库模块进行快照测试,确保当次更改是否需要
  • 在执行某些操作后state的状态值是否发生改变,某个标签元素是否渲染

单测框架技术选型

目前比较流行的React单测组合是Jest+Enzyme
Jest
Jest是Facebook开发的一个测试框架,它集成了测试执行器、断言库、spy、mock、snapshot和测试覆盖率报告等功能。React项目本身也是使用Jest进行单测的,因此它们俩的契合度相当高。
它具有特点:

  • 开箱即用,配置少,API简单,上手成本极低在沙箱中运行,更加安全
  • 支持断言和仿真
  • 自动生成测试覆盖率报告
  • 通过生成Snapshot 进行UI 测试单测执行效率

Enzyme
Enzyme是由airbnb开发的React单测工具。它针对类 react 组件提供了很多关于 UI 渲染,元素查找,事件触发等相关的 API 和匹配器,可以帮助我们更加高效的完成单测编写。它扩展了React的TestUtils并通过支持类似jQuery的find语法可以很方便的对render出来的结果做各种断言。

  • 方便操作 Dom 且操作风格模拟了jQuery的APi,比较直观,学习使用都比较简单
  • 便利的工具函数库封装,可以处理浅渲染,静态渲染标记以及DOM渲染。

Jest详解

详见那些年错过的React组件单元测试(上)
环境搭建
可以运行npx jest --init在根目录生成配置文件jest.config.js,一般部门现成的项目已经配置好了这些,实际用到再去搜这些配置项吧。
匹配器
toBe(value):使用 Object.is 来进行比较,如果进行浮点数的比较,要使用 toBeCloseTo
not:取反
toEqual(value):用于对象的深比较
assertions(number):验证在一个测试用例中有 number 个断言被调用
resolves:用来取出 promise 为 fulfilled 时包裹的值,支持链式调用
rejects:用来取出 promise 为 rejected 时包裹的值,支持链式调用
…………
命令行工具
在项目package.json文件添加如下script:“test”: “jest --watchAll”,
npm run test。有几种模式。
钩子函数
类似于react的生命周期,共有四种:
beforeAll():所有测试用例执行之前执行的方法
afterAll():所有测试用例跑完以后执行的方法
beforeEach():在每个测试用例执行之前需要执行的方法
afterEach():在每个测试用例执行完后执行的方法
Jest测试异步代码的三种方案
done关键字;返回promise;async/await
Mock
jest中与mock相关的api主要有三个,分别是jest.fn()、jest.mock()、jest.spyOn()。
Snapshot 快照测试
toMatchSnapshot:当使用toMatchSnapshot的时候,Jest 将会渲染组件并创建其快照文件。这个快照文件包含渲染后组件的整个结构,并且应该与测试文件本身一起提交到代码库。当我们再次运行快照测试时,Jest 会将新的快照与旧的快照进行比较,如果两者不一致,测试就会失败,从而帮助我们确保用户界面不会发生意外改变。

Enzyme详解

详见那些年错过的React组件单元测试(下)
常用函数
simulate(event, mock):用来模拟事件触发,event为事件名称,mock为一个event object;
instance():返回测试组件的实例;
…………
渲染方式
enzyme 支持三种方式的渲染:shallow:浅渲染,render:静态渲染,mount:完全渲染。
shallow: 主要适合不受子组件行为影响的单组件测试,因为它不会渲染被测试组件的子组件
mount: 主要适合测试存在 dom 操作的组件以及高阶组件, 它会全量渲染父组件和父组件下的子组件,并且是真实的dom渲染(node 环境下通常通过 jsdom 来模拟环境)。
render: 主要用于生成组件的 html 结构, 非常适合用于做快照测试。

单测实践

写单测和后期维护是需要一定成本的,我们一般只针对核心底层的模块书写单元测试,如组件和js公共函数。
一、组件的单测
阅读toft.react.mobile的readme.md,需要先npm run init ,再npm run generate,这两个命令主要是为了下载node_modules依赖,(watching可以自动把md文档转换为site里的tsx)之后另起终端,npm start。
在每一个组件文件夹下面的tests文件夹下面写单测:
index.test.tsx:主要是测props,看入参出参是否正确。props在type.ts文件里可以看。
对于前端组件来说,其核心测试的内容包括三个方面:渲染测试,事件行为测试以及 snapshot 测试。
渲染测试:
渲染测试主要是为了测试组件在各种输入条件下是否能够完成正常渲染,这是对一个组件最基本的要求,但也是我们日常遭遇 bug 的重灾区,常见的情形是测试或业务同学反馈页面白屏,然后反馈给前端,前端排查到是因为后端返回了不符合约定的数据格式导致前端代码报错。如果我们能在单测阶段就发现此类问题,就能避免很多提测阶段的 bug 反馈和线上故障的发生。因此,渲染测试是组件单测中最基本也是最重要的测试。
在组件的渲染测试方面,enzyme 提供了三个不同类型的 API,分别针对三种不同的场景:shallow:浅渲染,render:静态渲染,mount:完全渲染。
事件行为测试:
对于一个 UI 组件来说,通常不仅包含了 UI 渲染,也会有事件绑定来响应用户行为。在渲染测试的基础上,我们也需要测试当绑定的事件触发后,组件代码的执行结果是否会符合我们的预期。最典型的 case, 比如购物车中的商品组件,当我点击数量加减时,商品数量的状态是否会如期更新呢,以及组件内有一个点击某个按钮拉起弹窗的行为,当我点击该按钮后,弹窗真的会拉起吗?这些都是可以通过单元测试来保障的。
针对组件的事件行为测试,enzyme 提供了模拟触发 dom 事件的能力。
核心的点在于当组件中所绑定的事件触发时,你需要根据自己对该事件触发后所期望的输出结果来编写测试用例,从而来验证你编写的事件响应逻辑是否正确。
snapshot 测试:
snapshot 测试也称之为快照测试,它对于组件的 UI 渲染测试来说是一个非常有效的补充,当完成初次渲染时它会针对渲染的组件结构保存一个快照文件。当再次运行快照测试时,它会将新的快照与旧的快照进行一次比对,如果比对不一致,测试用例便不会通过,你可以用快照测试来防止组件发生意外的 UI 变更。

npm run test 让我们边写测试文件边debug;可以一个测试用例一个测试用例去过,过了一个再写下一个。
npm run test:coverage 命令用于写完测试文件生成一个文档看覆盖率,最后在test/coverage/Icov-report/index.html里看覆盖率报告,用访达打开。

标签: 前端 单元测试

本文转载自: https://blog.csdn.net/weixin_44915595/article/details/125638907
版权归原作者 bdundun 所有, 如有侵权,请联系我们删除。

“前端单元测试”的评论:

还没有评论