当前位置: 首页 > web >正文

【测试开发知识储备】之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覆盖率统计工具
    在这里插入图片描述

  • 导出本地日志,保存后会自动打开报告可以查看
    在这里插入图片描述

在这里插入图片描述

效果

在这里插入图片描述

http://www.xdnf.cn/news/6322.html

相关文章:

  • SVNAdmin管理使用教程
  • Problem E: List练习
  • 力扣刷题(第二十六天)
  • 运筹说 第136期 | 其他类型对策简介之合作对策
  • BGP联邦和发射试验
  • Linux wlan 单频段 dual wifi创建
  • git中忽略文件.gitignore文件的用法
  • 2025年AI开发者在开发者占比?
  • 进阶2_1:QT5多线程与定时器共生死
  • 深度剖析火狐飞鸟 MIP 泛目录程序:技术原理与实践应用
  • .NET程序启动就报错,如何截获初期化时的问题json
  • E. 23 Kingdom【Codeforces Round 1024 (Div. 2)】
  • 1669上什么课
  • day29-IO(其他流)
  • Java基础(多线程1)
  • 鸿蒙-5.1.0-release构建编译环境
  • 分割等和子集习题分析
  • HCIP(OSPF的拓展配置及选路规则)
  • 矩阵乘法的优化与复杂度分析
  • 一个日志量突增的问题分析处理经历
  • 普通IT的股票交易成长史--20250514复盘
  • 机器学习任务的常用评估指标
  • JVM内存模型
  • 前端面试题:vue3 为什么不需要时间分片?
  • Linux程序设计--期末复习
  • 企业网络新选择:软件定义架构下的MPLS
  • 【Docker】Windows10环境下安装DockerDesktop
  • TCP 三次握手建立连接详解
  • C2S-Scale:Cell2Sentence v2
  • 在星河社区学习PARL使用强化学习来训练AI