【测试开发知识储备】之Jacoco(Java Code Coverage)
文章目录
- Jacoco是什么
- Jacoco的主要功能
- (一)多样化覆盖率指标分析
- (二) 丰富的报告生成
- (三)实时数据收集
- Jacoco的工作原理
- (一)字节码增强
- (二)测试执行与数据收集
- 使用方法
- 需要工具
- 步骤
- 本地启动开启Jacoco覆盖率
- 效果
在测试过程中,为了解决 统计【行覆盖率】和【已经覆盖行数】两个指标,便于快速查看和复制,我们可以通过Jacoco去解决。
Jacoco是什么
Jacoco 是专门用于 Java 项目测试覆盖率检测的工具,由 EclEmma 项目演变而来。它能够精准地分析出代码中哪些部分已被测试覆盖,哪些部分尚未覆盖,为开发者优化测试用例提供了明确方向
Jacoco的主要功能
(一)多样化覆盖率指标分析
Jacoco 支持多种覆盖率指标,涵盖行覆盖、分支覆盖、方法覆盖和类覆盖等。行覆盖用于判断代码的每行是否至少有一个指令被执行;分支覆盖聚焦于如 if - else、switch 等语句分支的执行情况;方法覆盖判断方法是否被调用执行;类覆盖则确定类是否被执行。通过这些指标,开发者能全方位了解代码的测试覆盖状况。
(二) 丰富的报告生成
它能生成详细的覆盖率报告,且支持 HTML、XML 和 CSV 等多种格式。这些报告清晰展示代码的覆盖情况,突出显示未覆盖的代码区域,方便开发者分析和排查问题。
(三)实时数据收集
在测试运行时,Jacoco 可动态收集覆盖率数据,无需事后处理,能实时反映代码的测试状态,助力开发者迅速调整测试策略。
Jacoco的工作原理
(一)字节码增强
在测试运行前,Jacoco 会对 Java 字节码进行修改,插入覆盖率收集的逻辑,这一过程即 “字节码增强”。增强后的字节码包含用于记录代码路径执行情况的指令,为准确捕捉代码执行信息奠定基础。
(二)测试执行与数据收集
测试用例运行时,增强后的字节码会执行插入的覆盖率记录逻辑,实时收集代码行、分支、方法和类的执行信息。Jacoco 采用轻量级代理模式,对测试执行性能影响极小。测试完成后,Jacoco 汇总收集到的覆盖率数据,生成详细的覆盖率报告,清晰展示各代码单元的覆盖情况。
使用方法
需要工具
油猴插件:https://www.tampermonkey.net/
步骤
- 安装tampermonkey插件,并打开插件开关
- 点开详情,将允许访问文件网址打开,才可以生效与本地生成的jacoco覆盖率报告
- 通过管理面板,进入管理页面,新增脚本
- 通过添加新的脚本,将以下脚本键入并保存
// ==UserScript==
// @name 白盒覆盖率报告覆盖率插件
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 用于jacoco报告的计算行覆盖率!
// @author lulu
// @match https://coverage.myshopline.cn/jacoco/report/*
// @match file:///*.html
// @icon https://www.google.com/s2/favicons?sz=64&domain=myshopline.cn
// @grant GM_addStyle
// @grant unsafeWindow
// @grant GM_setClipboard
// @require https://unpkg.com/jquery@3.6.0/dist/jquery.min.js
// @require https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.all.min.js// ==/UserScript==(function() {'use strict';var element = document.querySelector("tbody");var thead = document.querySelector('td#i');var theadtdratio = document.createElement('td');var coveredtd = document.createElement('td');// 底部var foot = document.querySelector('tfoot > tr > td:nth-of-type(9)');var footcovered = document.createElement('td');var footratiotd = document.createElement('td');footcovered.setAttribute('class','ctr2')footratiotd.setAttribute('class','ctr2')foot.before(footcovered);foot.after(footratiotd);//设置表头theadtdratio.innerHTML = '行覆盖率比例';coveredtd.innerHTML = 'Covered';thead.before(coveredtd);thead.after(theadtdratio);var coveredConut = 0;// 获取地址var url =window.location.href;var baseUrl = url.substring(0,url.lastIndexOf('/')+1)console.log('读取地址:',baseUrl)for(var i=0; i<element.rows.length; i++){var miss = parseInt(element.rows[i].cells[7].innerHTML.replace(/,/g, ""));var lines = parseInt(element.rows[i].cells[8].innerHTML.replace(/,/g, ""));var link = element.rows[i].cells[0].querySelector('a').getAttribute('href');var covered = lines - missvar result =Math.round((1- miss/lines) * 10000) / 100;//添加结果var td = document.createElement('td');var alink = document.createElement('a');alink.innerHTML = result +'%'alink.href = baseUrl + linktd.appendChild(alink);td.setAttribute('class','ctr2');var coveredtd1 = document.createElement('td');coveredtd1.innerHTML = covered;coveredtd1.setAttribute('class','ctr2')element.rows[i].cells[7].after(coveredtd1);element.rows[i].cells[9].after(td);coveredConut += covered;//totalLines += result;/*//TODO 准备做一键复制var copyButton = document.createElement('span');copyButton.id = i;copyButton.innerHTML = miss +'\n' + lines +'\n' + resultelement.rows[i].appendChild(copyButton);copyButton.onclick = function(miss){//copy(miss+'\t'+lines+'\t'+result);console.log('copy:'+copyButton.innerHTML);//copy(parseInt(element.rows[i].cells[7].innerHTML.replace(/,/g, ""))+'\t'+parseInt(element.rows[i].cells[8].innerHTML.replace(/,/g, ""))+'\t'+td.innerHTML);}*///处于70-80if(result>=75 && result < 100){td.style.backgroundColor = '#00FFCC';}else if(result == 100){td.style.backgroundColor = 'green';}//低于70%else{td.style.backgroundColor = 'red';}//总覆盖率//totalLines += result;console.log(miss,lines,link,result);}footcovered.innerHTML = coveredConut;var tatolratiotd = coveredConut/parseInt(document.querySelector('tfoot > tr > td:nth-of-type(10)').innerHTML.replace(/,/g, "")) ;footratiotd.innerHTML = Math.round(tatolratiotd * 10000) / 100 + '%';if(tatolratiotd>=75 && tatolratiotd < 100){footratiotd.style.backgroundColor = '#00FFCC';}else if(tatolratiotd == 100){footratiotd.style.backgroundColor = 'green';}//低于70%else{footratiotd.style.backgroundColor = 'red';}const copy = (text) => {GM_setClipboard(text, 'text');}})();
- 打开对应开关即可
本地启动开启Jacoco覆盖率
-
编辑运行配置
-
调整运行模板的junit code coverage配置为项目目录,并选择jacoco覆盖率统计工具
-
导出本地日志,保存后会自动打开报告可以查看