鉴于上篇jacoco增量覆盖率实践实现了差异代码获取和jaocco二开后,很多咨询我的是测试的小伙伴,对java可能不太熟悉,想要直接使用又赶脚稍许迷茫,所以又写下这边文章来帮助迷茫中的小伙伴拉
首先说明一下实现此增量方案所依赖的组件
首先你需要了解jacoco的实现步骤,知道单元测试覆盖率和功能测试覆盖率,而我们通常讲的增量覆盖率一般讲的也是功能测试覆盖率
其实单元测试和功能测试其实分别对应jacoco的offline模式和on-the-fly模式
offline模式就是在测试之前先对文件进行插桩,生成插过桩的class或jar包,测试插过桩的class和jar包,生成覆盖率信息到文件,最后统一处理,生成报告。
而on-the-fly模式则是JVM通过 -javaagent参数指定jar文件启动代理程序,代理程序在ClassLoader装载一个class前判断是否修改class文件,并将探针插入class文件,探针不改变原有方法的行为,只是记录是否已经执行。
实现on-the-fly模式需要一下几个步骤
1.使用启动我们应用服务的时候,需要添加jvm参数 -javaagent,如:
-javaagent:[yourpath/]jacocoagent.jar=[option1]=[value1],[option2]=[value2]
具体实例如下:
java -javaagent:/tmp/jacoco/lib/jacocoagent.jar=includes=*,output=tcpserver,port=6300,address=localhost,append=true -jar demo-0.0.1-SNAPSHOT.jar
其中有个几个关键参数需要我们注意
- includes=*
这个代表了,启动时需要进行字节码插桩的包过滤,*代表所有的class文件加载都需要进行插桩。
你可以写成:
includes=com.test.service.*
这个参数我们可以用来做maven多模块的覆盖率,比如我们只想查看service服务层的覆盖率,我们可以通过设置包路径的方式进行只统计当前包的覆盖率
- output=tcpserver
output主要四个参数:
file
: At VM termination execution data is written to the file specified in thedestfile
attribute.(当jvm停止掉的时候产出dump文件,即服务挂了产出dump文件)
tcpserver
: The agent listens for incoming connections on the TCP port specified by theaddress
andport
attribute. Execution data is written to this TCP connection.(常用模式,将jacocoaget作为服务,每次通过cli包进行dump命令去获取dump包)
tcpclient
: At startup the agent connects to the TCP port specified by theaddress
andport
attribute. Execution data is written to this TCP connection.(将jacocoagent做为客户端,向指定ip和端口的服务推送dump信息)
none
: Do not produce any output.(不产出任何dump,dump个寂寞,忽略)此处需要有个说明:在k8s容器里面由于ip是动态的,
tcpserver模式的ip无法固定填写,可以
填 0.0.0.0 然后通过实际容器 ip 就可以访问到,而这个实际ip,一般可以从cmdb服务中动态获取
- port=98080
这是jacoco开启的tcpserver的端口,请注意这个端口不能被占用
- address=192.168.110.1
这是对外开发的tcpserver的访问地址。可以配置127.0.0.1,也可以配置为实际访问ip
配置为127.0.0.1的时候,dump数据只能在这台服务器上进行dump,就不能通过远程方式dump数据。
配置为实际的ip地址的时候,就可以在任意一台机器上(前提是ip要通,不通都白瞎),通过ant xml或者api方式dump数据。
举个栗子:
我如上配置了192.168.110.1:2014作为jacoco的tcpserver启动服务,
那我可以在任意一台机器上进行数据的dump,比如在我本机windows上用api或者xml方式调用dump。
如果我配置了127.0.0.1:2014作为启动服务器,那么我只能在这台测试机上进行dump,其他的机器都无法连接到这个tcpserver进行dump如果不知道本机ip地址,可以使用0.0.0.0,这样ip地址会绑定主机ip
2.我们需要使用cli包去获取exec文件
java -jar jacococli.jar dump --address 192.169.110.1 --port 2014 --destfile ./jacoco-demo.exe
使用这个命令会在我们调用方的服务上生成一个exec文件
3.生成report
java -jar jacococli.jar report ./jacoco-demo.exec --classfiles /Users/oukotoshuu/IdeaProjects/demo/target/classes/com --classfiles /Users/oukotoshuu/IdeaProjects/demo/target/classes/com --sourcefiles /Users/oukotoshuu/IdeaProjects/demo/src/main/java --sourcefiles /Users/oukotoshuu/IdeaProjects/demo/src/main/java --html report --xml report.xml
还是通过cli包去生成报告文件,注意这个classfiles和sourcefiles 可以是多个,我们如果是多模块项目通过指定代码路径和编译文件路径去分开做统计
以上就是jacoc原生知识点,相信大部分童鞋是清楚滴。
code-diff一个获取增量代码的服务,支持git(分支,tag,commitid)和svn(分支,rversion),具体实现已经在上篇讲解到,这里只讲使用
首先拉取代码,修改配置文件,主要修改git服务的账号和密码,以及拉取代码的存储地址
1、修改application.yml
##基于git
git:
userName: admin
password: 123456
local:
base:
dir: D:\git-test
##基于svn
svn:
userName: admin
password: 123456
local:
base:
dir: D:\svn-test
然后运行maven命令:
mvn clean package -Dmaven.test.skip=true
这样就可以获取到一个code-diff.jar包
找到一个服务器,将包扔上去,然后部署:
java -jar code-diff.jar
如此我们就算部署好差异代码服务了
运行项目,访问http://127.0.0.1:8085/doc.html(地址为部署服务ip)
输入git地址,填写差异分支的旧版本,新版本,执行,就可以获取差异信息
{
"code": 10000,
"msg": "业务处理成功",
"data": [
{
"classFile": "com/dr/application/InstallCert",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/controller/Calculable",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/controller/JenkinsPluginController",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/controller/LoginController",
"methodInfos": [
{
"methodName": "captcha",
"parameters": "HttpServletRequest&HttpServletResponse"
},
{
"methodName": "login",
"parameters": "LoginUserParam&HttpServletRequest"
},
{
"methodName": "testInt",
"parameters": "int&char"
},
{
"methodName": "testInt",
"parameters": "String&int"
},
{
"methodName": "testInt",
"parameters": "short&int"
},
{
"methodName": "testInt",
"parameters": "int[]"
},
{
"methodName": "testInt",
"parameters": "T[]"
},
{
"methodName": "testInt",
"parameters": "Calculable&int&int"
},
{
"methodName": "testInt",
"parameters": "Map&List&Set"
},
{
"methodName": "display",
"parameters": ""
},
{
"methodName": "a",
"parameters": "InnerClass"
}
],
"type": "MODIFY"
},
{
"classFile": "com/dr/application/app/controller/RoleController",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/controller/TestController",
"methodInfos": [
{
"methodName": "test",
"parameters": ""
},
{
"methodName": "getPom",
"parameters": "HttpServletResponse"
},
{
"methodName": "getDeList",
"parameters": ""
}
],
"type": "MODIFY"
},
{
"classFile": "com/dr/application/app/controller/view/RoleViewController",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/param/AddRoleParam",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/vo/DependencyVO",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/vo/JenkinsPluginsVO",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/app/vo/RoleVO",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/config/ExceptionAdvice",
"methodInfos": [
{
"methodName": "handleException",
"parameters": "Exception"
},
{
"methodName": "handleMissingServletRequestParameterException",
"parameters": "MissingServletRequestParameterException"
}
],
"type": "MODIFY"
},
{
"classFile": "com/dr/application/config/GitConfig",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/config/JenkinsConfig",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/ddd/StaticTest",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/ddd/Test",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/application/util/GitAdapter",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/common/errorcode/BizCode",
"methodInfos": [
{
"methodName": "getCode",
"parameters": ""
}
],
"type": "MODIFY"
},
{
"classFile": "com/dr/common/response/ApiResponse",
"methodInfos": [
{
"methodName": "success",
"parameters": ""
}
],
"type": "MODIFY"
},
{
"classFile": "com/dr/jenkins/JenkinsApplication",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/config/JenkinsConfigure",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/controller/JenkinsController",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/controller/TestApi",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/dto/JobAddDto",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/service/JenkinsService",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/service/impl/JenkinsServiceImpl",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/util/GenerateUniqueIdUtil",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/vo/DeviceVo",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/vo/GoodsVO",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/jenkins/vo/JobAddVo",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/repository/user/dto/query/RoleQueryDto",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/repository/user/dto/result/RoleResultDto",
"methodInfos": null,
"type": "ADD"
},
{
"classFile": "com/dr/user/service/impl/PermissionServiceImpl",
"methodInfos": [
{
"methodName": "getPermissionByRoles",
"parameters": "List"
},
{
"methodName": "buildMenuTree",
"parameters": "List"
},
{
"methodName": "getSubMenus",
"parameters": "Long&Map>"
}
],
"type": "MODIFY"
},
{
"classFile": "com/dr/user/service/impl/RoleServiceImpl",
"methodInfos": [
{
"methodName": "getByUserId",
"parameters": "Long"
},
{
"methodName": "getListByPage",
"parameters": "RoleQueryDto"
}
],
"type": "MODIFY"
}
],
"uniqueData": "[{\"classFile\":\"com/dr/application/InstallCert\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/Calculable\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/JenkinsPluginController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/LoginController\",\"methodInfos\":[{\"methodName\":\"captcha\",\"parameters\":\"HttpServletRequest&HttpServletResponse\"},{\"methodName\":\"login\",\"parameters\":\"LoginUserParam&HttpServletRequest\"},{\"methodName\":\"testInt\",\"parameters\":\"int&char\"},{\"methodName\":\"testInt\",\"parameters\":\"String&int\"},{\"methodName\":\"testInt\",\"parameters\":\"short&int\"},{\"methodName\":\"testInt\",\"parameters\":\"int[]\"},{\"methodName\":\"testInt\",\"parameters\":\"T[]\"},{\"methodName\":\"testInt\",\"parameters\":\"Calculable&int&int\"},{\"methodName\":\"testInt\",\"parameters\":\"Map&List&Set\"},{\"methodName\":\"display\",\"parameters\":\"\"},{\"methodName\":\"a\",\"parameters\":\"InnerClass\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/application/app/controller/RoleController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/TestController\",\"methodInfos\":[{\"methodName\":\"test\",\"parameters\":\"\"},{\"methodName\":\"getPom\",\"parameters\":\"HttpServletResponse\"},{\"methodName\":\"getDeList\",\"parameters\":\"\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/application/app/controller/view/RoleViewController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/param/AddRoleParam\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/vo/DependencyVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/vo/JenkinsPluginsVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/vo/RoleVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/config/ExceptionAdvice\",\"methodInfos\":[{\"methodName\":\"handleException\",\"parameters\":\"Exception\"},{\"methodName\":\"handleMissingServletRequestParameterException\",\"parameters\":\"MissingServletRequestParameterException\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/application/config/GitConfig\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/config/JenkinsConfig\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/ddd/StaticTest\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/ddd/Test\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/util/GitAdapter\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/common/errorcode/BizCode\",\"methodInfos\":[{\"methodName\":\"getCode\",\"parameters\":\"\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/common/response/ApiResponse\",\"methodInfos\":[{\"methodName\":\"success\",\"parameters\":\"\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/jenkins/JenkinsApplication\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/config/JenkinsConfigure\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/controller/JenkinsController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/controller/TestApi\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/dto/JobAddDto\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/service/JenkinsService\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/service/impl/JenkinsServiceImpl\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/util/GenerateUniqueIdUtil\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/vo/DeviceVo\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/vo/GoodsVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/vo/JobAddVo\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/repository/user/dto/query/RoleQueryDto\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/repository/user/dto/result/RoleResultDto\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/user/service/impl/PermissionServiceImpl\",\"methodInfos\":[{\"methodName\":\"getPermissionByRoles\",\"parameters\":\"List\"},{\"methodName\":\"buildMenuTree\",\"parameters\":\"List\"},{\"methodName\":\"getSubMenus\",\"parameters\":\"Long&Map>\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/user/service/impl/RoleServiceImpl\",\"methodInfos\":[{\"methodName\":\"getByUserId\",\"parameters\":\"Long\"},{\"methodName\":\"getListByPage\",\"parameters\":\"RoleQueryDto\"}],\"type\":\"MODIFY\"}]"
}
在linux系统部署时请注意修改代码的基础路径和日志路径,如:
java -jar -Dlog.path=/app/data2/devops/code-diff/logs -Dgit.local.base.dir=/app/dat code-diff.jar
其中字段uniqueData的值为序列化差异代码的值,后续我们获取差异代码直接使用这个值即可,code-diff就是一个正常的java springboot项目,在我们使用时可以通过接口调用获取到差异代码再进行其他步骤
jacoco二开主要是对cli包的改造,同时匹配code-diff产生的代码格式进行匹配,这里同样只讲使用
我们可以拿到jacoco二开代码进行编译获取我们的cli包,当然你也可以直接使用,我已经打好了包,下载地址。另外启用服务时用的agent包可以使用我的也可以不使用我的,没什么关系。
用法和原生jacoco一模一样,只是如果你要获取增量代码覆盖率,需要传递一个--diffCode的参数,其中--encoding=utf8为了防止报告乱码,diffCode为code-diff服务获取的uniqueData字段
java -jar org.jacoco.cli-0.8.7-SNAPSHOT-nodeps.jar report jacoco.exec --classfiles \Desktop\feigin\web\build\classes
--classfiles \Desktop\feigin\biz\build\classes
--classfiles \Desktop\feigin\base\build\classes --sourcefiles \Desktop\feigin\web\src\main\java
--sourcefiles \Desktop\feigin\biz\src\main\java
--sourcefiles \Desktop\feigin\base\src\main\java --html report --xml jacoco.xml
--diffCode "[{\"classFile\":\"com/dr/application/InstallCert\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/Calculable\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/JenkinsPluginController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/LoginController\",\"methodInfos\":[{\"methodName\":\"captcha\",\"parameters\":\"HttpServletRequest&HttpServletResponse\"},{\"methodName\":\"login\",\"parameters\":\"LoginUserParam&HttpServletRequest\"},{\"methodName\":\"testInt\",\"parameters\":\"int&char\"},{\"methodName\":\"testInt\",\"parameters\":\"String&int\"},{\"methodName\":\"testInt\",\"parameters\":\"short&int\"},{\"methodName\":\"testInt\",\"parameters\":\"int[]\"},{\"methodName\":\"testInt\",\"parameters\":\"T[]\"},{\"methodName\":\"testInt\",\"parameters\":\"Calculable&int&int\"},{\"methodName\":\"testInt\",\"parameters\":\"Map&List&Set\"},{\"methodName\":\"display\",\"parameters\":\"\"},{\"methodName\":\"a\",\"parameters\":\"InnerClass\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/application/app/controller/RoleController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/controller/TestController\",\"methodInfos\":[{\"methodName\":\"test\",\"parameters\":\"\"},{\"methodName\":\"getPom\",\"parameters\":\"HttpServletResponse\"},{\"methodName\":\"getDeList\",\"parameters\":\"\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/application/app/controller/view/RoleViewController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/param/AddRoleParam\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/vo/DependencyVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/vo/JenkinsPluginsVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/app/vo/RoleVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/config/ExceptionAdvice\",\"methodInfos\":[{\"methodName\":\"handleException\",\"parameters\":\"Exception\"},{\"methodName\":\"handleMissingServletRequestParameterException\",\"parameters\":\"MissingServletRequestParameterException\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/application/config/GitConfig\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/config/JenkinsConfig\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/ddd/StaticTest\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/ddd/Test\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/application/util/GitAdapter\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/common/errorcode/BizCode\",\"methodInfos\":[{\"methodName\":\"getCode\",\"parameters\":\"\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/common/response/ApiResponse\",\"methodInfos\":[{\"methodName\":\"success\",\"parameters\":\"\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/jenkins/JenkinsApplication\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/config/JenkinsConfigure\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/controller/JenkinsController\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/controller/TestApi\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/dto/JobAddDto\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/service/JenkinsService\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/service/impl/JenkinsServiceImpl\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/util/GenerateUniqueIdUtil\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/vo/DeviceVo\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/vo/GoodsVO\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/jenkins/vo/JobAddVo\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/repository/user/dto/query/RoleQueryDto\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/repository/user/dto/result/RoleResultDto\",\"methodInfos\":[],\"type\":\"ADD\"},{\"classFile\":\"com/dr/user/service/impl/PermissionServiceImpl\",\"methodInfos\":[{\"methodName\":\"getPermissionByRoles\",\"parameters\":\"List\"},{\"methodName\":\"buildMenuTree\",\"parameters\":\"List\"},{\"methodName\":\"getSubMenus\",\"parameters\":\"Long&Map>\"}],\"type\":\"MODIFY\"},{\"classFile\":\"com/dr/user/service/impl/RoleServiceImpl\",\"methodInfos\":[{\"methodName\":\"getByUserId\",\"parameters\":\"Long\"},{\"methodName\":\"getListByPage\",\"parameters\":\"RoleQueryDto\"}],\"type\":\"MODIFY\"}]"
--encoding=utf8
最后我们总结下我们的增量方案
整个增量方案对原生jaocco基本无侵入,也不用源码改造,欢迎大家一起找bug,哈哈,最最后汇总所有jacoco文章