缘由:
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;width: 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="width:30%%;">
<div class="card-body">执行总次数:%(countReprot)s</div>
</div>
<!--<div class="card bg-info text-white" style="width: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="width: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/")
六.效果(还未美化)