前端单元测试杂淡

1,521 阅读9分钟

本文不涉及单元测试的具体实践,主要是对前端开发者进行单元测试的小科普,具体测试框架的引入,测试案例的编写本文没有涉及。

前端单元测试是什么

我们先来了解一下开发阶段测试分类

UT(BaiUnit Test)即软件测试分类中的单元测试,它是对程序中的最小可测单元进行测试,一般理解的单元测试就是针对代码的测试, 比如js中的一个函数,项目中的一个组件,此种测试要求测试人员具备很强的编码能力,主要是开发自测为主

IT (System Integration Test)即软件测试分类中的集成测试,它是在单元测试的基础上,将软件的各单元(功能模块)按照概要设计说明书针对模块、子系统、系统的组装测试,以此来检验系统的各部分是否能满足相应的技术指标和要求,集成测试需要重点关注各个模块之间的接口;

ST(System Test)即软件测试分类中的系统测试,它是将软件作为一个整体来进行测试,主要关注计算机硬件、外部设备、第三方软件、数据和人员等系统元素及环境因素等等。

UAT(User Acceptance Test)即软件测试分类中的验收测试,主要是由客户主导按照签订的合同、技术协议以及需求说明规格书来检验软件实施方实现的软件是否满足客户业务方的需求

单元测试,是为了测试某一个类的某一个方法能否正常工作,而写的测试代码。 为检测特定的目标是否符合标准而采用专用的工具或者方法进行验证,并最终得出特定的结果。 对于前端开发过程来说,这里的特定目标就是指我们写的代码,而工具就是我们需要用到的测试框架(库)、测试用例等。检测处的结果就是展示测试是否通过或者给出测试报告,这样才能方便问题的排查和后期的修正。

说了这么多,可能还是不知道什么是前端单元测试,那我们先从几个不是开始了解单元测试

  • 需要访问数据库的测试不是单元测试
  • 需要访问网络的测试不是单元测试
  • 需要访问文件系统的测试不是单元测试

哪些又是单元测试的行为呢?

  • 它是一种验证行为 程序中的每一项功能都是测试来验证它的正确性。它为以后的开发提供支援。就算是开发后期,我们也可以轻松的增加功能或更改程序结构,而不用担心这个过程中会破坏重要的东西。而且它为代码的重构提供了保障。这样,我们就可以更自由的对程序进行改进。
  • 是一种设计行为 编写单元测试将使我们从调用者观察、思考。特别是先写测试(Test First),迫使我们把程序设计成易于调用和可测试的,即迫使我们解除软件中的耦合
  • 它是一种编写文档的行为 单元测试是一种无价的文档,它是展示函数或类如何使用的最佳文档。这份文档是可编译、可运行的,并且它保持最新,永远与代码同步。
  • 它具有回归性 自动化的单元测试避免了代码出现回归,编写完成之后,可以随时随地的快速运行测试

前端单元测试的意义

  • 大规模代码重构时,保证重构的正确性, 保证代码的质量, 验证功能完整性
  • TDD(测试驱动开发) 被证明是有效的软件编写原则,它能覆盖更多的功能接口。
  • 快速反馈你的功能输出,验证你的想法
  • 保证代码重构的安全性,没有一成不变的代码,测试用例能给你多变的代码结构一个定心丸。
  • 易于测试的代码,说明是一个好的设计。做单元测试之前,肯定要实例化一个东西,假如这个东西有很多依赖的话,这个测试构造过程将会非常耗时,会影响你的测试效率,怎么办呢?要依赖分离,一个方法类尽量保证功能单一,比如视图与功能分离,这样的话,你的代码也便于维护和理解。

为什么需要前端单元测试

正确性: 测试可以验证代码的正确性,在上线前做到心里有底。

自动化: 当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到保证。通过编写测试用例,可以做到一次编写,多次运行。

解释性: 测试用例用于测试接口、模块的重要性,那么在测试用例中就会涉及如何使用这些API。其他开发人员如果要使用这些API,那阅读测试用例是一种很好地途径,有时比文档说明更清晰。

驱动开发,指导设计: 代码被测试的前提是代码本身的可测试性,那么要保证代码的可测试性, 强迫开发者写可测试的代码,一般来说可测试的代码可读性也比较好

保证重构: 互联网行业产品迭代速度很快,迭代后必然存在代码重构的过程,那怎么才能保证重构后代码的质量呢?有测试用例做后盾,就可以大胆的进行重构。

单元测试用例的原则

  • 测试代码时,只考虑测试,不考虑内部实现
  • 数据尽量模拟现实,越靠近现实越好
  • 充分考虑数据的边界条件
  • 对重点、复杂、核心代码,重点测试
  • 减少测试代码数量,避免无用功能
  • 测试、功能开发相结合,有利于设计和代码重构

常用的单元测试方法论

TDD(测试驱动开发)

TDD的过程: 需求分析,思考实现。考虑如何“使用”产品代码,是一个实例方法还是一个类方法,是从构造函数传参还是从方法调用传参,方法的命名,返回值等。这时其实就是在做设计,而且设计以代码来体现

一句话简单来说,就是先写测试,后写功能实现。TDD的目的是通过测试用例来指引实际的功能开发,让开发人员首先站在全局的视角来看待需求。

就个人而言,TDD不是一个技术,而是一种开发的指导思想。在目前互联网的开发环境下,业务开发很难做到TDD开发,一是因为需要更多时间编写单元测试用例;二是要求非常了解业务需求;三是要求开发人员有很强的代码设计能力。但是当我们写组件、工具方法、类库的时候,TDD就可以得到很好地使用。

BDD(行为驱动开发)

行为驱动开发(BDD),重点是通过与利益相关者(简单说就是客户)的讨论,取得对预期的软件行为的认识,其重点在于沟通

从业务的角度定义具体的,以及可衡量的目标

找到一种可以达到设定目标的、对业务最重要的那些功能的方法

然后像故事一样描述出一个个具体可执行的行为。其描述方法基于一些通用词汇,这些词汇具有准确无误的表达能力和一致的含义。例如,expect, should, assert

寻找合适语言及方法,对行为进行实现

测试人员检验产品运行结果是否符合预期行为。最大程度的交付出符合用户期望的产品,避免表达不一致带来的问题

前端单元测试个人理解

单元测试的首要目的不是为了能够编写出大覆盖率的全部通过的测试代码,而是需要从使用者(调用者)的角度出发,尝试函数逻辑的各种可能性,进而辅助性增强代码质量

  • 测试试是手段而不是目的。测试的主要目的不是证明代码正确,而是帮助发现错误,包括低级的错误
  • 测试要快。快速运行、快速编写
  • 测试代码保持简洁。
  • 不会忽略失败的测试。一旦团队开始接受1个测试的构建失败,那么他们渐渐地适应2、3、4或者更多的失败。在这种情况下,测试集就不再起作用

长期以来,前端开发的单元测试并不是在前端的开发过程中所必须的,也不是每个前端开发工程师所注意和重视的,甚至扩大到软件开发过程中单元测试这一环也不是在章程上有书面规定所要求的。但是随着每个工程的复杂化、代码的高复用性要求和前端代码模块之间的内聚耦合的需求,前端工程中的单元测试流程就显得很有其必要。

是否引入自动化测试

引入自动化测试是有成本的。在实施自动化测试之前需要对软件开发过程进行分析,基于投入产出来判断是否适合实施自动化测试。实施自动化测试的项目通常需要同时满足以下条件:

需求变动不频繁+项目周期足够长+自动化测试脚本可重复使用+代码规范可测试

如果需求变动过于频繁,维护测试脚本的成本太高;如果项目周期比较短,没有足够的时间去支持自动化测试的过程;如果测试脚本重复使用率低,耗费的精力大于创造的价值,不值得;如果代码不规范,可测试性差,那自动化测试实施起来会比较困难。