众所周知的原因,前端作为一种特殊的 GUI 软件,做自动化测试困难重重。在快速迭代,UI 变动大的业务中,自动化测试想要落地更是男上加男 🐶。
近期的学习过程中,翻阅了众多前端自动化测试相关的文章,大多数都在讲如何使用自动化测试框架对前端代码进行测试,很少讲解为什么要引入自动化测试,引入自动化测试有哪些好处,哪些项目适合引入自动化测试,但这些才是真正我们想要知道的。
考虑到各位读者爸爸们可能没有接触过自动化测试的内容,这篇文章就从基本概念和基础用法入手,为大家讲解自动化测试的内容。
开始之前,先进行一下前戏(可能比较长,不喜欢的可以快进 🐶):
情景还原
小王是国内一家大厂的前端开发。就在述职前一周,产品经理给了一个需求,要求在老项目上加上新的功能。
小王打开老项目代码,定睛一看,心头一紧 —— 要改的组件已经长达 800 多行,快速扫一眼,发现还没有注释。 小王哭了,但产品经理要求 3 天内实现新功能,没办法,只能硬着头皮写了。
小王准备开始写了,对新功能大致做了一下技术分析,发现与老代码的耦合比较厉害,于是就开始一边写,一边阅读和修改老代码。
老代码又臭又长,小王发现有一段代码不知道为什么要对输入文本做处理,觉得是一段没有用的代码,还影响到自己添加新功能,于是小王把这段代码删掉了。
新功能按期完成,小王经过了简单的手工自测,没有问题,于是就发送了提测邮件,等待测试反馈,开开心心准备述职去了。
对新功能的测试也顺利通过,小王将新功能发布上线,结束了这周的工作,回家享受周末了。
小王早早地洗漱完上床睡觉了,突然大半夜老板打电话过来:小王,快起来,出 BUG 了,影响了 1w+ 的用户,快起来看看什么问题!
小王猛地起身,从背包里取出电脑,开始排查 BUG 出现的原因,一顿 debug 之后,发现竟然是自己删掉的那段老代码导致了 BUG!
小王又一次哭了,修复好 BUG,紧急发布上线。
“下周一就述职了,今天出这么个 BUG,年终奖肯定没了,普调估计也悬。还要写 case 报告抄送大部门,丢人丢到家了。”
但是如果公司的老项目引入了自动化测试,后来的故事就完全不一样了:
情景反转
小王准备开始写了,对新功能大致做了一下技术分析,发现与老代码的耦合比较厉害,于是就开始一边写,一边阅读和修改老代码。
老项目的前端开发为了保证项目能够正常运行,编写了单元测试和集成测试的代码,在 README 里要求维护的同事要在添加/修改了代码之后跑一遍测试用例。
老代码又臭又长,小王发现有一段代码不知道为什么要对输入文本做处理,觉得是一段没有用的代码,还影响到自己添加新功能,于是小王把这段代码删掉了。
小王删掉代码之后跑测试用例,突然好几个刺眼的红色字符映入眼帘 —— FAIL TO TEST
一看测试用例描述,小王这才知道这段代码的作用。于是小王对这段代码做了重构,同时也加上了新功能,跑一遍测试用例 —— 全是绿色的 PASS。
小王长舒一口气,给自己的新功能也加上了测试用例,修修改改让新加的测试用例也跑通了。
虽然小王因为编写测试用例稍微加班了一会,但是他感觉一身轻松,非常有安全感。
提测、发布一切正常,小王享受了一个愉快的周末。
下周回来之后述职,心情大好,状态极佳,得到老板们的赞赏。绩效评定棒棒哒,年终奖和普调都没问题。
上面的故事都是我 YY 的,如有雷同纯属巧合 🐶。
什么是测试?
测试其实就是在已经开发完成的软件之上采用人工或非人工的方式验证软件是否符合工程预期,是否会造成用户/开发商损失等潜在问题的一种方式。
大多数情况下,我们编写的前端代码都是开发手工自测,又或是提测后由专门的测试人员手工测试。
手工测试当然也是没有问题的,但是通过自动化的测试工具,可以更加快速高效且准确定位问题所在。
自动化测试实际上是运行一段测试代码,去验证目标代码是否满足某个期望。
本文后续的内容中,“测试”一词将专门指代自动化测试。
为什么要测试?
我们进行测试的目的在于,及时发现错误,提高代码质量和开发效率,避免存在 BUG 的代码发布上线造成损失。
测试自动化的好处在于反馈及时,能够极大地提高前端的开发效率。
在我们日常的开发过程中,是不是经常需要在项目跑起来之后去人工测试某些操作或者流程是否能够正常运行?是不是经常需要打断点或者使用 console.log
查看控制台信息来检查某个函数是否执行?
这些需要我们自己手工测试代码的执行结果是否符合预期的场景,完全可以使用自动化测试的脚本代替。
现有的很多成熟的自动化测试框架完全可以模拟我们的手工操作,使用脚本自动运行测试用例,通常只需要几秒就能给出准确的反馈,同时还能侦听代码变化,自动执行项目中发生了变化的代码对应的测试用例,能够极大提高我们的开发效率。
在公司业务和人员变动都比较快的当下,编写自动化测试脚本的收益越来越高。开发者再也不用害怕引入回归 BUG,也再也不用害怕把代码交给他人维护。有了测试脚本的约束,迭代/重构都能更加从容。
测试自动化的收益=迭代次数×全手动执行成本−首次自动化成本−维护次数×维护成本测试自动化的收益 = 迭代次数 \times 全手动执行成本 - 首次自动化成本 - 维护次数 \times 维护成本测试自动化的收益=迭代次数×全手动执行成本−首次自动化成本−维护次数×维护成本
有哪些测试类型?
前端测试主要分为 3 种:单元测试(Unit Test)、集成测试(Integration Test)、UI 测试(UI Test)
三种测试的占比分别为:
现实是,大多数公司的测试金字塔是倒过来的,由人工进行UI 测试反而是最多的,集成测试和单元测试却大多被忽略。
单元测试(Unit Test)
单元测试是最容易实现的:代码中多个组件共用的工具类库、多个组件共用的子组件等。
通常情况下,在公共函数/组件中一定要有单元测试来保证代码能够正常工作。单元测试也应该是项目中数量最多、覆盖率最高的。
能进行单元测试的函数/组件,一定是低耦合的,这也从一定程度上保证了我们的代码质量。
集成测试(Integration Test)
集成测试通常被应用在:耦合度较高的函数/组件、经过二次封装的函数/组件、多个函数/组件组合而成的函数/组件等。
集成测试的目的在于,测试经过单元测试后的各个模块组合在一起是否能正常工作。会对组合之后的代码整体暴露在外接口进行测试,查看组合后的代码工作是否符合预期。
集成测试是安全感较高的测试,能很大程度提升开发者的信心,集成测试用例设计合理且测试都通过能够很大程度保证产品符合预期。
UI 测试(UI Test)
在我学习查阅文献的过程中,我发现国内不少文章都将 UI 测试(UI Test)和端到端测试(E2E Test)混为一谈,认为是同一个测试类型。
事实上,UI 测试(UI Test)和端到端测试(E2E Test)是稍有区别的:
UI 测试(UI Test)只是对于前端的测试,是脱离真实后端环境的,仅仅只是将前端放在真实环境中运行,而后端和数据都应该使用 Mock 的。
端到端测试(E2E Test)则是将整个应用放到真实的环境中运行,包括数据在内也是需要使用真实的。
就前端而言,UI 测试(UI Test)更贴近于我们的开发流程。在前后端分离的开发模式中,前端开发通常会使用到 Mock 的服务器和数据。因而我们需要在开发基本完成后进行相应的 UI 测试(UI Test)。
UI 测试的自动化程度还不高,大多数还依赖于手工测试。
在一些自动化测试工具中有创建快照的功能,也能帮助我们在一定程度上实现 UI 测试(UI Test)的自动化。
哪些项目适合引入自动化测试?
目前市面上的大多数文章都没有讲过这个问题,但事实上这个问题是最值得思考的!
在化学上有一句名言:
抛开剂量谈毒性都是耍流氓。
同理,在前端自动化测试方面,抛开项目类型、软件开发的人员配置和生命周期而谈论自动化测试的好处和必要性,也是耍流氓。
于我个人而言,我比较喜欢写测试代码,当看到测试用例都全部 PASS 都是绿色的时候,非常舒服。
但我猜大部分的开发都会觉得:需求这么多,这么紧急,保证完成需求都已经非常困难了,已经没精力再编写测试代码了。
现实中,我们经常会针对一些活动开发一些一次性的代码模块,这样的代码模块功能简单,且后续继续迭代的可能性低,这种代码就完全没有必要引入自动化测试工具。
适合引入自动化测试的场景:
- 公共库类的开发维护
- 中长期项目的迭代/重构
- 引用了不可控的第三方依赖
这些场景是需要引入自动化测试来对现有代码进行约束的。尤其是中长期项目,迭代/重构时人力回归困难,自动化测试就显得尤为重要!
如何选择测试工具?
现在市面上有很多流行的测试工具,但普遍都存在一个问题:新特性的支持滞后。
前端测试的框架可谓是百花齐放。
- 单元测试(Unit Test)有 Mocha, Ava, Karma, Jest, Jasmine 等。
- 集成测试(Integration Test)和 UI 测试(UI Test)有 ReactTestUtils, Test Render, Enzyme, React-Testing-Library, Vue-Test-Utils 等。
主流测试工具比较
框架 | 断言 | 仿真 | 快照 | 异步测试 |
---|---|---|---|---|
Mocha | 默认不支持,可配置 | 默认不支持,可配置 | 默认不支持,可配置 | 友好 |
Ava | 默认支持 | 不支持,需第三方配置 | 默认支持 | 友好 |
Jasmine | 默认支持 | 默认支持 | 默认支持 | 不友好 |
Jest | 默认支持 | 默认支持 | 默认支持 | 友好 |
Karma | 不支持,需第三方配置 | 不支持,需第三方配置 | 不支持,需第三方配置 | 不支持,需第三方配置 |
Mocha
- Mocha 是生态最好,使用最广泛的单测框架,但是他需要较多的配置来实现它的高扩展性。
Ava
- Ava 是更轻量高效简单的单测框架,但是自身不够稳定,并发运行文件多的时候会撑爆 CPU。
Jasmine
- Jasmine 是单测框架的“元老”,开箱即用,但是异步测试支持较弱。
Jest
- Jest 基于 Jasmine, 做了大量修改并添加了很多特性,同样开箱即用,但异步测试支持良好。
Karma
- Karma 能在真实的浏览器中测试,强大适配器,可配置其他单测框架,一般会配合 Mocha 或 Jasmine 等一起使用。
每个框架都有自己的优缺点,没有最好的框架,只有最适合的框架。Augular 的默认测试框架就是 Karma + Jasmine,而 React 的默认测试框架是 Jest。
Jest 被各种 React 应用推荐和使用。它基于 Jasmine,至今已经做了大量修改并添加了很多特性,同样也是开箱即用,支持断言,仿真,快照等。Create React App 新建的项目就会默认配置 Jest,我们基本不用做太多改造,就可以直接使用。
采用何种测试思想?
TDD:Test-Driven Development(测试驱动开发)
- TDD:Test-Driven Development(测试驱动开发):TDD 则要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过测试来推动整个开发的进行
BDD:Behavior-Driven Development(行为驱动开发)
- BDD:Behavior-Driven Development(行为驱动开发):BDD 可以让项目成员(甚至是不懂编程的)使用自然语言来描述系统功能和业务逻辑,从而根据这些描述步骤进行系统自动化的测试
Jest 基本语法
由于大厂普遍使用 React/Vue 进行开发,而 React/Vue 官方推荐的单元测试工具都是 Jest,因此本文我们就简单介绍一下 Jest 的基本语法。
匹配器
Number
String
Array & Iterable
Exception
异步代码测试
生命周期钩子
生命周期钩子执行顺序符合洋葱模型。
执行顺序
测试单元/用例执行顺序类似异步队列
函数 Mock
小结
本篇文章介绍了前端自动化测试的一些基本概念和主流测试框架 Jest 的基础用法。
相信看完本篇为文章,你一定对前端自动化测试有了一定的了解。
总结:
感谢每一个认真阅读我文章的人!!!
作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。
-
文档获取方式:
-
加入我的软件测试交流群:680748947免费获取~(同行大佬一起学术交流,每晚都有大佬直播分享技术知识点)
这份文档,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
以上均可以分享,只需要你搜索vx公众号:程序员雨果,即可免费领取