一、大、中、小型测试

在国内软件测试领域中,按照软件生命周期的和业务迭代发布的不同阶段,我们有单元测试、增量测试、集成测试、回归测试、冒烟测试、系统测试等等,但是因为行业氛围的种种因素,在测试上我们更集中在了测试中的后续阶段集成测试和系统测试等等,忽略了”质量左移“的重要性。 而在谷歌的实践中,按照测试的规模将测试分为:小型测试、中型测试和大型测试:

- 小型测试:一般来说,都是自动化实现的,勇于验证一个单独函数或者独立功能模块的代码是否按照预期工作,着重于典型功能性问题,数据损坏、错误条件和大小差-错误(大小差-错误是一类常见的程序设计错误)等方面的验证

- 中型测试:通常也都是自动化实现的,该测试一般会设计2个或以上甚至更多模块之间的交互,测试重点在于验证这些功能临近区(即功能交互区)之间的交互以及彼此调用时的功能是否正确

- 大型测试:关注的是所有模块的继承,更倾向于结果驱动,验证软件是否满足最终用户的需求。

因规模不同,在测试时不同的测试类型的关注点和依赖点存在较大的差异,一般说来:

- 小型测试:针对单个函数的测试,关注其内部逻辑,mock所有需要的服务。小型测试带来优秀的代码质量、良好的异常处理、优雅的错误报告;

- 中型测试:验证两个或多个制定的模块应用之间的交互;

- 大型测试:也被称为 “系统测试” 或“端到端测试”。大型测试在一个较高层次上运行,验证系统作为一个整体是如何工作的。

总结来看,越是规模越小的测试越能实现自动化,因为其依赖更少,串联测试上下文或者系统的成本更低;从另外一个角度说,因成本低、流程简化也就更容易发现问题。


二、如何理解”单元“?

在传统意义的理解中,单元即为一个函数,任何走出函数的测试都算不上单元测试。但是在实践过程中,”单元“的含义应更多的取决于开发者自身,如果正在使用函数式编程,一个单元最有可能指的是一个函数。单元测试将使用不同的参数调用这个函数,并断言它返回了期待的结果;在面向对象语言里,下至一个方法,上至一个类都可以是一个单元(从一个单一的方法到一整个的类都可以是一个单元)

按照[一、测试规模]中叙述,我们理解意义上的单元测试其实就是小型测试,它不应依赖任何其它模块,即专注于单元自身,验证单元自身的逻辑是否符合预期。

小型测试中型测试大型测试
测试类型单元测试单元测试 + 逻辑层测试(泛单元或分层测试)UI测试/接口测试

三、为什么要做单元测试?

单元测试的重要性不言而喻,它是保证”写的代码就是我想要的结果“的最有效的方法,且没有之一。

金字塔模型

越是底层的测试,牵扯到相关内容越少,而高层测试则涉及面更广。比如单元测试,它的关注点只有一个单元,而没有其它任何东西。所以,只要一个单元写好了,测试就是可以通过的;而集成测试则要把好几个单元组装到一起才能测试,测试通过的前提条件是,所有这些单元都写好了,这个周期就明显比单元测试要长;系统测试则要把整个系统的各个模块都连在一起,各种数据都准备好,才可能通过。 另外,因为涉及到的模块过多,任何一个模块做了调整,都有可能破坏高层测试,所以,高层测试通常是相对比较脆弱的,在实际的工作中,有些高层测试会牵扯到外部系统,这样一来,复杂度又在不断地提升。

为什么要做单测?

下面这张图,来自微软的统计数据:bug 在单元测试阶段被发现,平均耗时 3.25 小时,如果漏到系统测试阶段,要花费 11.5 小时。

  • 单元测试对我们的产品质量是非常重要的;
  • 单元测试是所有测试中最底层的一类测试,是第一个环节,也是最重要的一个环节,是唯一一次有保证能够代码覆盖率达到 100% 的测试,是整个软件测试过程的基础和前提,单元测试防止了开发的后期因 bug 过多而失控,单元测试的性价比是最好的。
  • 据统计,大约有 80% 的错误是在软件设计阶段引入的,并且修正一个软件错误所需的费用将随着软件生命期的进展而上升。错误发现的越晚,修复它的费用就越高,而且呈指数增长的趋势。作为编码人员,也是单元测试的主要执行者,是唯一能够做到生产出无缺陷程序这一点的人,其他任何人都无法做到这一点
  • 代码规范、优化,可测试性的代码
  • 放心重构
  • 自动化执行 three-thousand times

85% 的缺陷都在代码设计阶段产生,而发现 bug 的阶段越靠后,耗费成本就越高,指数级别的增高。所以,在早期的单元测试就能发现 bug,省时省力,一劳永逸,何乐而不为呢


本篇文章为《从头到尾说Golang单元测试》系列的第一篇文章,后续还有单元测试框架、依赖mock框架的使用说明与最佳实践。