程序员真的有必要掌握 TDD 吗?
你好,我是猿java。
你听过或者了解过 TDD 吗? 你知道 TDD 是什么吗?你知道它是如何工作的吗?今天我们就来聊聊 TDD。
曾经在Martin Fowler(马丁·福勒) 的个人博客里看过一篇关于Kent Beck、David 、Martin Fowler 3位大牛关于 Is TDD Dead 的讨论以及David
的TDD is dead. Long live testing. 的帖子。
几位作者的部分介绍
1 | Martin Fowler(马丁·福勒),出生于英格兰,后移居美国,像微服务, |
TDD 是什么 ?
TDD 是来自极限编程,百度百科的解释如下:
TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前, 先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法
的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他 开发方法和过程。
这个解释是比较片面的,其实TDD 包含两大部分:ATDD 和 UTDD
ATDD
Acceptance Test Driven Development,验收驱动开发。比如,QA(质量保障)会编写测试用例,然后和PM(产品经理),RD(技术开发)一起评审,这个过程可以帮助RD更好的理解业务需求和验收条件,以至于在后面的代码编写中带着验收目标直到验收测试用例通过。
测试的方式有很多,比如BDD(功能测试),白盒测试,集成测试等等,根据不同的场景采用不同的测试手段,以便达到验收通过。
UTDD
Unit Test Driven Development,单元测试驱动开发,RD先编写单元测试用例,然后再编写实现代码直到单元测试通过。
关于ATDD和UTDD 在Thoughtworks官网,有一张抽象图,大家可以参考下:
下面整理了一个xmind图
如何做好 TDD?
在分析TDD方案之前,我们先来解决一个问题:测试驱动开发,整个过程从哪里开始?
答案:测试
那么,测试又从哪里开始呢?
答案:需求。
如果没有需求,测试的目标是什么?因此需求是测试的源头;面对庞大的需求,要如何测试?方法是将需求分解成一个一个可实施测试的小任务。
所以 测试驱动开发要从任务分解开始。
下面摘取了 Thoughtworks 官网的2张图片,来表达TDD的整个过程。
TDD实施-步骤示意图:
TDD实施-协作示意图:
个人觉得TDD 可以和 DDD 一样,从战略和战术两个角度来实施。
战略角度
战略角度,更多是一个思想层面的方法论,它可以指导我们以一种更优的方式去实施TDD。
下面先描述一个需求从提出到上线的整个生命周期:
当接到一个新需求时,
- 首先,PM会有需求评审,评审会阐述业务背景,讲解需求解决的问题以及要达到什么目标;
- 然后,RD会根据需求评审,做业务分解、上下游沟通、接着做技术详设,技术串讲;
- 接着,QA会结合需求评审和RD的技术串讲编写测试用例以及用例评审,多方拉齐验收目标和上线时间;
- 再接着,RD会做架构设计,代码设计以及代码编写,代码测试;QA会做测试相关的工作,比如:用例设计,测试脚本等;
- 最后,RD开发完成&提测,QA进行测试直到准出,PM进行最后的验收直到代码上线;
整个流程体现了TDD的战略思想,整个生命周期为ATDD和UTDD提供了一定的流程规范。
战术角度
战术角度,更多是从技术层面来阐述。在战略角度我们提出了方法论,针对流程里面的每个步骤要怎么落地,这个就是战术角度。
- 比如:需求分解,需要按照什么维度分解,是按照领域划分还是按照过程划分,任务分解成多大才算合理。
- 比如:架构设计,要用什么架构思想,是六边形架构还是洋葱架构。
- 比如:代码设计,需要用到什么设计模式,适配器模式还是工厂模式。
- 比如:代码编写,需要用到什么数据结构,算法,怎么让代码更具有复用性。
- 比如:测试,如何设计测试用例,选用什么测试框架,怎么让测试变得自动化
TDD的实施有一个经典三步曲:红 - 绿 - 重构,不论是ATDD还是UTDD都可以按照这个三步来实施,三部曲示意图如下:
在很多测试框架中 红代表测试没有通过,绿代表测试通过,而要想让红变成绿就需要经过不断的重构。
因此,我们可以理解:为了写测试,首先“驱动”着我们理解业务,把需求分解成一个个的任务,然后会“驱动”着我们给出一个可测试的设计,而在具体的写代码阶段,又会“驱动”着我们不断改进写出来的代码。把这些内容结合起来看,我们真的是在用测试“驱动”着开发。
有了战略和战术的指导,最主要的就是需要修炼支撑这些策略的能力。实施 TDD 最好需要具备以下能力:
- 测试前移(左移)的思维能力
- 业务和技术需求的分析和任务拆分能力
- 测试用例设计能力
- 自动化测试开发
- 能力代码重构
- 能力持续改进的能力
误区
误区1
在很多程序员的理解中,UTDD就是TDD,TDD就是UTDD,以至于我们把面向业务或测试的ATDD给忽略了,因此,无形中把TDD的范围给缩小了。下面给了一个ATDD和UTDD的对标表
误区2
TDD 就是先写测试后写代码,原因已经在TDD 战术部分中分析过。
TDD真的”死了”吗?
如文章开头 Is TDD Dead?
答案是:NO, 而且目前TDD活的还是不错的,很多公司一直在践行它,只是没有特别去强调它是TDD的范畴。 同时,TDD不是银弹,不可能解决实际工作中的任何问题,我们要做的是不断的学习,比较和总结,根据实际的业务需求去实施,毕竟合适才是最好的。
程序员真的有必要掌握TDD吗?
很有必要,我们不一定要特别强调TDD这个概念,但是TDD根本就是保证程序员的代码质量,而代码质量是程序员的底线
UTDD可以帮助程序员更好,更系统的去写单测;ATDD,可以让程序员更好的了解业务,通过更深度的了解业务来保证代码对业务的健壮性。
参考文献
书籍:Java测试驱动开发 (Viktor Farcic著,袁国忠译)
敏捷软件开发(RobertC.Martin 著)
学习交流
如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。