【接口平台】测试报告邮件通知
在接口平台中,原本测试报告是通过微信的方式发给公司企业号进行广播通知。但是,现在由于其他子公司的使用,企业号设置相对繁琐,现计划增加邮件通知的功能
首先得支持邮件发送,Python3 SMTP发送邮件网上有数不清的栗子
#!/usr/bin/python3
import smtplib
from email.mime.text import MIMEText
from email.header import Header
sender = 'from@runoob.com'
receivers = ['429240967@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
# 三个参数:第一个为文本内容,第二个 plain 设置文本格式,第三个 utf-8 设置编码
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("菜鸟教程", 'utf-8') # 发送者
message['To'] = Header("测试", 'utf-8') # 接收者
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message.as_string())
print ("邮件发送成功")
except smtplib.SMTPException:
print ("Error: 无法发送邮件")
一开始对于s.sendmail(MAIL_USER, receivers, msgRoot.as_string())
中的 receivers
和 msgRoot['To']
中的收件人有些误解,以为两者一致,导致浪费了一些时间
调试修改一番就可达到预期的需求,代码是最好的文档
import smtplib
import traceback
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
from config.setting import *
def send_text(title, receivers, mail_msg):
"""
发送邮件
:param title: 邮件名称
:param receivers: 接收者 [a,b,c]
:param mail_msg: 邮件内容
:return:
"""
msgRoot = MIMEMultipart('related')
msgAlternative = MIMEMultipart('alternative')
# 标题信息
msgRoot['Subject'] = Header(title, 'utf-8')
# 发送人
msgRoot['From'] = Header(SENDER, 'utf-8')
# 接收人
msgRoot['To'] = ','.join(receivers)
msgRoot.attach(msgAlternative)
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
try:
s = smtplib.SMTP(SERVER, PORT)
s.login(MAIL_USER, MAIL_PWD)
s.sendmail(MAIL_USER, receivers, msgRoot.as_string())
except Exception as e:
traceback.print_exc(e)
finally:
s.quit()
重点来了。如何在邮件中优雅的呈现具体的信息呢
一开始一行行的敲html页面,发现太艰辛了,网上找找是否有测试报告模板吧
GOOD!找到一个还看的过去的测试报告和源码
直接修改代码发送邮件。发现两个问题,一个是详细的用例执行信息可以在swapi接口平台中展示即可,一个是css样式在邮件中并没有显示
这么挫不能忍啊
将css对应的代码直接复制到邮件信息中,然后调整布局,得到一下邮件报告
最后,贴上修改后的html
html_template = """
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<title>接口测试报告</title>
<meta name="generator" content="HTMLTestRunner 0.8.2.2" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css" media="screen"></style>
<style type="text/css">
.nav {{
padding-left: 0;
margin-bottom: 0;
list-style: none;
}}
.nav:before,
.nav:after {{
display: table;
content: " ";
}}
.nav:after {{
clear: both;
}}
.nav:before,
.nav:after {{
display: table;
content: " ";
}}
.nav:after {{
clear: both;
}}
.nav > li {{
position: relative;
display: block;
}}
.nav > li > a {{
position: relative;
display: block;
padding: 10px 15px;
}}
.nav > li > a:hover,
.nav > li > a:focus {{
text-decoration: none;
background-color: #eeeeee;
}}
.nav > li.disabled > a {{
color: #999999;
}}
.nav > li.disabled > a:hover,
.nav > li.disabled > a:focus {{
color: #999999;
text-decoration: none;
cursor: not-allowed;
background-color: transparent;
}}
.nav .open > a,
.nav .open > a:hover,
.nav .open > a:focus {{
background-color: #eeeeee;
border-color: #428bca;
}}
.nav .nav-divider {{
height: 1px;
margin: 9px 0;
overflow: hidden;
background-color: #e5e5e5;
}}
.nav > li > a > img {{
max-width: none;
}}
.nav-tabs {{
border-bottom: 1px solid #dddddd;
}}
.nav-tabs > li {{
float: left;
margin-bottom: -1px;
}}
.nav-tabs > li > a {{
margin-right: 2px;
line-height: 1.428571429;
border: 1px solid transparent;
border-radius: 4px 4px 0 0;
}}
.nav-tabs > li > a:hover {{
border-color: #eeeeee #eeeeee #dddddd;
}}
.nav-tabs > li.active > a,
.nav-tabs > li.active > a:hover,
.nav-tabs > li.active > a:focus {{
color: #555555;
cursor: default;
background-color: #ffffff;
border: 1px solid #dddddd;
border-bottom-color: transparent;
}}
.nav-tabs.nav-justified {{
width: 100%;
border-bottom: 0;
}}
.nav-tabs.nav-justified > li {{
float: none;
}}
.nav-tabs.nav-justified > li > a {{
margin-bottom: 5px;
text-align: center;
}}
.nav-tabs.nav-justified > .dropdown .dropdown-menu {{
top: auto;
left: auto;
}}
@media (min-width: 768px) {{
.nav-tabs.nav-justified > li {{
display: table-cell;
width: 1%;
}}
.nav-tabs.nav-justified > li > a {{
margin-bottom: 0;
}}
}}
.nav-tabs.nav-justified > li > a {{
margin-right: 0;
border-radius: 4px;
}}
.nav-tabs.nav-justified > .active > a,
.nav-tabs.nav-justified > .active > a:hover,
.nav-tabs.nav-justified > .active > a:focus {{
border: 1px solid #dddddd;
}}
@media (min-width: 768px) {{
.nav-tabs.nav-justified > li > a {{
border-bottom: 1px solid #dddddd;
border-radius: 4px 4px 0 0;
}}
.nav-tabs.nav-justified > .active > a,
.nav-tabs.nav-justified > .active > a:hover,
.nav-tabs.nav-justified > .active > a:focus {{
border-bottom-color: #ffffff;
}}
}}
</style>
</head>
<body>
<div class="container-fluid">
<div class="page-header">
<h2 class="text-primary" style="font-size:45px;line-height:75px;text-align:center">{plan_name}(v{version} 测试报告)</h2>
<a href = {report_href} style="display: block; text-align: center; margin-left: 200px">测试报告详情链接(公司内网访问)</a>
</div>
<div>
<div class="tabbable" id="tabs-957640" style="display:flex; justify-content: center">
<ul class="nav nav-tabs">
<li class="active">
<a href="#panel-0" data-toggle="tab" style="Background-Color: #428bca; color: #fff;">用例数 ({case_num})</a>
</li>
<li>
<a href="#panel-1" data-toggle="tab" style="Background-Color: #5cb85c; color: #fff;">成 功 ({case_pass_num})</a>
</li>
<li>
<a href="#panel-2" data-toggle="tab" style="Background-Color: #d9534f; color: #fff;">失 败 ({case_fail_num})</a>
</li>
<li>
<a href="#panel-3" data-toggle="tab" style="Background-Color: #5bc0de; color: #fff;">通过率 ({passing_rate}%)</a>
</li>
</ul>
</div>
<div style="display:flex; justify-content: center; margin-top:20px">
<div class="col-md-4" style="Background-Color:#F5F5F5; ">
<h3 style="line-height:25px"> 测试报告概要信息</h3>
<table class="table table-hover table-bordered" style="width:100%; height:11px">
<tbody>
<tr class="info">
<td class="text-center"> 项  目: </td>
<td class="text-center">{project_name}</td>
</tr>
<tr class="info">
<td class="text-center"> 计  划: </td>
<td class="text-center">{plan_name}</td>
</tr>
<tr class="info">
<td class="text-center"> 执行版本: </td>
<td class="text-center">v{version}</td>
</tr>
<tr class="info">
<td class="text-center"> 运行环境: </td>
<td class="text-center">{env_name}</td>
</tr>
<tr class="info">
<td class="text-center"> 开始时间: </td>
<td class="text-center">{start_time} </td>
</tr>
<tr class="info">
<td class="text-center"> 测试时长: </td>
<td class="text-center">{elapsed}s</td>
</tr>
<tr class="info">
<td class="text-center"> 总用例数: </td>
<td class="text-center">{case_num}</td>
</tr>
<tr class="info">
<td class="text-center"> 通 过 率: </td>
<td class="text-center">{passing_rate}%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
"""
其实在调用的时候又遇到了一个问题,使用变量%s
的方式的时候,发现html中有一大批%
,可以将%
替换成%%
还有一种方式,str.format()
的方式,但是,html中出现{
或 }
时又被误判
最后选择将html原本的 {
替换成 {{
, }
替换成 }}
,变量使用 {case_num}
这样的方式
具体调用
# 邮件提示测试报告内容
mail_content = html_template.format(
project_name=project_name,
plan_name=plan_name,
version=plan_version,
env_name=env_name,
start_time=start_time,
elapsed=plan_elapsed,
case_num=case_num,
passing_rate=passing_rate,
case_pass_num=case_pass,
case_fail_num=case_fail,
case_error_num=case_error,
report_href=report_href
)