测试驱动开发(TDD)
本篇文章简单叙述一下什么是测试驱动开发,以及怎么进行测试驱动开发!
TDD (Test Driven Development):(源于极限编程(XP))在不同的场景和不同的角色中的对 TDD 的认知可能会有不同。
- 有人可能会理解成 ATDD(Acceptance Test Driven Development);
- 也有人可能会理解成 UTDD(Unit Test Driven Development)
为了避免产生歧义,文章中涉及到的 TDD 名词专指 UTDD(Unit Test Driven Development),即 「单元测试驱动开发」。
什么是测试驱动开发
Kent Beck 的著作《测试驱动开发》中说:“测试驱动开发不是一种测试技术。它是一种分析技术、设计技术,更是一种组织所有开发活动的技术”。
由此可看:TDD 不是一种简单的通过单元测试来驱动代码的开发,然后在优化内部代码逻辑的方法,而是一种有机的技术结合。
-
分析技术:
- 将问题分析成为一个个可操作的任务模块。
-
设计技术:
- 测试驱动代码的设计和功能实现,然后驱动代码的重构。持续改善海马。
TDD 的目标
Kent Beck 在他的著作《Test-Driven Development》一书中提到:“代码简洁可用这句言简意赅的话,正是 TDD 所追求的目标”。
对于保证代码的 简洁可用,可以采用分治的思想去实现,先达到 可用 目标,在思考如何 简洁。
TDD 的规则
在 TDD 的编码中,需要遵循两条简单的规则:
- 仅在自动测试失败时才编写新代码。
- 消除重复设计(去除不必要的依赖关系),优化设计结构(逐渐使代码一般化)。
即 可用,简洁!
TDD 的口号/原则
简单来说,不可运行 -> 可运行 -> 重构——这正是测试驱动开发的口号,也是 TDD 的核心。在这个闭环中,每一个阶段的输出都会成为下一阶段的输入。
- 不可运行——写一个功能最小完备的单元测试,并使得该单元测试编译失败。
- 可运行——快速编写刚刚好使测试通过的代码,不需要考虑太多,甚至可以使用一些不合理的方法。
- 重构——消除刚刚编码过程引入的重复设计,优化设计结构。
怎么做测试驱动开发
普遍的开发过程
- 获取需求
- 做简单的设计
- 在大脑中规划需要那几个类,大概用什么设计模式
- 开始编写代码
- 发现有些类设计多余了,删除了,有些类不满足,增加设计
- 需求好像不清晰,和产品经理确认
- 一口气写完所有代码,心里没地儿,造数据跑一下
- 调试
- 解决了几个蠢问题,跑起来了
- 提测,QA 报 bug
- 造数据,找到 bug 原因了,修复
- 修复几次,代码变烂,过一段时间自己都看不懂了
相信大多数人是这种开发方式!
TDD 开发过程
- 获取需求
- 做简单的设计
- 分解任务
- 针对单个任务编写单元测试,只关心输入输出
- 编写实现,让单元测试能跑通
- 提交代码,进入下一个任务
- 联调,手动测试下,一般没有问题,如果有问题使用 git diff 差异,快速发现问题
- 重构,利用单元测试保护,消除代码坏味道
- 提交测试,如果有问题,使用单元测试发现问题
注意的问题
- 测试不是越多越好,只为必要的代码编写测试,用尽可能少的用例保障代码质量。而且随着测试变多,运行测试的速度也会变慢。
- 没有标准的 TDD 规则,就像模糊的 DDD 设计模式一样!
- 分析问题的粒度,决定了之后写出来的代码质量。
- 不要忽略任何一个测试集合的失败结果。
总结
文章在理论层次上总结了 TDD ,TDD 的概念和开发方式,并没有提供示例去演示,仅仅作为一个文章总结。
使用 TDD,它将会在实践的过程中学会如何雕琢我们的代码,从而得到稳定的面向对象设计、可维护和高质量的系统。