TDD 的一些实践
不是所有方法都需要写单元测试
如果具体的实现方法也需要写单元测试的话,就变成为了测试而测试,太关注细节,导致任何实现方面的改动都会引起用例失败。麻烦不说,还让人不敢修改代码了。用代码来锁死代码实现,不推荐。
从外到内写用例
实现一个函数,先确定函数是否需要写单元测试,如果是太具体的实现,可以考虑不用单元测试,该方法由其 Caller 的测试用例来覆盖。
如果是一个对外提供功能的入口函数,则需要为其增加单元测试,验证其功能。
预期到实现方式可能有优化空间,那应该为 Caller 写单元测试,验证其结果稳定,不应该为具体的实现写单元测试,否则改变实现又会需要重写单元测试。
简单一点的判断方式,
public
方法需要写,private
方法不需要写。一边填充算法实现,一边补充单元测试
实现一个功能可能需要再调用若干个方法,开始写代码的时候,只知道一个入口函数,将来会写什么样的细节实现,很难预测到,甚至会因为实际开发的过程中遇到什么问题导致方案改变,所以 TDD 应该不会要求一开始就把所有的细节都想的清清楚楚,不容一丝改变,而是在填充算法实现的过程中,根据需要,一点一点补充对应的测试用例。
先写测试用例,再完成方法实现
一开始写 High 了,很容易一溜把算法实现写出来,但是后续可能会有考虑不周全的地方,导致返工,调试。不如在写方法实现之前先想好是否要单元测试,如果需要,待实现的方法先留 TODO,把测试用例给出,然后再填充方法实现,磨刀不误砍柴功。
如果先写完算法实现,再去补充单元测试,一方面可能时间不允许,有新的需求催过来了。另一方面,已经实现的算法会限制写单元测试的思路,可能会遗漏某些 Case。
单元测试从上往下写,测试用例从下往上调通
有时候测试用例的代码也需要调试。写完方法实现后,测试用例和方法实现可以互相验证。
比如今天写一个用例的时候,想判断两个 List 的内容是一样的,使用了
equalTo
方法,但是 List 中 Item 出现的顺序不同,这种用例 Review 的时候可能不容易看出问题,运行的时候才发现还需要调整一下。用这个方式写了 LeetCode 的 827 题,单元测试跑过的情况下,一遍过,有一丝丝满足感。