单元测试是高效的开发过程质量控制机制,帮助企业保证产品质量、降低成本、提高生产率、缩短开发周期、赢得市场先机,提升竞争力。

  1、保证代码质量

  仅依靠系统测试会存在大量未覆盖的“死角”,单元测试可以对各个代码单元彻底测试,保证代码质量。针对一个函数,单元测试可以覆盖输入数据的所有分类,做到不管输入什么数据,函数本身的处理都符合设计,从而全面检测其功能逻辑,消灭可能隐藏的大量细小错误,这种测试效果是其他测试难于做到的。输入数据的“分类”,称为“等价类”,即测试效果上的等价,同类数据中只需要测试一个,相当于测试了同类中的所有数据。这种设计用例的方法叫做“等价类法”。

  2、降低排错成本

  排错包括“验证是否有错”、“找出错在哪里”、“修正错误”三个工作。单元测试的目标小,涉及代码少,发现错误后排错容易。Bug发现得越晚,修改所需费用越高,因此应该尽早查找和修改Bug,单元测试提供了尽早抓住Bug的好机会。相比后续阶段的测试,单元测试的创建更简单,维护更容易,并且可以更方便地进行重复。从全程费用来考虑,相比复杂且旷日持久的集成测试、系统测试,单元测试所需的费用是很低的。下图摘自<<实用软件度量>>(Capers Jones, McGraw-Hill 1991),它列出了准备测试、执行测试、和修改缺陷所花费的时间(以一个功能点为基准),这些数据显示单元测试的成本效率大约是集成测试的两倍,系统测试的三倍。

  3、自动回归

  自动回归测试可以避免小量修改导致大量系统级调试与测试。“回归”是指代码修改后回复到原来的正确状态。例如,一个函数本来工作正常,后来发现少了个功能点,修改代码后,原有功能可能被破坏,回归测试是检验原来的功能是否仍然正常。代码之间具有复杂的依赖关系,一个函数的修改,可能引起其他代码产生错误,回归测试不仅针对被修改的代码单元,也针对其他相关代码。单元测试目标小、结果明确、执行快捷,容易实现自动化回归测试。

  单元测试将代码功能“定格”,代码修改后可以自动检查是否引入新的错误,避免陷入“系统测试->修改->引入新的错误->新一轮系统测试->修改->引入新的错误”的怪圈。自动回归也使开发过程适应频繁变更的需求,使开发过程趋于“敏捷”。

  4、促进开发

  如果边开发边测试,那么,单元测试的结果可以完整地描述程序的行为,如下图。程序行为是在什么输入下,会执行哪些代码,会产生什么输出。写代码时能随时察看程序行为,比较容易想明白思路对不对,接下来应该怎么写。刚写的代码有没有错误也随时可以发现,不但效率高得多,也没那么累。

  只要做了单元测试,反映程序行为的数据一定会存在,只要使用工具将这些数据捕获并显示出来,可以一边编程一边察看程序行为。

  编程时,程序员一定需要考虑清楚代码的功能,包括会有哪些输入,如何处理,应该产生什么结果,列出来是测试数据了,因此,并不需要多少额外的时间来设计测试数据,同时编写效率会显著提高,并且基本上不需要调试。调试是花时间的。如果结合自动化的测试工具,让设计测试数据以外的工作(如编写测试代码、隔离测试任务、底层模拟、统计覆盖率等等)由工具完成,那么,在开发的过程中进行单元测试,开发和测试同步完成,所用的时间一般比传统方式更短,代码单元功能越复杂,节约的时间越多。

  我们初学C语言时,通常会编写一些小算法,并通过控制台输出结果进行测试。这是一种高效的编程方式,因为第一时间可以了解代码是否工作正常,随时调整思路。但在实际项目中,这种方式不再现实,正在编写的代码单元很难单独运行并观察其行为。单元测试可以帮助我们重返“小算法编程”,让代码单元随时独立运行,减少麻烦的调试,缩短编码周期。