前端单元测试框架梳理

发表于:2019-5-15 10:12

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:mguy_1    来源:掘金

  作为一个前端,一开始并不知道单元测试的好处,觉得费时费力,效果也不明显,直到有个模块因为性能问题进行了一次重构,被折磨得筋疲力尽的时候,才发现单元测试的好处,可以说,有了单元测试,才能面对其他同事写的或者n年以前的代码,放心大胆的对其进行持续的维护甚至重构。
  单元测试有别于集成测试,是对最小可测试单元(一般为单个函数或小组件)进行检查和验证。功能越简单越好,单个验证其他变量影响越少越好,这样能达到最好的效果。好的单元测试用例可以充当开发文档供后人阅读。
  断言库 chai
  单元测试的核心就是断言,通过断言来判断代码是否达到目的
  node内置断言assert,以下图为最简单例子,如果错误会抛出异常
  chai这个断言库很全很强大,提供了常用的assert should expect断言关键字
  各类的用法就不提了,方法比较简单,一查便知。assert最简单,不过目前expect用得比较多,例如expert(xxx).toBe(xxxx)。但是egg官网推荐assert,理由是简单,不用记一些复杂api。
  Mocha
  Mocha是老牌的库,简单全面易用,目前公司就在用Mocha+chai测试前端数据逻辑,用来测试node,util里面的函数都可以,测试组件需要搭配其他框架。
  Mocha测试的钩子
  Mocha在describe块之中,提供测试用例的四个钩子:before()、after()、beforeEach()和afterEach()。
  可以用before钩子提前把测试环境和数据准备好,beforeEach钩子可以在每个测试用例前准备一个或多个新的对象,防止被前面的用例污染
   describe('测试index.js',()=> {
  before(()=>console.info("在本区块的所有测试用例之前执行"))
  after(()=>console.info("在本区块的所有测试用例之后执行"))
  beforeEach(()=>console.info("在本区块的每个测试用例之前执行"))
  afterEach(()=>console.info("在本区块的每个测试用例之后执行"))
  describe('测试addNum函数', ()=> {
  it('两数相加结果为两个数字的和', ()=> {
  assert.equal(addNum(1,2),3)
  })
  })
  })
   最后,Mocha默认每个测试用例最多执行2000毫秒,如果到时没有得到结果,就报错,
  而且Mocha默认会高亮显示超过75毫秒的测试用例,可修改
  sinon
  sinon具有非常有特色的spies, stub, mock三个功能,有兴趣的可以尝试手写实现。
  spies的概念
  spies => 间谍函数,间谍函数是Sinon最简单的部分,其它的功能都是建立在spies之上的,spies的主要用途是收集有关函数调用的信息,例如是否调用了函数等。spies的实现监听的基础上是不会影响函数本身正常调用(被监听的函数的上下文关系不会被影响)。
  stub的概念
  stub完全取代了这个函数,而且拥有spies的所有功能。当使用stub时,函数将不具有原始的功能,而是替换后的函数。
  mock的概念
  mock与stub的功能一样都是用来替换指定的函数,如果你想替换掉一个对象中的多个方法,这时mock就可以发挥作用了,但是如果仅仅是替换对象中的一个函数,那么stub更加简单易用,当我们使用mock的时候应该十分小心,因为大量的替换原有代码逻辑,会导致test变的脆弱。
  nock或者moxios
  用来模拟发送网络请求,需要替代后台接口时使用。
  Karma
  非jsdom,提供真实浏览器环境,由于目前各类框架已经比较完善了,现在已经基本被排除在主流框架之外
  redux-mock-store
  顾名思义,用于模拟 redux 中的 store。由于工作中一直用mobx,这里不多做介绍了
  jasmine
  使用与jest类似,以前通常和karma配合,大而全的测试框架(jest)成为主流后,用的少了
  jest
  jest 是facebook推出的一款测试框架,集成了Mocha,chai,jsdom,sinon等功能。所以刚入门的同学如果想应用直接可以上jest。
  react官方脚手架自带jest,vue-cli3.0中也集成了单元测试框架,选择的时候会问你选mocha+chai还是jest。
  运行命令 jest 后会自动运行项目下所有.test.js和.spec.js这种格式的文件。jest的配置默认只要在package.json中配置即可,如只测test文件夹下test.jsx文件
   "jest": {
  "testRegex": "/test/*.test.jsx?$"
  }
  集成expect断言
  异步处理 对于callback采用done()确保完成测试,对于promise自动处理,遇到reject自动抛出错误,async+await同理
  Jest 中的 mock ,
  类似于sinon的 sinon,并且还可以模拟axios的网络请求
  快照snapshot 对组件或者数据生成一份快照,每次测试自动深比较,不一致就报错
  可以生成测试覆盖率报告,只需要在jest命令后加入 --coverage即可
  jest --coverage
  enzyme && test-utils
  airbnb公司推出的 enzyme ,专门用来测试react组件,相对应vue中也有test-utils包,基本是一样的功能,也是对组件挂载后进行事件触发、元素存在等判断。
  这里以enzyme为例讲解,enzyme主要提供三种渲染方式:render、mount、shallow,存在以下区别:
  render渲染结果是普通的html结构,shallow和mount对组件的渲染结果是react树,如果你用过chrome的react devtool插件,他的渲染结果就是react devtool tab下查看的组件结构。
  shallow和mount的返回结果是个被封装的ReactWrapper,可以进行多种类似JQ的链式操作,譬如find()、parents()、children()等选择器进行元素查找;state()、props()进行数据查找,setState()、setprops()操作数据;simulate()模拟事件触发。
  shallow只渲染当前组件,只对当前组件做断言,不会产生子组件;mount会渲染当前组件以及所有子组件,对所有子组件也可以做上述操作。一般交互测试都会关心到子组件,我使用的都是mount。但是mount耗时更长,内存啥的也都占用的更多,如果没必要操作和断言子组件,一般使用shallow。
  总结
  单元测试属于需要投入,但是看不见产出的工作,所以直接选择最简洁的框架,节约时间,才是提升kpi的关键,现在的框架越来越趋向简单和人性化,所以如果工作中使用,直接选jest类集成框架就好。
  我在的toB传统软件服务公司,前端的稳定性更加重要,在一个产品快速迭代期后,单元测试也会逐步进行覆盖util模块和model层(响应action的数据变化处理),其它则需要看迭代排期,经常重构的基础公共组件也会排上。每个公司需求不同,如果是上线就撤的项目,可以不用部署测试。考虑引进单元测试前,请灵活考虑成本和收益

     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号