“设计驱动测试”还是“测试驱动设计”?
收藏

面一篇文章“真有人把“测试左移”的价值和实践说透了”在测试左移实践中提到TDD,还说这不是测试驱动开发(test driven development),让大家猜猜,是什么?而是测试驱动设计test driven design)。
当我们谈到“软件设计”时,涉及面很广,之前会包含两部分:概要设计和详细设计,而今天更乐于分为:架构设计、数据库设计、UI设计、算法设计等,但其中“架构设计”更为重要。
在架构设计中,不否定是为了满足业务需求,架构设计时要能洞察业务背后对系统提出的要求,包括约束条件,从这个角度看,业务驱动设计(Business driven design,BDD)也没错。但是,架构设计除了实现功能与系统组件映射关系之外,更重要的是要考虑如何满足系统特性需求,包括:
  • 性能要求,满足多大的并发用户、并发交易和响应时间的要求。
  • 可靠性/可用性要求,如何通过冗余设计、故障转移、快速恢复等实现
  • 可伸缩性,通过分布式架构实现
  • 可维护性/可扩展性通过异步消机制、微服务架构实现松耦合
  • .......

特性或质量驱动设计,但这些特性需要验证,而且不能完全依赖系统构建之后进行系统测试(包括系统性能测试、系统可靠性测试...)来验证,必须在设计时就能得到初步验证(包括设计评审),所以在架构设计时就需要考虑测试,让设计的系统各种特性具有可测试性,架构师需要良好的测试思维,在设计中驱动他们从这些方面去思考、去达成设计目标,所以从这个意义上看,就是“测试驱动设计,TDD”。TDD,准确地说,就是先要想好“有哪些指标可以检验当前这个系统架构设计是成功的”,系统地列出需要验证的系统设计指标,从而再去进行架构选型比较、调整、优化等设计工作。在硬件设计中,就有著名的“design for testing (DFT)”:DFT consists of IC design techniques that add testability features to a hardware product design. The added features make it easier to develop and apply manufacturing tests to the designed hardware。这里说,TDD(测试驱动设计)更进了一步。

同时,我们还看到一本书《设计驱动测试(DDT)》(Matt Stephens & Doug Rosenberg,Design Driven Testing: Test Smarter, Not Harder)。DDT是说“设计在前,测试在后”,和我们之前谈到的“测试驱动设计”(测试在前,设计在后),是不是相反?其实不是,因为背景(上下文)不一样,它们指的“测试”都不一样,DDT中的测试主要指单元测试,Matt和Doug之所以提出DDT,是相对狭义的测试驱动开发(即真有人把“测试左移”的价值和实践说透了提到的UTDD,代码级的测试驱动开发——单元测试驱动编程)来进行讨论的,因为许多做UTDD的程序员,一上来就写测试代码和产品代码,不做设计,这是很糟糕的。Matt和Doug 指出UTDD的问题:

10.(代码层)测试驱动设计,如盲人摸象

  9.完全没有文档(因为10.)
  8.所有东西都是单元测试
  7.TDD测试不是完全的单元测试
  6.验收测试提供针对需求的反馈 (如果没有ATDD
  5.TDD导致盲目自信的变更 (通过重构来设计
  4.设计在不断增长 (编程后的持续重构
  3.有一些预先设计就可以了
  2.TDD产生了大量测试
1.TDD实在太难了(所以代码层的TDD现实中很少见

并阐述DDT(测试驱动设计)的优点:
10.DDT包含业务需求测试
  9.DDT包含场景测试
  8.测试是被设计驱动的
  7.DDT包含控制器测试
  6.DDT测试更灵活,更简单
  5.DDT中的单元测试是“经典”的单元测试
  4.DDT中的测试用例可以转换成测试代码
  3.DDT测试用例指导测试计划
  2.DDT测试对开发和测试团队都很有用
  1.DDT可以消除重复工作
说明先设计(包括借助UML先完成用例图)、后做单元测试的重要性。

前面那篇文章“真有人把“测试左移”的价值和实践说透了”把测试驱动开发思想的落地分为三个层次,不局限于早期极限编程的编程层次。

  • 单元测试驱动编程 UTDD
  • (系统)测试驱动(系统架构)设计 TDD
  • 验收测试驱动开发 ATDD
ATDD实际已经涵盖了DDT(测试驱动设计)。这是由简单的V模型来支撑,而没有用《设计驱动测试》复杂的V模型。

参考:


北京测试大师公开课