导航
1前言
2什么是单元测试
3为什么要进行单元测试
3.1降低代码缺陷
3.2推动架构优化
3.3守护代码迭代质量
4如何进行单元测试
4.1使用AAA规则编写测试用例
4.2让每个测试用例符合AIR特性
4.3在需要的时候使用测试替身
4.4了解单元测试覆盖方式
4.5单元测试过程中的一些常见疑问
5可测试性设计
5.1分层设计
5.2抽象设计
5.3依赖注入
6可测试性编码
6.1注入协作对象
6.2不要依赖静态方法
6.3不要依赖全局变量
6.4不要为了测试而测试
7使用测试框架
7.1GTest简介
7.2使用GTest编写单元测试用例
7.3单元测试覆盖率统计
8单元测试的成败关键
8.1时间与成本预算
8.2在软件架构设计阶段整体考虑可测试性(架构师)
8.3在编码阶段具备可测试性意识(开发工程师)
9后记
1 前言
这篇文章源于工作中的一个项目,2021年,我负责汇川技术工业机器人应用软件的基础架构重构,当时单元测试是重构工作的核心环节之一,从无法进行单元测试到最终60%以上的行覆盖率,过程中自己也有非常多的收获,于是将其整理成文,希望对计划开展和正在开展单元测试的同学有所帮助。文章来源:https://www.wubayue.com
2 什么是单元测试
单元测试(Unit Testing),是指对软件中的逻辑单元或组件进行检查和验证,以确保其按预期执行。通常单元测试是软件开发过程中进行的最低级别测试活动,通过单元测试可发现和修复软件开发早期的BUG和缺陷。
单元(Unit),是一个应用程序中最小的可测试部分,在面向过程开发中,单元通常为函数(Function),在面向对象开发中,单元通常为类中的方法(Method)。文章来源:https://www.wubayue.com
3 为什么要进行单元测试
3.1 降低代码缺陷
单元测试的首要目标是降低代码缺陷,如上图所示,当代码缺陷越早被发现,它的修复成本就越低,这种把测试尽量提前进行的思想就叫做测试左移。
3.2 推动架构优化
单元测试与软件架构有着非常紧密的联系,通常越是架构设计优秀的项目(比如符合SOLID规则),越容易实施单元测试,反之越是架构糟糕的项目,越难以实施单元测试。并且单元测试以及其严格的方式要求软件架构设计,如果架构设计存在问题,单元测试就根本无法开展。
假如你发现在自己的项目中实施单元测试举步为艰,那么首先应该停下来观察和思考一下,项目架构设计的是否合理?比如一些项目中UI与业务逻辑耦合,单元测试无法命中核心业务逻辑,可思考一下项目是否需要分层设计?UI与业务逻辑是否需要分离?比如项目中当碰到物理设备的依赖,单元测试就被阻断,可思考一下是否永远只使用这一台设备?后续有没有可能换成其它设备?是否需要考虑扩展性?再比如发现被测对象就是铁板一块,根本不能改变其协作对象的行为和数据,那么就应思考一下,对象之间是否存在强耦合?是否可以通过依赖注入降低和消除对象之间的耦合?
大多数情况我们在项目中实施单元测试的目的是为了保障代码质量,但我认为单元测试对软件架构优化的驱动实际更为重要。
3.3 守护代码迭代质量
在当下的商业环境中,大鱼吃小鱼,快鱼吃慢鱼,对软件开发的效率要求越来越高,传统的瀑布开发模式越来越少,敏捷开发模式越来越普及。因此软件版本快速迭代,快速测试,快速发布,小步快跑在大多数项目中成为常态。
而单元测试在代码快速迭代过程中发挥着守护代码质量的至关重要作用。当单元测试覆盖了一个模块中的业务逻辑,该业务逻辑在迭代变更过程中出现任何问题,会第一时间自动被单元测试捕获,因此单元测试对发生变更的代码正确性提供了保障,同时开发人员在这样的保障下可以大胆的对代码进行重构,对业务逻辑进行增减变更调整。大名鼎鼎的TDD(测试驱动开发)就是基于这个原理。文章来源:https://www.wubayue.com
4 如何进行单元测试
4.1 使用AAA规则编写测试用例
我们用一个简单的示例来演示单元测试的编码过程,如下代码所示,是一个非常简单的方法,它根据不同的距离,推荐不同的交通工具:
[code]class UnitTestDemo{ public: // 一个被测方法,根据距离推荐交通工具 // distance参数:距离(单位为千米) string StransportForDistance(float distance) { // 100公里内推荐的士 if (distance |