缘由:
1)jmeter生成的html报告容量偏大
2)jmeter生成的报告,没有历史统计
3)此外,该目录整体可以整合的自动化平台内
故:做了调整~
一.目录结构
1)scriptPy文件夹:主要是python脚本的存放;
----historyTest.py:历史报告生成html文件展示;
----htmlTem.py:html模板文件;
----jtlTohtml.py:jtl转html文件。
2)scriptApi文件夹:主要是jmx脚本的存放;
----Test.jmx:测试脚本;
----img文件夹:存放需要上传的图片目录;
----excel文件夹:存放需要上传的文件目录。
3)reportHtml文件夹:主要是对jtl文件解析后生成的html报告存放;
4)demoReport文件夹:主要是对jmeter执行后生成的jtl文件存放,按时间戳生成子目录,子目录内为jtl文件;
5)apace-jmeter-5.1.1文件夹:jmeter软件包;
6)total.log:是jmeter执行后的数据统计块存放;
7)startApiTest.sh:为启动脚本。
二.shell脚本
说明:shell脚本主要作为启动脚本的存在,提供给Jenkins调用。
#!/bin/bash current=`date "+%Y-%m-%d %H:%M:%S"` timeStamp=`date -d "$current" +%s` name=`date "+%Y-%m-%d_%H-%M-%S"` workpath=`pwd` ${workpath}/apache-jmeter-5.1.1/bin/jmeter -Jurl=IP -n -t ${workpath}/scriptApi/Test.jmx -l ${workpath}/demoReport/${timeStamp}/log.jtl >${workpath}/total.log rm -rf ${workpath}/reportHtml/history.html python ${workpath}/scriptPy/jtlTohtml.py "/opt/api/demoReport/${timeStamp}/log.jtl" "${name}" python ${workpath}/scriptPy/historyTest.py
三.htmlTem.py脚本
说明:htmlTem.py脚本中是封装了所有需要涉及到的html模板。
# -*- coding:UTF-8 -*- #!/usr/bin/env python class singlehtml(object): """html报告""" HTML_TMPL = """ <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>%(reprotName)s_测试报告</title> <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script> <script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/echarts.min.js"></script> <script src="fun.js"></script> <!--<h1 style="font-family: Microsoft YaHei">%(reprotName)s_测试报告</h1>--> <hr/> <style type="text/css" media="screen"> body{ font-family: Microsoft YaHei,Tahoma,arial,helvetica,sans-serif;padding: 20px;} </style> </head> <body> <h1 style="font-family: Microsoft YaHei">%(reprotName)s_测试报告</h1> <div style="border-bottom: 1px solid;">本次执行概况: <span style="color: blue;">%(total)s</span></div> <hr/> %(body)s """ THREADS_TMPL=""" <div> <p>%(thread)s</p> <table id='result_table' class="table table-condensed table-bordered table-hover"> <colgroup> <col align='left' /> <col align='right' /> <col align='right' /> <col align='right' /> </colgroup> <tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 14px;"> <th>接口</th> <th>结果</th> <th>失败信息</th> <th>URL</th> <th>响应时长(ms)</th> </tr> %(table_tr)s </table> </div> """ TABLE_TMPL = """ <tr class='failClass warning'> <td>%(apiName)s</td> <td>%(result)s</td> <td>%(failureMessage)s</td> <td>%(url)s</td> <td>%(elapsed)s</td> </tr>""" """html历史报告""" HISTORY_TMPL = """ <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>历史测试报告</title> <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script> <script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/echarts.min.js"></script> <script src="fun.js"></script> <h1 style="font-family: Microsoft YaHei">XX接口-测试报告</h1> <hr/> <style type="text/css" media="screen"> body{ font-family: Microsoft YaHei,Tahoma,arial,helvetica,sans-serif;padding: 20px;} .card{display: inline-block;padding: 5px;border: 1px solid; auto;height: 50px;} </style> </head> <body> <div class=""> <div class="row"> <div class="col-md-3" style="border-right: 1px solid #428bca;height:800px;"> <p>历史报告</p> <ul class="nav nav-pills nav-stacked"> <li class=""><a href="#">%(first)s</a></li> %(reports)s </ul> </div> <div class="col-md-9"> <div> <div class="card bg-info text-white" style="30%%;"> <div class="card-body">执行总次数:%(countReprot)s</div> </div> <!--<div class="card bg-info text-white" style="30%%;"> <div class="card-body">成功次数:</div> </div> <div class=" bg-info text-white" style=""> <div class="card-body">本次执行概况:</div> </div>--> </div> <div> <!--<h1>报告</h1>--> <hr/> <iframe src="%(firsthtml)s" style="100%%;height:600px;"></iframe> </div> </div> </div> <script> $("li").click(function(){ $("iframe").attr("src",$(this).text()); }); </script> """ LI_TEMP=""" <li><a href="#">%(report)s</a></li> """
四.jtlTohtml.py脚本
说明:jtlTohtml.py脚本是对jtl文件解析成html。
# -*- coding:UTF-8 -*- #!/usr/bin/env python import os,sys,json from htmlTem import singlehtml defaultencoding = 'utf-8' if sys.getdefaultencoding() != defaultencoding: reload(sys) sys.setdefaultencoding(defaultencoding) def tohtml(f,name): html=singlehtml() table_tr0="" threadstmpl_div="" alldata=[] threadnames={} totalDetail="" totlaFile = open("total.log") for line in totlaFile: if "=" in line: totalDetail=line file = open(f) #filename=f.split("/")[-1].split(".")[0] #alldata.append(filename) next(file) for line in file: #line=file.readline() data={} if not line: break; if """ in line: msg=line.split(""")[1] newline=line.replace(msg,"") apiline=newline.split(",") data["failureMessage"]=msg data["url"]=apiline[12] else: apiline=line.split(",") data["failureMessage"]="NA" data["apiName"]=apiline[2] data["result"]=apiline[7] data["elapsed"]=apiline[1] #data["reprotName"]=filename data["url"]=apiline[13] threadname=apiline[5] table_td = html.TABLE_TMPL % dict( apiName=data["apiName"], result=data["result"], elapsed=data["elapsed"], url= data["url"], failureMessage=data["failureMessage"], ) if threadname in threadnames.keys(): threadnames[threadname]+= table_td else: threadnames[threadname]=table_td #print(alldata) for key in threadnames.keys(): threadstmpl=html.THREADS_TMPL % dict( thread=key, table_tr=threadnames[key], ) threadstmpl_div+=threadstmpl output = html.HTML_TMPL % dict( reprotName = name, total=totalDetail, body = threadstmpl_div, ) path=os.getcwd()+"/reportHtml/" with open(path+name+".html",'wb') as f: f.write(output.encode('utf-8')) getf=sys.argv[1] name=sys.argv[2] tohtml(getf,name)
五.historyTest.py脚本
说明:historyTest.py脚本用于生成历史报告html
# -*- coding:UTF-8 -*- #!/usr/bin/env python import os,sys defaultencoding = 'utf-8' if sys.getdefaultencoding() != defaultencoding: reload(sys) sys.setdefaultencoding(defaultencoding) from htmlTem import singlehtml def file_name(file_dir): html=singlehtml() allreport=[] reports="" rootdir="" totalDetail="" #fistReport="" totlaFile = open("total.log") for line in totlaFile: if "=" in line: totalDetail=line for root, dirs, files in os.walk(file_dir): #rootdir=root #当前目录路径 #print(dirs) #当前路径下所有子目录 allreport=files #当前路径下所有非目录子文件 allreport.sort(reverse=True) for file in range(1,len(allreport),1): lis=html.LI_TEMP % dict( report=allreport[file], ) reports+=lis output=html.HISTORY_TMPL %dict( first=allreport[0], countReprot=len(allreport), #total=totalDetail, firsthtml=allreport[0], reports=reports, ) #path=os.path.abspath(os.path.join(os.getcwd(), "../reportHtml/")) path=os.getcwd()+"/reportHtml/" with open(path+"/history.html",'wb') as f: f.write(output.encode('utf-8')) #currpath=os.path.abspath(os.path.join(os.getcwd(), "..")) currpath=os.getcwd() file_name(currpath+"/reportHtml/")
六.效果(还未美化)