软件测试用例覆盖率怎么算,如何计算增量测试覆盖率
为了保证代码质量,一般会要求提交的源码要有测试用例覆盖,并对测试覆盖率有一定的要求,在实践中不仅会考核存量代码覆盖率(总体覆盖率)还会考核增量代码的覆盖率。
或者说增量覆盖率更有实际意义,测试用例要随源码一并提交,实时保证源码的质量,而不是代码先行,测试用例后补,这有些应付的意思。
对于存量代码覆盖率主流的测试工具(框架)都是默认支持的,配置reporter相关参数,执行完测试用例就会生成测试报告。
对于增量测试覆盖率主流的测试工具一般没有支持,我想计算增量代码貌似不是测试工具该干的事,所以主流测试工具并没有提供这一功能。
那么如果计算增量覆盖率呢?
计算增量测试覆盖率,总共需要3步:
·计算出增量代码的所有行号
·计算出测试未覆盖的代码的所有行号
·对比计算增量代码被测试覆盖的比例,得出增量覆盖率
是不是很简单,有没有一种 “道理我都懂,就是过不好这一生的赶脚”
一、计算增量代码的所有行号
代码管理一般都会用到 GIT 这个工具,GIT提供了非常强大的管理增量代码的能力,因此,可以利用GIT这一特性,通过git diff(参考文献1) 这个命令获取增量代码。
git diff命令可以使用如下格式,用来对比不同commit(或分支)间的增量代码
git diff []
其中可以是分支名,对比分支间的差异,则是 git diff [] targetBranchName sourceBranchName。可以简写为 git diff targetBranchName 表示对比当前分支与目标分支间的代码增量差异。
例如 git diff master 生成当前分支与master分支的增量信息,当有多个文件变化时,会有多个这样的信息块。
·第1部分是发生变化的文件名。---表示文件发生了删除行 +++表示文件发生了新增的行,当---和+++后面是文件路径(相对代码根目录的相对路径)。
·如果某个文件是新增文件,则---后面是/dev/nul
·如果某个文件被删除了,则+++后面是/dev/nul
·如果文件发生修改,则---和+++后面都有文件名
·先介绍第3部分,因为第2部分的解读需要用第3部分辅助。第3部分是详细的含有上下文的增量信息(增量不是指增加,删除也算增量)
- 表示这一行被删除
+ 表示这一行是新增
如果某一行发生修改,则由一条-和一条+表示
·第2部分是变化的行号信息,以 @@开头和结尾,中间是删除的行号信息和新增的行号信息,以上图为例
-1,11表示,文件出现删除,从第1行开始包含上下文信息一共有11行,在第3部分中分别是第6, 8, 9, 10, 12, 13, 14, 15, 16, 17, 25 行,共11行
+1,18表示,文件出现新增,从第1行是包含上线文信息一共18行,在第3部分中分别是第7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25 行,共18行
其中,第8, 9, 10, 12, 13, 14, 15, 16, 25 行是上下文信息,真正删除的行是第6, 17 行,共2行; 新增的行是第7, 11, 18, 19, 20, 21, 22, 23, 24 行,共9行。
不难发现,git diff 默认给出的行号信息,不仅包含真正删除和增加的行,还包含一定的上下文信息(为的是给人看时,能看出到底改了哪些行信息,尤其在一个文件有很多相似或重复的语句的情况下)。并且在计算删除的行的行数时(-1,11中的11)要过滤掉增加的行后再计算,反之亦然(+1,18中的18)。
通过上面的命令确实能计算出增量代码的实际行号(有开始行号,有行数,有差异信息),但对于第3部分的差异信息的解析存在一定的难度,不仅要过滤掉对向信息,还要过滤掉上下文信息。
经查阅文档,发现git diff有一个options是--unified=,简写-U。使用此参数来决定diff结果中上下文信息显示n行,而不是默认的3行。
使用 git diff --unified=0 master 或 git diff -U0 master看运行结果:
数据结构与不带options的结果基本一致,只不过第2部分和第3部分作为一个整体可能会出现1次或多次,还有一点变化是第2部分行号信息的表达出现了三种格式。
-(+)后面只有一个数字,数字是,表示删除(增加)了1行,行号是。此例中-1, +1, +5, -10分别表示第1行删除1行,第1行增加1行,第5行增加1行,第10行删除一行。
-(+)后面有两个数字,第一个数字是,第二个数字是0, 表示删除(增加)了0行,即m行没有变化,此例中-4,0表示第4行没有变化
-(+)后面有两个数字,第一个数字是,第二个数字是,不是0,表示删除(增加了)n行,起始行号是m。此例中+11,7表示从第11行开始,共增加了7行,行号一次递增,即 11, 12, 13, 14, 15, 16, 17 这几行。
因此,计算增量代码的信息只使用第1部分和第2部分就可以完成,由第1部分计算出增量代码的路径,由第2部分的+后面的数字计算得到增量代码的行号(-后面是删除的行信息,不是增量代码)。本例中a.js文件的增量行号是[1, 5, 11, 12, 13, 14, 15, 16, 17]。
由于git diff生成的是固定格式纯文本,解析增量信息时可以按行读取字符串后做正则解析即可。对于linux系统,可以通过管道符|将diff文本导给grep命令(参考文献2),使用正则匹配出需要的信息,命令如下:
git diff -U0 master | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
生成结果如下图,此时,再按行遍历,生成以文件路径为Key,增量行号组成的Array为值的Hash表,用于后续逻辑的索引。
二、计算测试未覆盖的代码的所有行号
计算未被测试覆盖的行号,需要先在当前分支运行测试脚本生成对应的测试报告。
测试报告有很多种格式,其中http://lcov.info(参考文献3)是一种描述源码覆盖率的纯文本格式的文件,因此它非常便于计算,可利用此文件计算得到未被覆盖的行号。
http://lcov.info文件内容如下图:
数据包含以下字段,因工具不同,字段出现的顺序会略有变化
·TN: 用例名称,[因工具不同,有的无法生成此字段]
·SF: 源文件路径,[因工具不同,有的是绝对路径,有的是相对路径]
·FN:, 函数起始行号,函数名称,[因工具不同,有的函数名无法生成]
·FNDA:, 函数被执行次数,函数名称,[因工具不同,有的函数名无法生成]
·FNF: 识别统计到的函数数量
·FNH: 被测试覆盖的函数数量, FNH / FHF即函数覆盖率
·BRDA:,,, 条件分支所在行号,块号,分支号,被执行的次数
·BRF: 识别统计到的条件分支数量
·BRH: 被测试覆盖的条件分支数量 BRH / BRF 即分支覆盖率
·DA:,[,] 行号,执行次数, 检验和,[因工具不同,有的有校验和,有的没有]
·LH: 被测试覆盖的行数量
·LF: 可被执行的行数量, LH / LF 即行覆盖率
·end_of_record 统计信息块结束符,一个文件一个块
由此可见,计算未覆盖代码的行号,只需要提取覆盖率数据中SF和DA字段的值即可
·SF是源码文件路径
·DA字段有两个数字,第1个是行号,第2个是执行次数,半角逗号分隔,执行次数的值是0的即是未被覆盖的行
同解析diff增量数据一样,解析覆盖率数据时也可以按行读取字符串后做正则解析即可。对于linux系统,可以通过管道符|连接cat和grep命令(参考文献2),使用正则匹配出需要的信息,命令如下
cat coverage/lcov.info | grep -Po '^SF:\K.*|^DA:\K[0-9]+(?=,0)'
生成的结果如下图,得到未被覆盖的行号,再按行遍历,生成以文件路径为Key,增量行号组成的Set为值的Hash表,用于后续逻辑的索引:
三、最后一哆嗦
得到上面两份数据,就可以计算得出每个文件的增量覆盖率和总体增量覆盖率了。
但还需要考虑一种情况:由于一些原因(可是配置文件的问题)导致一些源码文件未被统计到测试覆盖率报告中,那么 + 有意为之,则增量文件不用计入增量覆盖率中,此文件的增量覆盖率是 100% + 无意为之,则增加文件需要计入增量覆盖率中,此文件的增量覆盖率是 0
伪代码如下:
const incData = { // 增量代码行号Hash表
'path/a.js': [1, 2, 3],
'path/b.js': [2, 3, 4],
...
}
const notCovData = { // 未覆盖代码行号的Hash表
'path/b.js': 'Set(3) {1, 2, 3}',
'path/c.js': 'Set(3) {1, 2, 3}',
...
}
let notCovLintCount = 0
let lineCount = 0
forEach(incData, (data, file) => {
const notCovSet = notCovData.get(file)
const notCovLines = []
if (notCovSet) { // 如果增量代码文件中有未覆盖的行数
forEach(data, lineNum => {
if (notCovSet.has(lineNum)) {
notCovLines.push(lineNum)
}
})
} else { // 增量代码的文件没有被测试覆盖到
if (!ignore) { // 如果是无意为之,所有行号均被统计
notCovLines = notCovLine.concat(data)
}
}
console.log(file, '增量覆盖率:', (1 - notCovLines.length / data.length).toFixed(2) + '%')
lineCount += data.length
notCovLineCount += notCovLines.length
})
console.log('总体增量覆盖率:', (1 - notCovLintCount / lineCount).toFixed(2) + '%')
至此,分支间的增量代码的测试覆盖率计算完成。
详细的实现逻辑可参考 nodejs版本
实践与应用
·一般会用于CI检测中,在test step后添加增量覆盖率检测脚本,增量覆盖率未达标的代码禁止并入代码库
·也可用于git hook中做检测(这会增加提交代码的等待时长,不太建议),增量覆盖率未达标的代码禁止提交。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理
软件测试用例覆盖率怎么算,如何计算增量测试覆盖率相关推荐
- iOS 覆盖率检测原理与增量代码测试覆盖率工具实现
背景 对苹果开发者而言,由于平台审核周期较长,客户端代码导致的线上问题影响时间往往比较久.如果在开发.测试阶段能够提前暴露问题,就有助于避免线上事故的发生.代码覆盖率检测正是帮助开发.测试同学提前发现 ...
- ios 单元测试覆盖率怎么查看_iOS 覆盖率检测原理与增量代码测试覆盖率工具实现...
背景 对苹果开发者而言,由于平台审核周期较长,客户端代码导致的线上问题影响时间往往比较久.如果在开发.测试阶段能够提前暴露问题,就有助于避免线上事故的发生.代码覆盖率检测正是帮助开发.测试同学提前发现 ...
- 多环境多需求并行下的代码测试覆盖率统计工具实现
个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈 测试覆盖率常被用来衡量测试的充分性和完整性,也是测试有效性的一个度量.「敏捷开发」的大潮之下,如何在快速迭代的同时保证对被测代码的覆 ...
- 软件测试用例优秀例子_功能测试用例设计方法分享
测试用例可以用来衡量一个项目测试质量,因此在平时的测试流程中,编写测试用例就是测试过程中很重要的一步,每一个测试工程师都需要并且非常熟练的编写测试用例,能在编写测试用例中尽可能的覆盖任何异常的测试点: ...
- 测试覆盖率是软件测试的重要组成部分?当然是,必须是啊!
摘要: 就软件质量而言,测试覆盖率是软件测试中的重要指标.接下来一起了解测试范围.测试技术,测试标准以及如何改进它.由于软件中普遍存在的错误,全世界都见证了一些灾难性事件.2008年在英国希思罗机场5 ...
- 测试覆盖率之一——测试覆盖率分类(转)
转一篇,别人写的关于覆盖率的文章,没事常看看琢磨琢磨 测试覆盖率之一--测试覆盖率分类(转) 关于覆盖率,网络上最常见的两个词应该是"测试覆盖率"(Test Coverage)和& ...
- 测试覆盖率工具--EMMA
测试覆盖率(Code Coverage) 测试覆盖率,简单的说,就是评价测试活动覆盖产品代码的指标.测试的目的,是确认产品代码按照预期一样工作,也可以看作是产品代码工作方式的说明文档.进一步考虑,测试 ...
- Go测试覆盖率 - Goc
先聊聊,为什么要有测试覆盖率? 设想以下场景: 1,自动化组,长期做接口黑盒测试 2,业务组,针对单项目做系统测试 这种情况,会导致对所测系统的覆盖度未知.而综合覆盖率收集系统,尤其适合没有白盒测试的 ...
- matlab 测试覆盖率分析,简单几步分析测试覆盖率
太久没有更新博客了,当初承诺的周更快变成月更了,(⊙﹏⊙)b 上次介绍了单元测试的重要性和如何开始写单元测试,今天再推荐给大家一种分析测试覆盖率的工具NUnit.本文测试环境为windows 10 + ...
- .Net core基于xUnit的单元测试查看测试覆盖率
写代码如何保证代码质量,基本大家都知道要做单元测试,那如何知道你单元测试是不是测试到了所有代码场景呢,这就要通过测试覆盖率来体现了. 测试覆盖率,一般来说主要是Line代码行数覆盖率,同样还会有Bra ...
最新文章
- IT小小鸟VS.小小小鸟:展翅,我们一起翱翔!
- 【每日算法】桶排序算法
- powerdesigner基本使用 - 创建概念模型
- Elasticsearch-集群原理
- cv2 imshow窗口大小_cv2.imshow()图片无法显示
- 挖槽!堪称神级的Java技术手册火了???(文末送书活动)
- (转) 微软项目管理培训笔记(一)
- springboot+jsp+mybatis项目实例(后台成功,但是无法跳转jsp页面,没有实体类的注解,看springboot+jsp第二弹相关配置,即可成功配置jsp)...
- mysql 多点在 多边形,在MySQL中获取多点空间数据
- 宿命传说2之女神召唤java_热血传奇:传奇那些传说中的秘密,连骨灰级的玩家都未必知道...
- 【优化分类】基于matlab改进的人工蜂群算法优化SVM分类【含Matlab源码 1833期】
- 0906--学成在线页面案例
- 剖析车联网的完美形态,机器人化还是智能交通?
- unity3d 词典访问_正确的词典访问方式
- 计算机科学人工智能的应用,计算机人工智能技术的应用与发展.pdf
- fiddler 手机代理上网 通过代理服务器进行身份验证失败
- OneTab Plus|标签管理大师
- 爪哇国新游记之三十二----邮件发送
- 哗哗地照样子写词语_描写哗哗的词语
- 网易2018校园招聘:合唱 [python]
热门文章
- Ruby语言的特别之处
- 左拥快手右抱抖音,丁磊直播究竟图什么?
- BZOJ 5477: 星际穿越
- pow是什么意思python,python中pow什么意思
- 8款实用的Jquery瀑布流插件
- android微信认证失败怎么办,微信登陆好友头像验证失败该怎么办?
- Mybatis“四大神兽”
- 移动Win7用户文件夹(我的文档)默认位置至D盘
- 计算机骂人的专业术语,台湾网友分享“如何用本专业术语骂人不带脏字”
- 邮件安全证书(S/MIME),如何申请邮件证书