仅仅是覆盖率?如何让TDD成为开发利器

你真正了解 TDD 吗?

TDD(Test-driven Development),是一种开发软件的手段,意在开发出整洁代码( Clean Code[1] )。它对某个业务包含以下的开发流程:
1. 写出任务拆解文档(拆解设计思路、类与方法与变量的定义名称、覆盖所有业务场景的输入参数及预期输出)
写出任务拆解文档后,开发者应该对文档中的测试(预言)递归按如下所示的方式[2]进行开发:
1. 对某个预期写出失败的测试(红)
2. 编写业务代码使测试通过(绿)
3. 重构刚才编写的代码(蓝)
例如:FizzBuzz
你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有100名学生在上课。游戏的规则是:
1. 让所有学生排成一队,然后按顺序报数。
2. 学生报数时,如果(a)所报数字是3的倍数或含有3,那么不能说该数字,而要说Fizz;(b)如果所报数字是5的倍数或含有5,那么要说Buzz;如果既满足a又满足b,则说FizzBuzz。
你希望有一个软件,能够自动打印一个100行的FizzBuzz列表。
这个时候,开发者应该仔细分析需求然后给出一个任务拆解文档。例如:
# Question
你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有100名学生在上课。游戏的规则是:
1. 让所有学生拍成一队,然后按顺序报数。
2. 学生报数时,如果(a)所报数字是3的倍数或含有3,那么不能说该数字,而要说Fizz;(b)如果所报数字是5的倍数或含有5,那么要说Buzz;如果既满足a又满足b,则说FizzBuzz。

# Sequence
1. 定义FizzBuzz类,定义成员变量String line
2. FizzBuzz类的构造方法接受int number参数,然后按照a、b的逻辑,将number转化成对应的字符串赋值给line
3. 重写FizzBuzz的toString方法直接返回line
4. 定义一个FizzBuzzLine类,定义print方法,可以返回100个元素的List, 从 1 至 100 循环构建FizzBuzz对象并将其装入List中

# Tasking
- [ ] assert FizzBuzzLine.print().size() == 100
- [ ] assert new FizzBuzz(0).toString == "1"
- [ ] assert new FizzBuzz(2).toString == "Fizz"
- [ ] assert new FizzBuzz(4).toString == "Buzz"
- [ ] assert new FizzBuzz(14).toString == "FizzBuzz"
- [ ] assert new FizzBuzz(12).toString == "Fizz"
- [ ] assert new FizzBuzz(24).toString == "Buzz"
- [ ] assert new FizzBuzz(50).toString == "FizzBuzz"
按照这个思路,不出意外,代码就从业务角度全覆盖了。接下来,就按照Tasking一个个红、绿、蓝重构就可以了。

TDD与代码覆盖率

很多项目都会有代码的覆盖率要求,有的甚至需要完全覆盖。很多软件工程师对此叫苦不迭,代码写完就开始补测试,补着补着耗费了大量的时间,难免还有遗漏,开始厌恶代码测试覆盖率的要求。其实真正的代码覆盖率要求是在业务的层面出发的。一个业务一定会有多种入参及其应该反馈的结果,这被称为happy ending,但也应该有一些异常场景的反馈(tragic ending)。如果一个业务的happy ending和tragic ending都被测试所覆盖,那这个业务代码就可以做到满覆盖率了。这样的代码的测试,应该是很干净简洁的对业务入参及出参的预期。那么如果后期需要重构或者修改需求,这些测试的变动直接就构成了代码的安全网[3],为开发者接下来的变动保驾护航。

概念要清楚

好的设计,需要OOP化。要将业务提炼出概念,抽象成软件模型。上面的例子中,有FizzBuzzLine的概念,有FizzBuzz概念。FizzBuzzLine的用途就是打印体育老师需要的那个列表。FizzBuzz接受序号的参数,并将其自动转换为需要的字符串(line)。
需要软件开发者熟悉设计模式和领域模型,或是在TDD的蓝流程中,积极相应重构。

总结

按照TDD的流程,思考业务、提炼模型与概念、任务拆解、设计Tasking、断言错误测试、让测试通过、重构代码,这样产出的代码拥有可靠性、可扩展性、健壮性、易读性、易重构性。TDD是软件开发都当之无愧的神兵利器。

标注

[1] Clean Code : 概念来自于代码整洁之道
返回首页