1, Background
The RF result report can facilitate us to view each use case set and the execution result statistics of use cases. However, some projects involve the comparison of some data. We hope to see the data intuitively. The original test report can not meet this demand.
- Native Report
- Project requirements report format
2, Solution
2.1 flow chart
- Parse output XML to obtain the relevant information and execution results of the use case
- Obtain the data to be displayed through API and database
- Encapsulate the data of the above two steps into a data list to facilitate template rendering later
- Draw HTML report template according to requirements
- Perform data filling and rendering on the template to generate a report file
- Mail sending report
2.2 output.xml parsing
We can analyze the RF output by analyzing the test case related information and operation results XML file
2.2.1 obtain statistics of use case operation
import xml.dom.minidom import xml.etree.ElementTree # Open xml document dom = xml.dom.minidom.parse('E:\\robot\\fightdata_yuce\\results\\output.xml') root2 = xml.etree.ElementTree.parse('E:\\robot\\fightdata_yuce\\results\\output.xml') # Get document element object root = dom.documentElement total = root.getElementsByTagName('total'); total_len = len(total) # total number of stat nodes 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"))#Number of failed cases d['pass'] = int(statlist[i].getAttribute("pass"))#Number of successful cases d['total'] = d['fail']+d['pass']#Total number of use cases d['percent'] = ('{:.2%}'.format(d['pass'] / d['total']))#Percentage of use cases list.append(d) return list
2.2.2 obtaining use case information
- Organizational structure of use cases
- Obtain use case information and execution results
The use case structure is multiple suites, with four cases under each suite
import xml.dom.minidom import xml.etree.ElementTree # Open xml document 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() # Get child nodes under suite def getcase(): casedict = {} testlist2 = [] for elem in tree3.iterfind('suite/suite'): a = elem.attrib suitedict = {} testlist2.append(suitedict) #Each use case set is stored in the list testlist = [] suitename = a['name']#Get the name of the use case combination for test in elem.iter(tag='test'): b=test.attrib for data in test.iterfind('status'): casename = b['name'] #Get the name of the use case c=data.attrib status=c['status'] #Get the execution result of each use case casedict['casename'] = casename #Use case names are stored in the dictionary casedict['status'] = status #The use case execution results are stored in the dictionary testlist.append(casedict) #The name and execution result of each use case are stored in the list as a dictionary casedict = {} suitedict['suitename']=suitename suitedict['test']=testlist return testlist2 #The final return is [{'suitename':'xxx ',' test ': [{' casename ':'01 xxx', 'status':'pass'}, #{'casename': '02 xxx', 'status': 'PASS'}
2.3 data filling
Through the previous acquisition and filling into the template of jinja2, another html file with data will be generated
from jinja2 import Environment, FileSystemLoader import parsexml def generate_html(data): env = Environment(loader=FileSystemLoader('./')) # Load template template = env.get_template('report.html') # template.stream(body).dump('result.html', 'utf-8') data=parsexml.get_total_statistics()#Get the use case statistics of the parsed xml data2=parsexml.getcase()#Obtain test case information and execution results with open("result.html", 'w',encoding='utf-8') as fout: html_content = template.render(data=data,data2=data2) fout.write(html_content) # Generate html by writing template
2.4 jinja2 template introduction
The principle of jinja2 template is to create an html template file first, and then render the data to the template file to generate a rendered html file, which will display the filled data
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Zhanwa profit center index automation test report</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>Automatic detection of daily report of zhanwa profit center</b></td> </tr> <!-- <tr> <td bgcolor="#F3f3f3 "style =" width: 80px "> < b > detailed report:</b></td> <td colspan="8"> <a href="${rooturl}${build.url}robot/report/report.html">Click to view report details</a> </td> </tr>--> <tr> <td bgcolor="#F3f3 "style =" width: 100px "> < b > indicator prediction rules:</b></td> <td colspan="8"> <a href="https://docs. qq. COM / sheet / dt1zbzhdgdxjkvwfl "> Click to view indicator prediction rules</a> </td> </tr> <!--The statistics of use cases are defined here--> <tr bgcolor="#F3F3F3"> <td><b>Total number of use cases</b></td> <td><b>adopt</b></td> <td style="width:60px"><b>Fail</b></td> <td colspan="6"><b>Pass rate</b></td> </tr> <!--Pass 2.3 The data obtained by rendering is filled here--> <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> <!-- The header information of the use case is defined here--> <tr bgcolor="#F3F3F3"> <td colspan="2"><b>Test Name</b></td> <td><b>results of enforcement</b></td> <td><b>Upper prediction limit</b></td> <td><b>Lower prediction limit</b></td> <td><b>Estimate</b></td> <td><b>actual value</b></td> <td><b>Difference(forecast-actual)</b></td> <td><b>Percentage difference</b></td> </tr> </thead> <tbody> <!--Pass 2.3 Data obtained by rendering data2,That is, the use case information data is filled in here, because it involves multiple suite, each suite There are multiple under case,Here, take each through two layers of circulation case Information about --> {% 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 sending mail
Send the html file with data generated by the above rendering as a test report
# !/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' #Sender mail_to =['aa@fulu.com','bb@fulu.com] #addressee t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) #Get current time subject = 'Zhanwa profit center index automation test report' + t #Mail subject smtpserver = 'smtp.qiye.aliyun.com' #Sending server address username = 'cc@fulu.com' #user name password = '123456' #password 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("Mail sending failed!") else: print("Mail sent successfully!") finally: smtp.quit() def result(): file = 'result.html' #Rendered html report file result = {} generate.generate_html(result) send_mail_html(file)
Email display results
3, Review the whole implementation process
When we first received the demand, we tried to find relevant implementation schemes on the Internet. The RF plug-in provided by jenkins can analyze the report and send e-mail. In the first version, we pushed the report template
For the first edition of the report, please refer to this blog post https://blog.csdn.net/qq_38317509/article/details/81316940
When you need to display the specific data information of each use case, you also try to modify the value of the template file, and check the source code implementation of the plug-in. It is found that this personalized data value cannot be obtained. The source code only returns the use case information, execution status and execution time, as well as the msg at the time of failure. Can you make an article through the keyword msg, That is, the data to be viewed is printed and displayed through msg. However, it is found that the use case is displayed only when the case fails, not when it succeeds, and the data is displayed in log, so the view is not so clear
Based on the above situation, we found the package jinja2, so we gave up jenkins' plug-in, customized the report template, and then filled in the data. In this way, the flexibility is greatly improved, and the subsequent personalized requirements are convenient for customization and development. At present, we still rely on jenkins to trigger the test task. We hope to container the RF part. Do you have relevant practice? Welcome guidance~