JacocoReportSelectOper类的代码:
import os
class JacocoReportSelectOper(object):
"""
处理增量报告中的Index.html文件,过滤文件内容
"""
def correctIndexFile(self,packpath):
"""
更新一个目录下的index.html文件,去掉不是本次更新的的记录项目
:param packpath:
:return:
"""
#过滤目录下的文件
selectfilelist=[]
for i,j,k in os.walk(packpath):
for filename in k:
if filename.find("$")>-1 and filename.find("index.html")==-1:
tmpchange=filename[filename.index("$")+1:]
if tmpchange.find("$")>-1:
fnamejacoco=filename[0:filename.index("$")]+"."+tmpchange[0:tmpchange.index("$")]
else:
fnamejacoco=filename[0:filename.index("$")]+"."+tmpchange[0:tmpchange.index(".")]
if fnamejacoco not in selectfilelist and len(fnamejacoco)>0:
selectfilelist.append(fnamejacoco)
if filename.find("$")==-1 and filename.find("index.html")==-1 and len(filename)>0:
fnamejacoco=filename[0:filename.index(".")]
if fnamejacoco not in selectfilelist and len(fnamejacoco)>0:
selectfilelist.append(fnamejacoco)
#print(selectfilelist)
#处理该目录下的index.html文件
reportfile=open(packpath+"index.html","r")
reportcont=reportfile.read()
tempreport=open(packpath+"tmpindex.html","w")
#取测试报告的头部信息
getheadcont=reportcont[0:reportcont.index("</thead>")+8]
# print(getheadcont)
tempreport.write(getheadcont)
#过滤文件相关信息
rmisslines=0
rtotalline=0
detailcont=reportcont[reportcont.index("</thead>")+8:reportcont.index("</tbody>")]
detaillist=detailcont.split("</tr>")
for filedetail in detaillist:
for difffile in selectfilelist:
if filedetail.find(difffile)>-1:
#处理行覆盖率信息
linedetail=filedetail[filedetail.find('id="h'):filedetail.find('id="j')]
fmisline=linedetail[linedetail.index(">")+1:linedetail.index("<")]
temlined=linedetail[linedetail.index("class")+6:linedetail.rindex("class")]
ftotalline=temlined[temlined.index(">")+1:temlined.index("<")]
if fmisline.find(",")>-1:
fmisline=fmisline[0:fmisline.index(",")]+fmisline[fmisline.index(",")+1:]
if ftotalline.find(",")>-1:
ftotalline=ftotalline[0:ftotalline.index(",")]+ftotalline[ftotalline.index(",")+1:]
rmisslines=rmisslines+int(fmisline)
rtotalline=rtotalline+int(ftotalline)
#增量覆盖率内容
tempreport.write(filedetail+"</tr>")
break
print("最终的missed行:"+str(rmisslines)+",总行数:"+str(rtotalline))
tfootcont='<tfoot><tr><td>Total</td><td class="bar">-</td><td class="ctr2">-</td><td class="bar">-</td><td class="ctr2">-</td><td class="ctr1">-</td><td class="ctr2">-</td><td class="ctr1">'+str(rmisslines)+'</td><td class="ctr2">'+str(rtotalline)+'</td><td class="ctr1">-</td><td class="ctr2">-</td><td class="ctr1">-</td><td class="ctr2">-</td></tr></tfoot>'
tempreport.write(tfootcont)
#写入尾部信息
gettailcont=reportcont[reportcont.index("</tbody>"):]
tempreport.write(gettailcont)
tempreport.close()
os.system("rm -rf "+packpath+"index.html")
os.system("mv "+packpath+"tmpindex.html "+packpath+"index.html")
print("临时报告生成完成:"+packpath+"tmpindex.html")
def getReportHeader(self, branch):
"""生成增量覆盖率报告"""
headcontent = '''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<link rel="stylesheet" href="jacoco-resources/report.css" type="text/css"/>
<title>Diff Coverage</title>
</head>
<body>
<h1>Diff Coverage</h1>
'''
headcontent = headcontent + "<p>Diff: " + branch + "...HEAD, staged and unstaged changes</p>\r\n"
return headcontent
def getPackageLineMessage(self,rportpath):
"""
获取指定包的覆行信息
:param rportpath:
:return:
"""
reportfile=rportpath+"/index.html"
# print("reportfile="+reportfile)
rpcont=open(reportfile,"r").read()
sumcont=rpcont[rpcont.rindex("<tfoot>")+178:rpcont.rindex("</tfoot>")-102]
finalmsg=sumcont[0:sumcont.index("<")]+","+sumcont[sumcont.rindex(">")+1:]
return finalmsg
def createDiffReport(self,drpath,branch):
"""
生成汇总覆盖率报告
:param drpath:
:param branch:
:return:
"""
#获取diff的文件包列表
packagelist=[]
for i,j,k in os.walk(drpath):
for folder in j:
if folder.find("jacoco-resources")==-1:
packagelist.append(folder)
print(packagelist)
reportcontent = "<table class=\"coverage\" cellspacing=\"0\" id=\"coveragetable\">\r\n<thead><tr><th>Pagckages</th><th>Diff Coverage (%) </th><th width=\"100\">Total Lines </th><th width=\"100\">Missing Lines </th></tr></thead>\r\n"
totallines = 0
mislines = 0
for package in packagelist:
linesdetail=self.getPackageLineMessage(drpath+package)
fmissline=int(linesdetail[0:linesdetail.index(",")])
ftotaline=int(linesdetail[linesdetail.index(",")+1:])
#计算总行数
totallines=totallines+ftotaline
mislines=mislines+fmissline
#计算覆盖率
if ftotaline==0:
miscovrate=100
else:
miscovrate=int(fmissline/ftotaline*100)
# print("fmissline="+str(fmissline)+",ftotalline="+str(ftotaline)+",miscovrate="+str(miscovrate))
#拼接内容
reportcontent = reportcontent + "<tr><td><a href=\"./"+package+"/index.html\" class=\"el_package\">" +package+ "</a> </td>"
reportcontent = reportcontent + "<td class=\"bar\">" + "<img src=\"jacoco-resources/redbar.gif\" width=\"" + str(
miscovrate) + "\" height=\"10\">"
reportcontent = reportcontent + "<img src=\"jacoco-resources/greenbar.gif\" width=\"" + str(
100-miscovrate) + "\" height=\"10\"> " + str(100-miscovrate) + "%</td>"
# 2,总行数
reportcontent = reportcontent + "<td class=\"ctr1\">" + str(ftotaline) + "</td>"
# 3,没有覆盖的行数
reportcontent = reportcontent + "<td class=\"ctr1\">" + str(fmissline) + "</td>"
reportcontent = reportcontent + "</tr>\r\n"
reportcontent = reportcontent + "</table>"
# 添加头部信息及汇总信息
covlines = totallines - mislines
if totallines == 0:
covrate=0
else:
covrate = float(covlines) / float(totallines) * 100
headcontent = self.getReportHeader(branch)
headcontent = headcontent + "<ul>\r\n<li><b>Total</b>: " + str(totallines) + " lines</li>\r\n"
headcontent = headcontent + "<li><b>Missing</b>: " + str(mislines) + " lines</li>\r\n"
headcontent = headcontent + "<li><b>Coverage</b>: " + str(round(covrate, 2)) + " %</li>\r\n</ul>\r\n"
reportcontent = headcontent + reportcontent + "\r\n</body>\r\n</html>"
# 汇总报告写入文件
findreport = drpath + "index.html"
rf = open(findreport, "w")
rf.write(reportcontent)
rf.close
if __name__=='__main__':
jroper=JacocoReportSelectOper()
packpath="/Users/************"
print(jroper.getPackageLineMessage(packpath))
3,覆盖率合并模块
jacoco merge合并覆盖率的前提是同一版本的不同覆盖率文件合并,如果合并不同的版本,类文件的变化的直接丢掉所有的相关覆盖率数据。而业务测试同学的诉求是,在集成测试阶段,同一分支可以打不同的包进行测试,最后要看一下整个集成测试阶段的覆盖率情况。这就涉及到对不同diff函数以及其调用链路上函数覆盖率的去除,同时需要保留diff类中没有变化的函数的覆盖率数据,具体方案请看覆盖率全并相应的内容。
(1)CorrectMethodsLocOfCovLines类,修改ec文件,添加需要保留的覆盖率数据
# coding: utf-8
import json
import shutil
from AndroidCovAgent.CommitsMergeOperation.GitCompareBranchOper import GitCompareBranchOper
from AndroidCovAgent.Utils.Utils import Utils
import os,requests
class CorrectMethodsLocOfCovLines(object):
"""
根据覆盖率数据,校对受diff影响的函数的覆盖率情况
@author SXF
@date:2022-07-28
"""
def __init__(self):
self.diffcovdetail={}
def anylysisECFileContent(self,propath,srccommit,keepbuildid):
"""
解析受影响的函数,在指定的覆盖率数据中覆盖率的行号
:param propath:
:param ecfilename:
:param effect_methods:
:return:
"""
curpath=os.getcwd()
# 1,检测是否需要下载class文件
descclasses=propath+"/build_classes_" + keepbuildid.strip()
if not os.path.exists(descclasses):
os.chdir(propath)
classzipfile="build_classes_"+ keepbuildid.strip()+".zip"
classurl = "https://*********/build_classes_" + keepbuildid.strip() + ".zip";
downres=requests.get(classurl)
with open(propath+"/"+classzipfile,'wb') as f:
f.write(downres.content)
f.close()
#解压类文件压缩包
shutil.unpack_archive("./"+classzipfile,descclasses)
# 2,解析ec文件,获取针对diff的覆盖率信息
ecfilepath=propath[0:propath.index(srccommit)]+"/"+srccommit+"_merged.ec"
ecinfojson=propath+"/diffecfile.json"
scriptpath=Utils.SCRIPT_FILE_PATH
jacocoparse="java -jar "+scriptpath+"jacoco-parser2.0.jar -e "+ecfilepath+" -o "+ecinfojson+" --source "+propath+" --class "+descclasses
os.system(jacocoparse)
os.chdir(curpath)
#3,读取Json文件,过滤覆盖的行号
ecjsoncont={}
with open(ecinfojson,"r") as loadf:
ecjsoncont=json.load(loadf)
for key in ecjsoncont.keys():
detail=ecjsoncont.get(key)
if len(detail.get("covered"))>0:
newkey=detail.get("filename")
newkey=newkey[newkey.index("packages"):]
self.diffcovdetail[newkey]=detail.get("covered")
def correctLinesOfMethods(self,linelist,methoddict):
"""
根据受影响到的函数信息,校对行号
:param linelist:
:param methoddict:
:return:
"""
finallinelist=[]
for method in methoddict.keys():
linedetail=methoddict.get(method)
olderloc=linedetail.get("olderloc")
newloc=linedetail.get("newloc")
effectmethodline=[]
for line in linelist:
if line>olderloc[0] and line<olderloc[1]:
tmpspan=line-olderloc[0]
effectmethodline.append(newloc[0]+tmpspan)
if len(effectmethodline)>0:
effectmethodline.sort()
finallinelist.append(effectmethodline)
return finallinelist
def getMethodCovedInfo(self,linelist,methodlist):
"""
获取覆盖率数据中,函数的覆盖情况
:param linelist: 覆盖率文件中,对应类的覆盖行号
:param methodlist: 方法列表
:return:
"""
finallinelist=[]
for method in methodlist.keys():
linedetail=methodlist.get(method)
noeffectline=[]
for line in linelist:
if line>=linedetail[0] and line<=linedetail[1]:
noeffectline.append(line)
if len(noeffectline)>0:
noeffectline.sort()
finallinelist.append(noeffectline)
return finallinelist
def correctMethodsCovInfo(self,effect_methods,noeffect_methods):
"""
校准受diff影响的类的覆盖率数据
:param effect_methods:
:return:
"""
finaldiffcovinfo={}
#1,解析受影响的函数列表,在原覆盖率文件中的覆盖数据,并更新位置
for key in self.diffcovdetail:
if key in effect_methods.keys() and len(self.diffcovdetail[key])>0:
# 校对行号,转换成jacoco格式的覆盖率数据
newkey=key[key.index("com/"):key.index(".")]
finaldiffcovinfo[newkey]=self.correctLinesOfMethods(self.diffcovdetail[key],effect_methods[key])
#2,解析没有受的函数影响的函数列表,获取其在原覆盖率文件中的覆盖率数据
for key in self.diffcovdetail:
if key in noeffect_methods.keys() and len(self.diffcovdetail[key])>0:
fnewkey=key[key.index("com/"):key.index(".")]
if fnewkey in finaldiffcovinfo.keys() and len(finaldiffcovinfo[fnewkey])>0:
finaldiffcovinfo[fnewkey]=finaldiffcovinfo[fnewkey]+self.getMethodCovedInfo(self.diffcovdetail[key],noeffect_methods[key])
else:
finaldiffcovinfo[fnewkey]=self.getMethodCovedInfo(self.diffcovdetail[key],noeffect_methods[key])
#3,对finaldiffcovinfo中列表中的数据进行排序,保证行号按从小到大保存
for key in finaldiffcovinfo.keys():
finaldiffcovinfo[key].sort()
#print(finaldiffcovinfo)
return finaldiffcovinfo
def getNeedModifyLineInfo(self,proname,srccommit,descommit,keepbuildid,username):
"""
获取老版本中,需要保留的覆盖率信息
:param proname: 项目名称
:param srccommit: 源提交版本
:param descommit: 目标提交版本
:param keepbuildid: keep构建号
:return:
"""
#1,获取影响到的函数列表
gitoper=GitCompareBranchOper()
gitoper.get_diff_filelist(srccommit,descommit,proname,username)
#2,获取新老版本中受影响的函数的行号
locchangmethodlist=gitoper.correctChangeLocMethod(srccommit,proname,username)
#3,获取在diff类中,位置及内容都没有受到影响的函数列表
locnochangemethdlist=gitoper.getMethodsListLocHasNochange()
#4,解析旧的覆盖率数据
#获取老版本对应的文件夹路径
oldfilefolder=os.path.join(Utils.ANDROID_COMMITS_MERGE_WORKSPACE, proname,username, srccommit)
self.anylysisECFileContent(oldfilefolder,srccommit,keepbuildid)
#3,校准需要保留覆盖数据
needmodifyinfo=self.correctMethodsCovInfo(locchangmethodlist,locnochangemethdlist)
return needmodifyinfo
if __name__ == '__main__':
corrmethod=CorrectMethodsLocOfCovLines()
(2)MergeCommitsECFile去掉diff函数及调用链路上的函数,合并覆盖率数据
# coding: utf-8
import os
import sys
#添加本项目搜索路径
env_dist=os.environ
curenv=env_dist.get("AGENT_ENV")
if curenv!=None and curenv.find("prod")>-1:
sys.path.append(os.path.abspath('/accuratemobileagent'))
else:
sys.path.append(os.path.abspath('.'))
import simplejson, json
import requests, shutil
from flask import current_app
from AndroidCovAgent.CommitsMergeOperation.CorrectMethodsLocOfCovLines import CorrectMethodsLocOfCovLines
from AndroidCovAgent.CommitsMergeOperation.GitCompareBranchOper import GitCompareBranchOper
from AndroidCovAgent.Utils.Utils import Utils
class MergeCommitsECFile(object):
"""
合并两个不同分支的覆盖率数据
"""
def __init__(self):
self.removedline = {}
self.modifyline = {}
def removeDiffMethodCovInfo(self, propath, branchname, srccommit, descommit, keepbuildid, username, proname):
"""
根据diff函数,查询CCG,从老的覆盖率数据中去掉相关数据
:param propath: 项目路径,以便解析调用链路上的函数信息
:param branchname: 分支名
:param srccommit: 开始版本
:param descommit: 结束版本
:param oldecfilepath: 老版本merged覆盖率文件路径
:return:
"""
mergedoperpath = os.path.join(Utils.ANDROID_COMMITS_MERGE_WORKSPACE, proname, username)
# 1,获取需要删除的diff函数及调用链路上函数行
gitcomoper = GitCompareBranchOper()
self.removedline = gitcomoper.getAllNeedRemovedMethods(srccommit, descommit, proname, branchname, propath,username)
# 2,删除老的覆盖率数据文件中的数据
srccommitpath = mergedoperpath + "/" + srccommit + "_merged.ec"
# 将结果写入json文件中
removejson = mergedoperpath + "/" + srccommit + "_removedlines.json"
refile = open(removejson, "w")
refile.write(simplejson.dumps(self.removedline))
refile.close()
print("文件:" + removejson + "写入成功!")
if os.path.getsize(removejson)>100:
# class路径
classpath = mergedoperpath + "/" + srccommit + "/build_classes_" + keepbuildid.strip()
curpath=os.getcwd()
srcpath=mergedoperpath + "/" + srccommit
if not os.path.exists(classpath):
#类文件不存在,下载对应的类文件,并解压
os.makedirs(srcpath)
os.chdir(srcpath)
classzipfile="build_classes_"+ keepbuildid.strip()+".zip"
classurl = "https://********/build_classes_" + keepbuildid.strip() + ".zip";
print("下载文件:"+classurl)
downres=requests.get(classurl)
with open(srcpath+"/"+classzipfile,'wb') as f:
f.write(downres.content)
f.close()
#解压类文件压缩包
shutil.unpack_archive("./"+classzipfile,classpath)
os.chdir(curpath)
# 删除ec文件中diff函数及调用链路上函数影响的行
scriptpath=Utils.SCRIPT_FILE_PATH+"jacoco-parser2.0.jar"
removecmd = "java -jar " + scriptpath + " -e " + srccommitpath + " -j " + removejson + " -c " + classpath + " -p reduce"
print("执行去除覆盖率信息命令:" + removecmd)
os.system(removecmd)
print("去掉Diff函数及调用链路上的函数对应的覆盖率信息!")
else:
print("没有需要去掉覆盖率的函数列表!")
def getEffectMethodCovInfo(self, propath, srccommit, descommit, keepbuildid, username, proname):
"""
获取两个分支需要去掉和修改覆盖率信息
:param srccommit:
:param descommit:
:return:
"""
mergedoperpath = os.path.join(Utils.ANDROID_COMMITS_MERGE_WORKSPACE, proname, username)
# 1,获取需要修正函数信息
correctoper = CorrectMethodsLocOfCovLines()
self.modifyline = correctoper.getNeedModifyLineInfo(proname, srccommit, descommit, keepbuildid,username)
# 将结果写入json文件中
needmodifyjson = mergedoperpath + "/" + descommit + "_modifiedlines.json"
refile = open(needmodifyjson, "w")
refile.write(simplejson.dumps(self.modifyline))
refile.close()
print("文件:" + needmodifyjson + "写入完成!")
def modifyFinalCoverageInfo(self, propath, srccommit, descommit, desckeepid, username, proname):
"""
通过解析因diff影响到的函数内容没有变化,位置变化引在忙的覆盖率数据丢失的情况;将相应的数据写回到最新的覆盖率文件中
:param propath:项目路径
:param srccommit:源版本
:return:
"""
mergedoperpath = os.path.join(Utils.ANDROID_COMMITS_MERGE_WORKSPACE, proname, username)
srccommitpath = mergedoperpath + "/" + srccommit + "_merged.ec"
# 3,合并两个merged的版本
desccommitpath = mergedoperpath + "/" + descommit + "_merged.ec"
twocommitsmerge = mergedoperpath + "/commits_merged_coverage.ec"
jacococlipath=Utils.SCRIPT_FILE_PATH+"jacococli.jar"
#jacococlipath = "/Users/sxf/Documents/精准测试/AccurateCode/AndroidCovAgentFlask/ScriptFiles/jacococli.jar"
mergecmd = "java -jar " + jacococlipath + " merge " + srccommitpath + " " + desccommitpath + " --destfile " + twocommitsmerge
os.system(mergecmd)
# 4,再去修改合并后的ec文件
needmodifyjson = mergedoperpath + "/" + descommit + "_modifiedlines.json"
if os.path.getsize(needmodifyjson)>100:
# 1,检测是否需要下载class文件
descclasses = propath + "/build_classes_" + desckeepid.strip()
if not os.path.exists(descclasses):
os.chdir(propath)
classzipfile = "build_classes_" + desckeepid.strip() + ".zip"
classurl = "https://*******/build_classes_" + desckeepid.strip() + ".zip";
downres = requests.get(classurl)
with open(propath + "/" + classzipfile, 'wb') as f:
f.write(downres.content)
f.close()
# 解压类文件压缩包
shutil.unpack_archive("./" + classzipfile, descclasses)
if os.path.exists(needmodifyjson) and os.path.exists(twocommitsmerge):
scriptpath=Utils.SCRIPT_FILE_PATH+"jacoco-parser2.0.jar"
removecmd = "java -jar " + scriptpath + " -e " + twocommitsmerge + " -j " + needmodifyjson + " -c " + descclasses + " -p add"
os.system(removecmd)
else:
print("文件:" + needmodifyjson + "或者" + twocommitsmerge + "不存在,请确认相关文件!")
else:
print("没有需要修改覆盖率的函数列表!")
# 将全并后的文件更名为desc分支对应的ec,以便支持多版本合并
if os.path.exists(desccommitpath):
os.remove(desccommitpath)
else:
print(desccommitpath)
rename = "mv " + twocommitsmerge + " " + desccommitpath
os.system(rename)
# 执行一些数据清除操作
# 1,删除srccommit文件夹
srcfolder = mergedoperpath + "/" + srccommit
if os.path.exists(srcfolder):
shutil.rmtree(srcfolder)
else:
print("srcfolder=" + srcfolder)
# 2,删除desccommit文件夹
if os.path.exists(mergedoperpath + "/" + descommit):
shutil.rmtree(mergedoperpath + "/" + descommit)
# 3,删除json文件
if os.path.exists(mergedoperpath + "/" + srccommit + "_removedlines.json"):
os.remove(mergedoperpath + "/" + srccommit + "_removedlines.json")
if os.path.exists(mergedoperpath + "/" + descommit + "_modifiedlines.json"):
os.remove(mergedoperpath + "/" + descommit + "_modifiedlines.json")
def mergeAndMofidyTwoCommmitsCovData(self, propath, branchname, srcbuildid, srccomit, descbuildid, descomit,username, proname):
"""
合并两个指定版本的覆盖率数据文件
:param propath: 项目名称
:param branchname: 分支名
:param srcbuildid: 源版本keepbuildid
:param srccomit: 源版本
:param descbuildid: 目标版本Keepbuidid
:param descomit: 目标版本
:return:
"""
self.removeDiffMethodCovInfo(propath, branchname, srccomit, descomit, srcbuildid, username, proname)
print("删除Diff的函数及调用链路上的函数覆盖率数据!")
self.getEffectMethodCovInfo(propath, srccomit, descomit, srcbuildid, username, proname)
print("获取需要补充的覆盖率数据函数列表!")
self.modifyFinalCoverageInfo(propath, srccomit, descomit, descbuildid, username, proname)
print("生成最后地覆盖率数据文件!")
def runMergeCommitsFormJson(self, propath, branchname, mergeinfo, username, proname):
"""
通过读取合并版本信息的数据文件,循环进行覆盖率数据的合并
:param propath: 项目源码路径
:param branchname: 分支名称
:param mergeinfo: 合并版本信息文件,以KeepBuidID升序组成的json文件
:return:
"""
mergedoperpath = os.path.join(Utils.ANDROID_COMMITS_MERGE_WORKSPACE, proname, username)
# 1,读取需要合并的覆盖率信息文件
with open(mergeinfo, "r") as readjson:
json_data = json.load(readjson)
flag = 0
if len(json_data.keys())>1:
#多个版本的情况
for key in json_data.keys():
if flag == 0:
srcbuildid = key
srccommit = json_data[key]
flag = flag + 1
else:
descbuildid = key
descommit = json_data[key]
# 2,执行合并覆盖率操作
self.mergeAndMofidyTwoCommmitsCovData(propath, branchname, srcbuildid, srccommit, descbuildid,
descommit, username, proname)
# 替换src数据
srccommit = descommit
srcbuildid = descbuildid
else:
#只有一个版本的情况
print("只有一个版本的情况下,不需要走合并覆盖率流程,直接生成报告!")
print("多版本覆盖率文件合并完成!")
if __name__ == '__main__':
mergeoper = MergeCommitsECFile()
propath=sys.argv[1]
branchname=sys.argv[2]
mergeinfo=sys.argv[3]
username=sys.argv[4]
proname=sys.argv[5]
mergeoper.runMergeCommitsFormJson(propath,branchname,mergeinfo,username,proname)
4,用例关联模块
在做用例关联的时候,无论是手工还是自动化,核心问题就是需要解析出用例执行过程中覆盖了哪些函数,然后将用例信息与函数信息做关联,插入到数据库中。对于Android来说,就是要解析覆盖率EC文件,但是从网上查了很久都没有找到解析方案,后来从公司其他部门找到了一个工具jacoco-parser.jar,可以对覆盖率文件进行解析,于是就开发了解析覆盖率文件相关功能。
ClassOfProjectOperations类,解析覆盖率文件中覆盖的函数:
# coding=utf-8
#date 2022-03-22
import os
from flask import current_app
from AndroidCovAgent.CovRelateOperation.CreateReportForKeepClass import CreateReportForKeepClass
from AndroidCovAgent.Utils.Utils import Utils
class ClassOfProjectOperations():
"""
处理项目中所有的Class文件
"""
def anyliseCovInfo(self,jsoncont,username):
"""
转化覆盖率文件信息,返回符合CCG查询的格式
:param fileinfo:
:return:
"""
filejson= {}
i=0
for key in jsoncont.keys():
ckcont=jsoncont[key]
if len(ckcont["covered"])>0:
filename=ckcont["filename"]
#处理文件路径,去掉androidx相关的文件
if filename.find("androidx/fragment/app")==-1:
filename=filename[filename.index(username)+len(username)+1:len(filename)]
covlinelist=ckcont["covered"]
lininfo=""
for line in covlinelist:
lininfo=lininfo+str(line)+",1;"
lininfo=lininfo[0:len(lininfo)-1]
filejson[filename]=lininfo
current_app.logger.info("影响的文件个数:"+str(len(filejson.keys())))
return filejson
def getCovedFileListByEcFile(self,propath,ecfilename,keepbuildid):
"""
查找项目中所有的kotlin class文件
@param propath:项目路径
@param ecfilename:ec 覆盖率数据文件名称
@:param keepbuildid: Keep构建号
:return:
"""
createrfk=CreateReportForKeepClass()
#获取class文件路径
descclasses=createrfk.getBuildClassPath(propath)
#数据文件路径
utiloper=Utils()
ecfilepath=utiloper.getAppPath(propath)+"/build/outputs/code-coverage/connected/"+ecfilename
ecjson=ecfilename[ecfilename.index("-")+1:ecfilename.rindex(".")]
#解析对应的ec文件
ecinfojson=propath+"/ecfileparse_"+ecjson+".json"
curpath = os.getcwd();
scriptpath=Utils.SCRIPT_FILE_PATH
jacocoparse="java -jar "+scriptpath+"jacoco-parser2.0.jar -e "+ecfilepath+" -o "+ecinfojson+" --source "+propath+" --class "+descclasses+" &"
current_app.logger.info(jacocoparse)
os.system(jacocoparse)
current_app.logger.info("***********解析覆盖率数据文件完成**************")
if __name__=='__main__':
copro=ClassOfProjectOperations()
copro.getCovedFileListByEcFile("***","coverage.ec","9527")