Clean C++20学习 第二章
2.1 测试入门
金字塔模型
![[Pasted image 20230621212907.png]]
但是在实际的操作中,由于初级的单元测试被忽略,大量精力会投入到更高层次的测试,实际会呈现出倒金字塔模式
![[Pasted image 20230621213640.png]]
2.2 单元测试
单元测试的优势
- 可以看作一种可执行文档,准确的揭示了代码的使用方式
- 方便检测退化,展示经过调整后发生异常的部分
- 单元覆盖率高可以避免过多的不必要调试
- 单元测试可以促进整洁良好的接口设计
- 提高开发速度
2.3良好的单元测试原则
2.3.1单元测试代码质量
必须保证和产品代码质量一致
2.3.2单元测试命名
![[Pasted image 20230621214743.png]]
为单元测试起一个名称 类似
必须富有变现力和描述性名称!
如何富有表现力,名称中应该包含
- 测试场景的前置条件,在测试运行之前被测系统的状态
- 正在被测试爹部分,一般是测试的逻辑过程,函数,方法 ,API
- 预期的测试结果一些富有表现力的单元测试名字
1
<PreconditionAndStateOfUnitUnderTest>_<TestedPartOfAPI>_<ExpectedBehavior>
![[Pasted image 20230621215630.png]]
![[Pasted image 20230621215638.png]]
另一种命名方法是在名称中体现具体的需求,反应应用层面的需求
![[Pasted image 20230621220252.png]]
2.3.3 单元测试的独立性
应该互相独立,如果单元测试需要按特定的顺序执行,这将会影响测试的进行。要尽量避免单例依赖(后续章节详细展开)
2.3.4 One Assertion per Test
一个单元测试只有一个断言
![[Pasted image 20230621220752.png]]
![[Pasted image 20230621220759.png]]
多个断言的缺点
- 测试失败的原因有很多种,失败的断言会屏蔽其他错误
- 多个断言名称会困难
2.3.5 单元测试环境的独立初始化
一个单元测试执行完毕后,与该单元测试相关的状态都应该小时,部分实例话,同时已经改及时进行清理
2.3.6 Exclude Getters and Setters
2.3.7 避免测试代码与生产开代码的混淆
![[Pasted image 20230621221553.png]]
这段代码中通过 inTestMode 这个成员变量来判断是否要去测试。但是在实际的项目Customer类中引入了为了测试的函数,因此提出两种解决方案,保证生产代码的纯粹![[Screenshot 2023-06-21 at 10.28.00 PM.png]]![[Pasted image 20230621222901.png]]
2.3.8 Test Doubles (Fake Objects) 测试替身
被测试的单元对其他单元的外部系统以来关系必须被替换为测试替身(Test Doubles)
松耦合!
![[Pasted image 20230621223256.png]]
举例说明,开发一个需要使用web服务进行实时货币转化的应用,需要使用测试替身来替换实时对转换服务,通过接口 C++中的纯虚成员函数的抽象类
接口
![[Pasted image 20230621223623.png]]
实际代码
![[Pasted image 20230621223727.png]]
测试替身
![[Screenshot 2023-06-21 at 10.37.58 PM.png]]
调用转换服务的代码
![[Pasted image 20230621224029.png]]
![[Pasted image 20230621224036.png]]
对UserOfConversionService进行单元测试的时候,可以在初始化的时候,传入模拟对象
![[Pasted image 20230621224204.png]]