上一篇文章中,我们谈到了通过Roslyn进行代码分析,通过自定义代码扫描规则,将有问题的代码、不符合编码规则的代码扫描出来,禁止签入,提升团队的代码质量。
.NET Core技术研究-通过Roslyn全面提升代码质量
今天我们基于第二篇:基于Roslyn技术,扫描单元测试代码,通过单元测试覆盖率和执行通过率,严控产品提测质量,覆盖率和通过率达不到标准,无法提交测试。
首先,我们先讨论一下,什么是单元测试,单元测试的覆盖率统计。
一、什么是单元测试
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,C#里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。
总的来说,单元就是人为规定的最小的被测功能模块。同时,
单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
在实际研发中,很多团队浪费大量的时间和精力编写单元测试,那么“好的”单元测试是什么样的呢?
好的单元测试可以覆盖应用程序行为的不同情况和方面
好的单元测试应该结构良好的代码,包含测试准备、执行、断言、测试清理
好的单元测试每个都只测试一个最新的功能、代码单元
好的单元测试是独立和隔离的:什么都不依赖,不访问全局状态,文件系统或数据库。
好的单元测试是可描述的:见名知意。
好的单元测试是可重复执行的:无论何时运行,无论在何处运行都通过。
好的单元测试运行的很快
二、如何管理、评估单元测试的覆盖率和通过率
业界通常的做法有:
1. 代码行数覆盖率
2. 类、方法、条件分支覆盖率
3. 单元测试类型覆盖情况:正常、异常、性能、边界
4. 业务场景覆盖情况
但是会产生对单元测试一些误区、错误理解:
覆盖率数据只能代表你测试过哪些代码,不能代表你是否测试好这些代码。(比如上面第一个除零Bug)
不要过于相信覆盖率数据。
不要只拿语句覆盖率(行覆盖率)来考核研发交付质量
路径覆盖率 > 判定覆盖 > 语句覆盖
开发人员不能盲目追求代码覆盖率,而应该想办法设计更多更好的用例,哪怕多设计出来的用例对覆盖率一点影响也没有
经过内部架构师团队的技术交流和讨论,我们达成了以下共识:
我们如何写好、用好、管好单元测试?
面:覆盖核心微服务的实现,即:核心重要的微服务必须覆盖单元测试
点:单元测试场景要尽可能地覆盖
结构:单元测试要有完备的断言
类型:单元测试尽可能的覆盖正常、异常、性能、边界
可设计评估:概要设计时,确定并录入功能的单元测试场景,开发完成提测时保证单元测试覆盖率
管理:单元测试情况能全面上报管理起来,以进一步控制开发交付的质量
通过率:100%通过方可发起CI,生成补丁
在此基础上,我们启动了今年单元测试推动工作,主要的方案是这样的:
1. 增加一个单元测试注解,将一些关键的业务属性进行标注、上报,比如:微服务标识、微服务类型、单元测试集、单元测试说明、负责人、单元测试类型(正常、异常、性能、边界等)
2. CI持续集成时,必须运行单元测试工程,通过将单元测试执行结果上报到研发效能平台,保障后续补丁提测时控制单元测试通过率,同时单元测试通过率低于95%,无法生成补丁
3. 单元测试统一在研发效能平台中管理,即支持单元测试信息上报到管理平台中,方便后续代码提测时进行:核心微服务单元测试覆盖率控制
通过以上系统约束+管理规定,实现产品提测质量的控制。如何实现上述三个关键技术点呢?
增加单元测试注解、扫描单元测试注解情况、上报单元测试到研发效能平台。
接下来,第三部分,我们将引入Roslyn来完成单元测试代码分析
三、增加单元测试注解,让单元测试具备更多有价值的信息
正如上面所讲,我们增加一个了单元测试注解,将一些关键的业务属性进行标注、上报,比如:微服务标识、微服务类型、单元测试集、单元测试说明、负责人、单元测试类型(正常、异常、性能、边界等)。
UnitTestAttribute