如何写出有效的单元测试
什么是单元测试
一个单元测试是一段自动化的代码,这段代码调用被测试的工作单元,之后对这个单元的单个最终结果的某些假设进行校验。 单元测试几乎都是用单元测试框架编写的;只要产品代码不发生变化,单元测试的结果是稳定的。
为什么需要单元测试
单元测试是保证你写的代码是你想要的结果的最有效办法 单元测试帮我们塑造设计 单元测试是最好的文档之一
什么是有效的单元测试
它应该是自动化的,可重复执行;
它应该很容易实现;
它应该第二天还有意义;
任何人都应该能一键运行它;
它应该运行速度很快;
它的结果应该是稳定的(如果运行之间没有进行修改的话,多次运行一个测试应该总是
返回同样的结果);
它应该能完全控制被测试的单元;
它应该是完全隔离的(独立于其他测试的运行);
如果它失败了,我们应该很容易发现什么是期待的结果,进而定位问题所在。
可读性
可维护性
可信赖
测试可重复;
测试与依赖环境隔离;
只测试不进行验证是不可靠的测试;
在测试类中不要依赖与测试的顺序;
测试的结果是精准的:校验的精准以及错误问题的精准定位;
快速执行
为什么有效的单元测试如此重要
如何写有效的单元测试
使用测试框架
flutter_test
integration_test
统一的编码约定
使用测试替身
Dummy:一种什么也不做的实现方式。接口中的每个方法什么也不做,如果方法有返回值,返回的值尽量接近null或者0。
Stub:Dummy的一种,Stub的函数并不返回null或0,而是返回能推动函数沿预定路径被测试的值。
Spy:Stub的一种,它返回测试所需的特定值,推动系统沿着我们期望的路径前行。然而,Spy能记住对它所做的事,并允许测试询问。
Mock:Spy的一种,它返回测试所需的特定值,推动系统沿着我们期望的路径前行,而且还会记住对它所做的事。不过,Mock还知道我们的预期,基于这些预期,判断测试是否通过;换而言之,Mock中写明了测试断言。
Fake:Fake是一种模拟器,它实现基础业务规则,这样测试就能要求该Fake按需要的路径执行。
一个测试应当只检查一件事
一个测试只有一个模拟对象
避免冗余测试
避免条件逻辑
单测需要确定性
测试快速执行
避免过度指定
像素完美:顾名思义,是一种特定于图形和图像生成的测试坏味道。它混杂了魔法数字和基本断言,使得测试极难阅读也极其脆弱。 这种测试几乎无法阅读,因为即使测试在语义上是处于高层概念的,却仍然会针对硬编码的底层细节例如像素坐标和颜色来进行断言。指定坐标上的像素是黑还是白,与两个图形是否相连或堆叠的概念是有区别的。 这种测试极其脆弱,因为即使很小的和不相关的输入变化——是否是另一个图像,或图形对象的渲染方式——都足以影响输出、打破测试,谁让你非要精确地检查像素坐标和颜色呢。同样的问题在采用golden master技术时也会遇到,其做法是事先将图像录制下来,并手工检查其正确性,以后再进行测试时就将渲染出的图像与之进行比对。 这些可不是我们愿意去维护的测试。我们不希望带着这种脆弱的精确度去编写测试,而是使用模糊匹配和智能算法来代替繁琐的数值比较。
不要写永不失败的测试,不要写没有校验的测试
测试不要名不副实
测试私有或者受保护的方法
将方法变成公共方法;
将方法抽取到新类;
将方法变成静态方法;
将方法成为测试可见方法;
避免强制的测试顺序
清理测试环境
统一的单测命名、变量命名
使用有意义的断言
把单元测试视为“一等公民”
加速执行速度
测试金字塔
避免测试重复
如果一个更高层级的测试发现了一个错误,并且底层测试全都通过了,那么你应该写一个低层级测试去覆盖这个错误;
竭尽所能把测试往金字塔下层赶;
补充单元测试应该从哪里开始
优先覆盖回归测试用例中P0级别的用例;
避免过度指定的端到端测试;
适当的契约测试;
可测试的设计
行动指南
避免复杂的私有方法;
避免final方法;
避免static方法;
使用new要当心;
避免构造函数中包含逻辑;
避免单例;
组合优于继承;
避免服务查找;
基于接口的设计;
可测试的代码是否违背了SOLID中的开闭原则?
单元测试与重构
持续重构
果断重构
让测试始终能通过
留条出路
可测试的代码
做不到TDD,可以做到测试先行
如何理解单元测试代码覆盖率
不要把它们变成管理的指标。
这就是你使用覆盖率数字的目的:使用它们作为衡量标准来帮助你改进,而不是用它们作为惩罚团队和使构建失败的棍棒。 ——《匠艺整洁之道》
沉淀最佳实践
隔离单元测试与集成测试
集成测试是对一个工作单元进行的测试,这个测试对被测试的工作单元没有完全的控制,并使用该工作单元一个或多个真实依赖,例如时间、网络、数据库、线程或随机数生成器等。
单元测试与ABTest
写在最后
参考文档
《单元测试的艺术》 《有效的单元测试》 《Succeeding with Agile》 《匠艺整洁之道》 The Test Pyramid:https://martinfowler.com/articles/practical-test-pyramid.html Software Engineering at Google:https://qiangmzsx.github.io/Software-Engineering-at-Google/#/zh-cn/Chapter-12_Unit_Testing/Chapter-12_Unit_Testing