本系列是《Unit Testing》 一书的读书笔记 + 精华提取。
书中的例子 C# 语言编写,但概念是通用的,只要懂得面向对象编程就可以。
单元测试当前的状态
目前,在(美国的)大部分公司里,单元测试都是强制性的。
生产代码与测试代码之间的比例大约在 1:1 到 1:3 之间。
有时候比例会更高,甚至达到 1:10
二十多年来,讨论的话题已经从“是否应该做单元测试”变成了“编写出好的单元测试意味着什么?”
单元测试好与不好不仅仅是个人喜好品味的问题,更是与项目成功失败密切相关
我们的目标不仅是掌握测试工具(很多资料都有这种教程),而是要:“不仅要写单元测试,而且让做单元测试的方式能够为你提供最好的回报”
企业应用的特点是什么?
大量高复杂度的业务逻辑
项目的声明周期很长
数据量不算特别大,也不小
对性能的要求不高或中等水平
单元测试的目的
单元测试的实践通常会导致更好的设计,但这不是单元测试的主要目的,这仅仅是个副作用。
单元测试与代码设计的关系
如果你的代码很难进行单元测试,那这就是你代码需要改进的强烈信号。
代码质量差的通常表现就是紧密的耦合,就是说不同的生产代码段之间没有足够的解耦,所以很难对其进行单独测试。
不幸的是:
代码是否能进行单元测试这件事是一个负向指标(只能确定代码质量肯定不好);
如果你的代码能够容易的进行单元测试,并不意味着你的代码质量一定很高。
单元测试的目的就是让软件项目可持续的发展,“可持续”这个词是关键。
下图描述了项目有无单元测试与项目发展和消耗工时之间的关系:
这种迅速降低开发速度的现象就是软件的熵。而熵就是体系混乱程度的度量。
在软件中,熵以易于恶化的代码形式表现出来。每次你改变代码库中的某个东西,其中的无序量,或者说熵,都会增加。
测试有助于扭转这种趋势。它们充当了一个安全网——一个为绝大多数回归提供保险的工具。测试有助于确保现有功能正常工作,即使在引入新功能或重构代码以更好地适应新的需求之后。
回归(regression),是指某个特性在某个事件(通常是代码修改)之后停止按预期工作了。术语回归和软件 bug 是同义词,可以互换使用。
可持续性和可扩展性是关键。从长远来看,它们允许您保持开发速度。
什么是好和不好的单元测试?
此图描述了较好、较差、没有单元测试与项目发展和消耗工时的关系。
可以看出:不是所有的测试都是被平等创建的。
通过添加更多的测试并不会实现你单元测试的目标,你需要考虑测试的价值和维护成本。而成本取决于各项活动所花费的时间:
重构底层代码时重构测试的时间
针对每次代码修改,运行测试的时间
处理由测试引起的错误警报的时间
当您试图理解底层代码的行为时,阅读测试所花的时间
由于维护成本高昂,很容易写出净价值接近于 0 甚至负价值的测试。
最后强调一点:代码是一种负债,而不是资产。而测试也是代码。