前言
之前的文章呢,我们做了数据的存储,以及如何在测试报告中展示,那么这次我们分享如何将测试用例执行结果的历史记录也展示出来。
正文
我们在执行用例时候,每次执行完毕后,如果没有及时将测试结果备份,那么下次再来执行的时候,就不知道上一次的结果。我们也看不到历史执行中的结果的趋势,有些数据不好分析。那么我们应该怎么做,让我们的测试报告可以支持呢。答案也很简单。
我们在测试用例执行的完毕的时候,我们记录测试结果,然后下次执行的时候,有历史记录我们就读取历史记录即可。
我们用BSTestRunner.py为例去讲解。
第一步:记录测试用例执行数据
为了更加灵活呢,我们在类初始化的时候呢,默认有一个是否展示,并且配置文件的路径。
class BSTestRunner(Template_mixin):
"""
"""
def __init__(self, stream=sys.stdout, verbosity=1,
title=None, description=None, trynum=trynumcommonnum,
is_show=False,filepath=""):
self.stream = stream
self.verbosity = verbosity
self.trynum = trynum
self.is_show=is_show#是否展示
self.filepath=filepath#测试报告历史记录存储路径
if title is None:
self.title = self.DEFAULT_TITLE
else:
self.title = title
if description is None:
self.description = self.DEFAULT_DESCRIPTION
else:
self.description = description
self.startTime = datetime.datetime.now()
那么我们在run方法中呢,增加保存结果的代码。
def run(self, test):
"Run the given test case or test suite."
result = _TestResult(self.verbosity, trynum=self.trynum)
try:
test(result)
except TypeError:
pass
self.stopTime = datetime.datetime.now()
#是否展示历史记录
if self.is_show:
name=os.path.join(self.filepath,self.stopTime.strftime('%Y_%m_%d_%H_%M_%S')+'.txt')
with open(name,'w+') as f:
f.write(result.success_count.__str__()+"_"+result.error_count.__str__()+"_"+result.failure_count.__str__())
f.close()
self.generateReport(test, result)
print('\n测试耗时: %s' % (self.stopTime - self.startTime))
return result
这里面我做的事,要展示历史记录才存。可以改造成自己想要的。
第二步:在测试报告中展示数据
我们收集到的数据,接下来在测试报告中就是展示了。我们在generateReport做处理。因为有展示或者不展示,不展示我们走的是老的方法。
def generateReport(self, test, result):
report_attrs = self.getReportAttributes(result)
generator = 'BSTestRunner %s' % __version__
stylesheet = self._generate_stylesheet()
heading = self._generate_heading(report_attrs)
report = self._generate_report(result)
ending = self._generate_ending()
#如果展示那么我们走新的方法
if self.is_show:
scrpit=self.___generate_scrpitone()
else:
scrpit=self._generate_scrpit()
output = self.HTML_TMPL % dict(
title=saxutils.escape(self.title),
generator=generator,
stylesheet=stylesheet,
scripts=scrpit,
heading=heading,
report=report,
ending=ending
)
self.stream.write(output)
我们看新的产生静态html的方法
def ___generate_scrpitone(self):
namerun,faillist,success,error=self._readresult()
name, cpu, mem = self._getdata()
return self.SCRPICTDATA% dict(name=name,cpu=cpu,men=mem,
reslutname=namerun,
success=success,
fail=faillist,
error=error)
这里也很简单,有一个读取结果的方法。结果的方法。默认会返回执行结果的数据。
def _readresult(self):
namerun=[]
faillist=[]
success=[]
error=[]
for root,dirs,files in os.walk(self.filepath):
for file in files:
if file.endswith(".txt"):
namerun.append(file.split(".")[0].split("/")[-1])
with open(os.path.join(root,file),'r') as f:
reslut=f.readline().split('\n')[0].split("_")
success.append(reslut[0])
error.append(reslut[1])
faillist.append(reslut[2])
return namerun,faillist,success,error
那么我们看下self.SCRPICTDATA的代码,这里是关键的数据展示的地方。
SCRPICTDATA=r"""
<script language='javascript' type='text/javascript'>
var dom = document.getElementById('containerchart');
var myChart = echarts.init(dom);
var domone = document.getElementById('container2');
var myChartone = echarts.init(domone);
var optionsone;
optionsone = {
title: {
text: '历史记录'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['成功', '失败','错误']
},
grid: {
left: '3%%',
right: '4%%',
bottom: '3%%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: %(reslutname)s
},
yAxis: {
type: 'value'
},
series: [
{
name: '成功',
type: 'line',
stack: '总量',
data: %(success)s
},
{
name: '失败',
type: 'line',
stack: '总量',
data: %(fail)s
},
{
name: '错误',
type: 'line',
stack: '总量',
data: %(error)s
}
]
};
if (optionsone && typeof optionsone === 'object') {
myChartone.setOption(optionsone);
}
var option;
option = {
title: {
text: '性能数据'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['cpu', '内存']
},
grid: {
left: '3%%',
right: '4%%',
bottom: '3%%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data:%(name)s
},
yAxis: {
type: 'value'
},
series: [
{
name: 'cpu',
type: 'line',
stack: '总量',
data:%(cpu)s
},
{
name: '内存',
type: 'line',
stack: '总量',
data: %(men)s
}
]
};
if (option && typeof option === 'object') {
myChart.setOption(option);
}
output_list = Array();
/* level - 0:Summary; 1:Failed; 2:All */
function showCase(level) {
trs = document.getElementsByTagName('tr');
for (var i = 0; i < trs.length; i++) {
tr = trs[i];
id = tr.id;
if (id.substr(0,2) == 'ft') {
if (level < 1) {
tr.className = 'hiddenRow';
}
else {
tr.className = '';
}
}
if (id.substr(0,2) == 'pt') {
if (level > 1) {
tr.className = '';
}
else {
tr.className = 'hiddenRow';
}
}
}
}
function showClassDetail(cid, count) {
var id_list = Array(count);
var toHide = 1;
for (var i = 0; i < count; i++) {
tid0 = 't' + cid.substr(1) + '.' + (i+1);
tid = 'f' + tid0;
tr = document.getElementById(tid);
if (!tr) {
tid = 'p' + tid0;
tr = document.getElementById(tid);
}
id_list[i] = tid;
if (tr.className) {
toHide = 0;
}
}
for (var i = 0; i < count; i++) {
tid = id_list[i];
if (toHide) {
document.getElementById('div_'+tid).style.display = 'none'
document.getElementById(tid).className = 'hiddenRow';
}
else {
document.getElementById(tid).className = '';
}
}
}
function showTestDetail(div_id){
var details_div = document.getElementById(div_id)
var displayState = details_div.style.display
if (displayState != 'block' ) {
displayState = 'block'
details_div.style.display = 'block'
}
else {
details_div.style.display = 'none'
}
}
function html_escape(s) {
s = s.replace(/&/g,'&');
s = s.replace(/</g,'<');
s = s.replace(/>/g,'>');
return s;
}
</script>
</body>
</html>
"""
这是数据展示的方法,还有要对头部进行修改,在generateReport方法中有对应的处理方式。我们这里由于篇幅限制呢,我们先不做展示,我会把代码统一上传的。
接下来,就是在实际代码中,执行。
besautiful = BSTestRunner(title="报告",
description="测试报告",
stream=openone,
trynum=runprojecttrynum,
is_show=ISSHOWHISTORY,
filepath=BASH_DIR)
修改后支持是否展示,这些配置呢,都存在了config.py中。
BASH_DIR=os.path.join(os.getcwd(),"report")
ISSHOWHISTORY=True
我们可以执行下测试用例。最后结果如下。
最新代码已经提交
https://gitee.com/liwanlei/appiumdemo
后记
发现问题,解决问题。遇到问题,慢慢解决问题即可。
欢迎关注雷子说测试开发,后续将会持续为大家分享更多的技术知识