快速实现自定义的测试报告

测试开发社区

共 7088字,需浏览 15分钟

 · 2020-09-11

一、背景

RF的结果报告可以方便我们查看每一条用例集、用例的执行结果统计,但是有的项目涉及到一些数据的比对,希望能够直观到看到数据,原生的测试报告就无法满足这个需求了。

  • 原生的报告

  • 项目需求报告格式

二、解决方案

2.1 流程图

  • 解析output.xml,将用例的相关信息和执行结果获取

  • 通过API和数据库获取需要展示的数据

  • 将上述两步的数据封装到一个数据列表中,方便后面进行模板渲染

  • 根据需求画HTML的报告模板

  • 对模板进行数据填充渲染,生成报告文件

  • 邮件发送报告

2.2 output.xml解析

测试用例相关的信息和运行结果,我们可以通过解析RF的output.xml文件来进行获取

2.2.1获取用例运行情况的统计

import xml.dom.minidom

import xml.etree.ElementTree


# 打开xml文档

dom = xml.dom.minidom.parse('E:\\robot\\fightdata_yuce\\results\\output.xml')

root2 = xml.etree.ElementTree.parse('E:\\robot\\fightdata_yuce\\results\\output.xml')


# 得到文档元素对象

root = dom.documentElement

total = root.getElementsByTagName('total');

total_len = len(total)

# total的stat节点个数

total2 = root2.getiterator("total")

total_stat_num = len(total2[total_len-1].getchildren())

statlist = root.getElementsByTagName('stat');


def get_total_statistics():

list = []

for i in range(0,total_stat_num):

d = dict()

d['fail'] = int(statlist[i].getAttribute("fail"))#失败用例数

d['pass'] = int(statlist[i].getAttribute("pass"))#成功用例数

d['total'] = d['fail']+d['pass']#用例总数

d['percent'] = ('{:.2%}'.format(d['pass'] / d['total']))#用例百分比

list.append(d)

return list

2.2.2 获取用例信息
  • 用例的组织结构

  • 获取用例信息和执行结果
    用例结构是多个suite,每个suite下有4条case

import xml.dom.minidom

import xml.etree.ElementTree


# 打开xml文档

dom = xml.dom.minidom.parse('E:\\robot\\xxx\\results\\output.xml')

root2 = xml.etree.ElementTree.parse('E:\\robot\\xxx\\results\\output.xml')

tree3=root2.getroot()

# 获取suite下的子节点

def getcase():

casedict = {}

testlist2 = []

for elem in tree3.iterfind('suite/suite'):

a = elem.attrib

suitedict = {}

testlist2.append(suitedict) #每一个用例集合存入列表

testlist = []

suitename = a['name']#获取用例结合的名字

for test in elem.iter(tag='test'):

b=test.attrib

for data in test.iterfind('status'):

casename = b['name'] #获取用例的名字

c=data.attrib

status=c['status'] #获取每条用例的执行结果

casedict['casename'] = casename #用例名字存入字典

casedict['status'] = status #用例执行结果存入字典

testlist.append(casedict) #每一条用例的名字和执行结果作为字典存入列表

casedict = {}

suitedict['suitename']=suitename

suitedict['test']=testlist

return testlist2 #最终返回的就是[{'suitename': 'xxx', 'test': [{'casename': '01 xxx', 'status': 'PASS'}, {'casename': '02 xxx', 'status': 'PASS'}

2.3 数据填充

通过前面获取的获取,填充到jinja2的模板中,会生成另外一个有数据的html文件

from jinja2 import Environment, FileSystemLoader

import parsexml



def generate_html(data):

env = Environment(loader=FileSystemLoader('./')) # 加载模板

template = env.get_template('report.html')

# template.stream(body).dump('result.html', 'utf-8')

data=parsexml.get_total_statistics()#获取解析的xml的用例统计数据

data2=parsexml.getcase()#获取测试用例信息和执行结果

with open("result.html", 'w',encoding='utf-8') as fout:

html_content = template.render(data=data,data2=data2)

fout.write(html_content) # 写入模板 生成html

2.4 jinja2模板介绍

jinja2模板的原理就是,通过先创建一个html的模板文件,然后将数据渲染到模板文件,生成一个渲染后的html文件,该文件会显示填充的数据


<html lang="en">

<head>

<meta charset="utf-8">

<title>战娃利润中心指标自动化测试报告title>

head>

<body>

<div style="width:100%;float:left">

<table cellspacing="0" cellpadding="4" border="1" align="left">

<thead>

<tr bgcolor="#F3F3F3">

<td style="text-align:center" colspan="9"><b>战娃利润中心日报自动检测b>td>

tr>


<tr>

<td bgcolor="#F3F3F3" style="width:100px"><b>指标预测规则:b>td>

<td colspan="8"><a href="https://docs.qq.com/sheet/DT1ZBZHdGdXJkVWFL">点击查看指标预测规则a>td>

tr>


<tr bgcolor="#F3F3F3">

<td><b>用例总数b>td>

<td><b>通过b>td>

<td style="width:60px"><b>不通过b>td>

<td colspan="6"><b>通过率b>td>

tr>


<tr>

<td>{{data['total']}}td>

<td><b><span style="color:#66CC00">{{data['pass']}}span>b>td>

<td><b><span style="color:#FF3333">{{data['fail']}}span>b>td>

<td colspan="6">{{data['percent']}}td>

tr>


<tr bgcolor="#F3F3F3">

<td colspan="2"><b>Test Nameb>td>

<td><b>执行结果b>td>

<td><b>预测上限b>td>

<td><b>预测下限b>td>

<td><b>预测值b>td>

<td><b>实际值b>td>

<td><b>差值(预测-实际)b>td>

<td><b>差值百分比b>td>

tr>

thead>

<tbody>


{% for data in data2 %}

<tr>

<td colspan="9"><b>{{data['suitename']}}b>td>

tr>


<tr>

{% for c2 in data['test'] %}

<td colspan="2">{{c2['casename']}}td>

{% if c2['status']=='PASS' %}

<td><b><span style="color:#66CC00">{{c2['status']}}span>b>td>

{% else %}

<td><b><span style="color:#FF3333" >{{c2['status']}}span>b>td>

{% endif %}

<td>{{c2['max']}}td>

<td>{{c2['min']}}td>

{% if c2['casename']=='01 GMV' %}

<td>{{c2['yhat']}}td>

{% else %}

<td>--td>

{% endif %}

<td>{{c2['real']}}td>

{% if c2['casename']=='01 GMV' %}

<td>{{c2['reduce']}}td>

{% else %}

<td>--td>

{% endif %}

{% if c2['casename']=='01 GMV' %}

<td>{{c2['percent']}}td>

{% else %}

<td>--td>

{% endif %}

tr>

{% endfor %}

{% endfor %}

tbody>

table>

body>

html>

2.5 发送邮件

将上述渲染生成的有数据的html文件作为测试报告进行邮件发送

# !/usr/bin/python

# -*- coding: utf-8 -*-

import smtplib, time, os

from email.mime.text import MIMEText

from email.header import Header

import generate


def send_mail_html(file):

sender = 'ccc@fulu.com' #发件人

mail_to =['aa@fulu.com','bb@fulu.com] #收件人

t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) #获取当前时间

subject = '战娃利润中心指标自动化测试报告' + t #邮件主题

smtpserver = 'smtp.qiye.aliyun.com' #发送服务器地址

username = 'cc@fulu.com' #用户名

password = '123456' #密码

f = open(file, 'rb')

mail_body = f.read()

f.close()



msg = MIMEText(mail_body, _subtype='html', _charset='utf-8')

msg['Subject'] = Header(subject, 'utf-8')

msg['From'] = sender

msg['To'] = ";".join(mail_to)


try:

smtp = smtplib.SMTP()

smtp.connect(smtpserver)

smtp.login(username, password)

smtp.sendmail(sender, mail_to, msg.as_string())

except:

print("邮件发送失败!")

else:

print("邮件发送成功!")

finally:

smtp.quit()


def result():

file = 'result.html' #渲染后的html报告文件

result = {}

generate.generate_html(result)

send_mail_html(file)

邮件展示结果

三、回顾整个实现过程

在当初接到该需求的时候,尝试在网上找相关的实现方案,其中jenkins自带的RF的插件可以实现报告的解析和邮件发送,第一版我们就是采用该报告模板进行推送
第一版报告,参考该博文https://blog.csdn.net/qq_38317509/article/details/81316940

在需要展示每条用例的具体数据信息的时候,也是尝试对该模板文件进行修改取值,并查看了插件的源码实现,发现无法进行这种个性化的数据的取值,源码只是返回了用例信息、执行状态和执行时间,以及失败时候的msg,那能不能通过msg这个关键字来做文章呢,也就是把需要查看的数据通过msg打印显示出来,然而发现只有case失败的时候才显示用例,成功的时候不显示,而且数据以log显示,查看不是那么清晰

基于上述情况,发现了jinja2这个包,于是就放弃了jenkins的插件,通过自定义报告模板,然后填充数据的方式,这样灵活度就大大提高了,后续的个性化需求也方便去定制开发了,目前我们还是依赖jenkins进行测试任务的触发,我们希望将RF这块也容器化,这块你们有相关的实践吗,欢迎指导~




浏览 34
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报