11年前,在阿里做过一个分享,题目是“让缺陷无处藏身——谈软件可测试性” ,本次分享的内容提要为:
-
质量·缺陷·可测试性
-
测试驱动开发(TDD)
-
代码的可测试性
-
设计的可测试性
-
需求的可测试性
-
软件可测试性框架
所以看到这里,你就知道这篇文章讨论的主题就是“软件可测试性”。这个话题非常重要,被列入“持续测试解决方案 ACTS” 上层“方法技术”的第2项,但许多人对此比较陌生,只了解这个概念,在工作中关注不多,更没有在团队中推行 “可测试性规范”。
笔者一直还是比较关注这项内容,除了一直推崇ATDD(认为“搞敏捷开发一定要实施ATDD,否则就不能敏捷起来”)之外,十年前(2012年)出版的《完美测试:软件测试系列最佳实践》一书中,我用了整整一章的内容介绍了“软件可测试性”。之后,我还在多家企业做个分享,例如为华为公司讲过这方面的内容。
而且笔者还帮助某些企业建立了:
-
《TA可测试性设计规范》(TA:测试自动化)
-
《TA可测试性Java代码规范》
那么,什么是“可测试性”?良好的可测试性带来哪些价值?软件研发中如何提升可测试性?...... 下面就一一回答这些问题。
1. 什么是可测试性?
可测试性(testability),一般是指某个软件、某个组件或某段程序的特性或属性被验证的程度,或者说,为了完成测试任务所要付出的代价。如果代价越低,说明可测试性越好。
可测试性,包含了两层含义:你能否针对软件进行实际的测试,其次,软件中存在的任何缺陷是否都能发现。实际上,面对一个软件,咱们总是有办法进行验证的,但是有些软件容易被验证,有些则很难。“可测试性”改为“易测试性” 会更好些,但目前大家都习惯称为可测试性。
如果觉得可测试性还比较抽象,可以将“可测试性”分解为“可控制性”和“可观察性”,两者缺一不可,只有具有良好的可控制性和可观察性,软件系统才具有良好的可测试性。
举一个简单的例子,下面这个图显示模块 A、模块 B缺乏可测试性,因为模块 A 缺乏可观察性,而模块 B 缺乏可控制性。如何改善模块 A、模块 B的可测试性呢?
我们只要在模 块 A 和 B 之间增加一个接口,使 A 的状态信息(结果输出)可以在这个接口被观察;同 时,通过这个接口能够控制 B (给B输入数据)。这样原来模块 A 直接传给模块 B 的数据,不能被隐含起来,而是可以显现出来。
可测试性还可以继续扩展,例如加上“可预见性”、“简单性”、“稳定性”...... 我们能够预见系统会做出怎样的响应、输出哪些结果,否则我们很难写出测试用例的“期望结果”,如果没有“期望结果”,就没有测试用例。其次,系统越简单,越容易验证;系统越稳定,越容易验证。
2. 良好的可测试性带来哪些价值?
-
如标题所示,缺陷无处藏身,软件中存在缺陷,能够被发现。容易发现缺陷;
-
缺陷更容易被发现,尽早暴露质量风险,降低项目的风险和产品交付的质量风险。
-
更容易验证功能特性,降低测试、质量保障成本,缩短开发周期,进而降低整个研发成本,产品交付更快更早。
3. 软件研发中如何提升可测试性?
软件的可测试性带来的价值还是挺大的,自然,我们应该在软件研发中要极大地关注软件的可测试性,那么,软件研发中如何提升可测试性?例如,可以从“软件可测试性”定义出发,设计、编程力求简单,降低软件的复杂性和耦合性,适当增加接口,提升可控制性和可观察性。当然,我们可以更系统地、更全面地提升软件的可测试性,也就是“提升软件的可测试性”的工作应该贯穿整个软件生命周期。
先从需求开始,让需求具有良好的可测试性,例如不能在需求文档中有“可能”、“大概”、“几乎”、“响应快”等描述模糊的词汇,能量化的则尽可能量化。面对需求,ATDD能彻底确保需求的可测试性,正如TDD(其实是UTDD)能彻底确保代码的可测试性,每一个用户故事需要建立验收标准。再进一步,包括需求建模(如用例图、活动图等)、领域建模等。
其次,在设计上也需要关注可测试性,更好的实践是设计中专门考虑可测试性(Design for test),如前面所述的,为测试提供额外的接口。“设计的可测试性” 或 “为可测试性设计” 这部分内容会比较丰富,从架构设计、接口设计到日志设计等,需要为设计建立可测试性方面的规范,包括采用良好的设计模式、遵守高内聚低耦合、面向对象的SOLID原则。
最后,就是代码的可测试性,如前所述,可以为可测试性设计相应的代码规范,不同的编程语言会有差异。例如,代码中应避免在构造函数中引入业务逻辑,如实例化和初始化协作对象、调用静态方法、复杂的赋值逻辑等;在一个类里只传入需要的对象作为参数,避免在传入的对象中进一步挖掘真正需要的依赖对象。
反例:
其正例:
4. 其它
可测试性还需要能够度量,我们可以根据特定目标和需求定义度量框架及其度量指标。可测试性对测试设计、测试执行都有影响,所以其度量要结合对测试设计、测试执行的影响因素一并考虑。
可测试性不仅重要,而且不那么简单,从下面这张图略见一斑。
参考链接: