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

第6.2节 Android Agent开发<一>

       Android Agent为完成Android端覆盖率报告的生成,关联用例等功能的服务,本来可以做成微服务的形式,早期由于和iOS端放在了一起,而iOS相关功能无法布置到容器上,就直接使用django开发了一个服务,通过Http接口完成相应的操作。后来功能越来越强大,就将Android和iOS拆分出来,Android agent为Flask框架开发的服务,django无法部署到公司的容器上。

6.2.1 整体架构

     目前Android agent的整体架构如下,随着精准测试平台功能的越来越多,Agent的功能也会不断地增加的。

功能介绍:

1,文件模块

      为Flask的一个接口模块,主要用来处理Agent对于文件的操作。比如下载项目代码,上传覆盖率文件,下载覆盖率报告,下载构建后的class文件,以及拷贝覆盖率文件等操作。用于精准测试平台与Agent交互的所有文件操作,其中的小技巧:如果文件在同一文件存储服务上,就采用拷贝的方法来代码上传操作,以提高执行速度。

(1)clone文件代码:

class CloneProFromGit(object):"""从Git上下载代码"""def cloneprofiles(self,gitadr,gitbran,propath):"""下载或更新指定分支的代码"""utiloper=Utils()curpath = os.getcwd()print("开始Clone项目:"+gitadr)if not os.path.exists(propath+"XXXXXX"):os.makedirs(propath)# clone代码,需要优化一下if gitbran.find("master")!=-1:os.system("git clone "+gitadr+" "+propath)print("Clone代码库,master分支......")else:# 切换分支,可能超时os.system("git clone "+gitadr+" "+propath)os.chdir(propath)os.system("git checkout -b "+gitbran+" remotes/origin/"+gitbran)os.system("git pull")print("Clone代码库,并更新分支......")else:#更新代码库os.chdir(propath)os.system("git checkout -b "+gitbran+" remotes/origin/"+gitbran)os.system("git pull")print("Clone代码库,代码库已经存在,切换分支:"+gitbran)return propath

2,覆盖率模块

      通过上传构建后的class文件,使用jacococli工具来生成指定的需求的全量覆盖率报告,这样可以防止通过项目构建生成Class文件来生成报告。同时对于增量覆盖率报告有两种处理情况:

(1)对比分支的增量报告,利用开源工具diff-cover来生成增量报告,而后再生成一个汇总页面;核心代码:

# coding=utf-8
import logging
from pathlib import Path
import asyncio, os
import time, sys, shutillogger=logging.getLogger("AndroidDiffCoverReportOper")class AndroidDiffCoverReportOper(object):"""多线程执行生成diff-cover覆盖率报告,以提高执行速度@author SXF@date 2022-05-27"""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="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 headcontentdef createTotalReport(self, propath, branch, srcfold):"""生成最终的汇总报告"""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 = 0mislines = 0index = 0for sfold in srcfold:reportcontent = reportcontent + "<tr><td><a href=\"diffreport" + str(index) + ".html\" class=\"el_package\">" + sfold[sfold.find("packages"):sfold.find("src") - 1] + "</a>  </td>"diffreport = propath + "diffreport/diffreport" + str(index) + ".html"dfile = open(diffreport, "r")lines = dfile.readlines()if len(lines) < 94:# diff-cover生成的报告中无数据reportcontent = reportcontent + "<td colspan='3' class=\"ctr1\">No lines with coverage information in this diff.</td>"else:cktotal = ""ckmisline = ""ckcovrate = 0flag = 0for line in lines:if line.find("<b>Total</b>") > -1:cktotal = line[line.find(":") + 1:line.find("line")]totallines = totallines + int(cktotal.strip())flag = flag + 1if line.find("<b>Missing</b>") > -1:ckmisline = line[line.find(":") + 1:line.find("line")]mislines = mislines + int(ckmisline.strip())flag = flag + 1if line.find("<b>Coverage</b>") > -1:ckcovrate = int(line[line.find(":") + 1:line.find("%")].strip())flag = flag + 1# 统一添加相关数据if flag == 3:# 1,覆盖率miscov = 100 - ckcovratereportcontent = reportcontent + "<td class=\"bar\">" + "<img src=\"resources/redbar.gif\" width=\"" + str(miscov) + "\" height=\"10\">"reportcontent = reportcontent + "<img src=\"resources/greenbar.gif\" width=\"" + str(ckcovrate) + "\" height=\"10\">  " + str(ckcovrate) + "%</td>"# 2,总行数reportcontent = reportcontent + "<td class=\"ctr1\">" + cktotal + "</td>"# 3,没有覆盖的行数reportcontent = reportcontent + "<td class=\"ctr1\">" + ckmisline + "</td>"reportcontent = reportcontent + "</tr>\r\n"index = index + 1reportcontent = reportcontent + "</table>"# 添加头部信息及汇总信息covlines = totallines - mislinesif totallines == 0:covrate=0else:covrate = float(covlines) / float(totallines) * 100headcontent = 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>"# 汇总报告写入文件difffolder=propath + "diffreport"if not os.path.exists(difffolder):os.makedirs(difffolder)findreport = difffolder+"/index.html"rf = open(findreport, "w")rf.write(reportcontent)rf.closelogger.info("生成汇总报告:" + findreport)def getDiffFile(self, propath,branch):"""获取Diff文件"""curpath = os.getcwd()logger.info("getDiffFile中的当前路径:"+curpath)os.chdir(propath)gitcmd = "git diff " + branch + "|grep 'diff --git'"runcmd = os.popen(gitcmd)fileinfo = runcmd.readlines()pclist = []for line in fileinfo:if (line.find(".kt") > -1 or line.find(".java") > -1):if (line.find(".kt") > -1):getfile = line[line.find("a/") + 2:line.find(".kt") + 3]else:getfile = line[line.find("a/") + 2:line.find(".java") + 5]packagepath = getfile[9:getfile.find("/src")]if not (packagepath in pclist):pclist.append(packagepath)# print(pclist)os.chdir(curpath)return pclistdef getAllSourcePath(self, propath, branch):"""获取项目中的所有源码路径:param propath::return:"""sroucepath = []diffpclist = self.getDiffFile(propath,branch)folder = Path(propath)result = list(folder.rglob("src/main/java"))for ckfile in result:ckpath = str(ckfile.resolve())for packinfo in diffpclist:if ckpath.find(packinfo) > -1:sroucepath.append(ckpath)break# print (sroucepath)return sroucepathasync def creatDiffReport(self, propath, combran, srcpath, index):"""生成增量覆盖率报告"""logger.info("开始生成" + srcpath + "的增量报告.........")jacocoxml = propath + "jacocoTestReport.xml"diffrepfold = propath + "diffreport"if not os.path.exists(diffrepfold):os.makedirs(diffrepfold)os.chdir(propath)diffcmd = "diff-cover " + jacocoxml + " --html-report " + diffrepfold + "/diffreport" + str(index) + ".html --compare-branch " + combran + " --src-roots " + srcpathproc = await asyncio.create_subprocess_shell(diffcmd)stdout, stderr = await proc.communicate()return srcpath + "的增量报告生成完成!"async def runDiffCreateTask(self, propath, combran, srclist, start):"""批量生成报告任务"""task_list = []index = startloop=asyncio.get_event_loop()for srcpath in srclist:task = loop.create_task(self.creatDiffReport(propath, combran, srcpath, index))task_list.append(task)index = index + 1done, pending = await asyncio.wait(task_list, timeout=None)for done_task in done:print(done_task.result())def createDiffCoverReportOfAndroid(self, propath, branch):"""生成Android的增量报告"""logger.info("*******************开始生成增量报告*********************")print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))srcfold = self.getAllSourcePath(propath, branch)curpath = os.getcwd()index = 0for i in range(len(srcfold)):# 取子列表,一次并发10个if index >= len(srcfold):breaksublist = srcfold[index:index + 10]loop = asyncio.get_event_loop()loop.run_until_complete(self.runDiffCreateTask(propath, branch, sublist, index))index = index + 10logger.info("所有增量报告生成完成.....")# 生成汇总报告self.createTotalReport(propath, branch, srcfold)logger.info("*******************结束生成增量报告*********************")#将diffreport打包os.chdir(propath)shutil.make_archive("diffreport","zip",'./diffreport')logger.info("将diffreport打包!")os.chdir(curpath)print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))if __name__ == '__main__':propath = sys.argv[1]combranch = sys.argv[2]crfk = AndroidDiffCoverReportOper()crfk.createDiffCoverReportOfAndroid(propath, combranch)

(2)对比版本的增量报告,由于diff-cover不支持版本对比,就单独开发了版本对比的功能。通过git diff来获取变更的文件列表,再去过滤全量覆盖率报告,最终生成增量覆盖率报告。核心代码:

# coding=utf-8
import os
import shutil
from datetime import time
from pathlib import Path
from flask import current_appfrom AndroidCovAgent.CovRelateOperation.JacocoReportSelectOper import JacocoReportSelectOperclass AndroidComPareCommitsReport(object):"""生成Android版本对比覆盖率报告"""def selectReportByDiffFiles(self,filelist,jacocorpath,diffreport):"""根据diff文件列表,生成相应的增量覆盖率报告文件:param filelist::param jacocorpath::return:"""for ckfile in filelist:#解析文件名ckfname=ckfile[ckfile.rindex("/")+1:ckfile.rindex(".")]changepath=ckfile[ckfile.index("com"):ckfile.rindex("/")].replace("/",".")folder=Path(jacocorpath)result=list(folder.rglob(changepath+"/"+ckfname+"*"))for ckfile in result:ckpath=str(ckfile.resolve())newpath=diffreport+ckpath[ckpath.index("jacoco")+7:ckpath.rindex("/")]newfilename=ckpath[ckpath.rindex("/")+1:]if not os.path.exists(newpath):os.makedirs(newpath)#拷贝index.html文件shutil.copy(ckpath[0:ckpath.rindex("/")+1]+"index.html",newpath+"/index.html")shutil.copy(ckpath,newpath+"/"+newfilename)# print(ckpath)def getDiffFile(self, propath,comparecommit):"""获取Diff文件"""curpath = os.getcwd()os.chdir(propath)gitcmd = "git diff " + comparecommit + "|grep 'diff --git'"runcmd = os.popen(gitcmd)fileinfo = runcmd.readlines()# print(fileinfo)difffiles = []for line in fileinfo:if (line.find(".kt") > -1 or line.find(".java") > -1):if (line.find(".kt") > -1):getfile = line[line.find("a/") + 2:line.find(".kt") + 3]else:getfile = line[line.find("a/") + 2:line.find(".java") + 5]if not (getfile in difffiles):difffiles.append(getfile)# print(pclist)os.chdir(curpath)return difffilesdef createDiffReportByCompareCommits(self,propath,comparecomit):"""对比分支,生成增量覆盖率报告:param propath::param comparecomit::return:"""#获取diff文件列表difffilelist=self.getDiffFile(propath,comparecomit)#print(difffilelist)jacocopath=propath+"jacoco/"diffrppath=propath+"diffreport/"if not os.path.exists(diffrppath):os.makedirs(diffrppath)#拷贝资源文件到diffreport文件夹中shutil.copytree(jacocopath+"/jacoco-resources",diffrppath+"/jacoco-resources")print("创建增量覆盖率文件夹,拷贝资源文件!")#拷贝增量覆盖率文件相关报告self.selectReportByDiffFiles(difffilelist,jacocopath,diffrppath)#修改各个package下的index文件,去掉不是diff中的文件信息jrsoper=JacocoReportSelectOper()for i,j,k in os.walk(diffrppath):for folder in j:# print("package="+folder)if folder.find("jacoco-resources")==-1:packagepath=diffrppath+folder+"/"jrsoper.correctIndexFile(packagepath)#生成最终的覆盖率报告jrsoper.createDiffReport(diffrppath,comparecomit)print("对比版本:"+comparecomit+"的增量报告生成完成!")#将全量覆盖率报告打包curpath=os.getcwd()os.chdir(propath)shutil.make_archive("jacoco","zip",'./jacoco')#将增量报告打包shutil.make_archive("diffreport","zip",'./diffreport')os.chdir(curpath)if __name__=='__main__':acpcr=AndroidComPareCommitsReport()propath="/Users/*******/"
acpcr.createDiffReportByCompareCommits(propath,"321ce030db507b72f04da3fa09b9e90e3be7313e")


文章转载自:

http://Y0UjO84D.jkzjs.cn
http://PJGeEeqa.jkzjs.cn
http://gsBy3jP2.jkzjs.cn
http://mRMLGo24.jkzjs.cn
http://v2wSjhbp.jkzjs.cn
http://LnrOZva2.jkzjs.cn
http://wJQALhOF.jkzjs.cn
http://VIB41Sx9.jkzjs.cn
http://3k89Xhho.jkzjs.cn
http://VJojBaSe.jkzjs.cn
http://jZ8TIvHy.jkzjs.cn
http://6sGswYzc.jkzjs.cn
http://YASEjokk.jkzjs.cn
http://woVXpemL.jkzjs.cn
http://y303lZTR.jkzjs.cn
http://3MUU5L73.jkzjs.cn
http://AozBNrzW.jkzjs.cn
http://9yv5qfZn.jkzjs.cn
http://Dq4vVfAL.jkzjs.cn
http://WGDxKhTf.jkzjs.cn
http://YCFHwACe.jkzjs.cn
http://00HyM2Bg.jkzjs.cn
http://f5c3t73W.jkzjs.cn
http://f8ZVNn0g.jkzjs.cn
http://jiNkFxY3.jkzjs.cn
http://aznaVow2.jkzjs.cn
http://f4BaWZms.jkzjs.cn
http://AA6oPns5.jkzjs.cn
http://3kH8aHYB.jkzjs.cn
http://TTJLkN41.jkzjs.cn
http://www.dtcms.com/a/379643.html

相关文章:

  • 【 C/C++ 算法】入门动态规划-----一维动态规划基础(以练代学式)
  • YOLOv8 从yaml配置文件生成PyTorch模型
  • 重复文件清理的标准化操作流程
  • Amazon DocumentDB Serverless 技术深度解析:架构特性、弹性扩缩容机制与实操指南
  • 项目管理方法适合什么类型的企业
  • HTTPS(Hypertext Transfer Protocol Secure,超文本传输安全协议)
  • 【LLM越狱】AI大模型DRA攻击解读与复现
  • k8s下的发布策略详解
  • 第 9 篇:深入浅出学 Java 语言(JDK8 版)—— 吃透泛型机制,筑牢 Java 类型安全防线
  • 机器人防爆与隔爆的本质,两者的区别对比
  • 从蛮力清扫到 “会看路”:室外清洁机器人的文明进阶
  • 大数据毕业设计选题推荐-基于大数据的家庭能源消耗数据分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • 【Settings】恢复出厂设置密码校验
  • 机器人控制器开发(通讯——ros话题转为websocket)
  • Go 1.25.1 自定义包调用
  • go语言,彩色验证码生成,加减法验证,
  • 深入解析 AST2600 H2B 接口:架构、原理与完整开发指南
  • 手机ip隔离方法
  • RAG检索增强生成:让AI拥有“外部记忆“的黑科技
  • Jmter接口网站压力测试工具使用记录
  • Agentic BI技术解构:多智能体协作框架如何实现“分析-决策-执行”闭环?
  • 如何用AI做海报、IP设计,稿定AI一站式创作
  • Threejs案例实践笔记
  • React18学习笔记(一) 如何创建一个React项目,JSX的基础应用,案例---视频网站评论区
  • 【Threejs】学习笔记
  • 图像显示技术与色彩转换:从基础原理到实际应用
  • C 语言实现 I.MX6ULL 点灯(续上一篇)、SDK、deep及bsp工程管理
  • 飞桨paddlepaddle旧版本2.4.2安装
  • 2.5 DNS(Domain Name System)
  • CK: 03靶场渗透