文章目录
一、前言:
在日常接口自动化过程中,在执行完成后,通常都会将执行结果以邮件的形式或者企业微信等方式发送给相关人员,本篇主要介绍通过邮件发送
二、邮件发送功能实现:
2.1、邮件信息配置:
…# ========================================================= #
… # ************** 邮件发送配置信息 ************** #
…# ========================================================= #
公司自己都会有企业邮箱信息不知道的问相关人员要下就可以,按下图配置:
2.2、导入模块:
## 导入模块
from email.mime.text import MIMEText # 纯文本,HTML
from email.mime.image import MIMEImage # 图片
from email.mime.multipart import MIMEMultipart # 多种组合内容
2.3、建立邮箱连接、登录、发送功能:
class send_email(object):
# image().count()
# image().month_count()
def __init__(self):
# 连接重试功能和连接超时功能的smtp连接
self._max_retries_count = 2 # 设置最大重试次数
self._conn_retries_count = 0 # 初始重试次数
self._conn_timeout = 100 # 连接超时时间为10秒
self._smtp = smtplib.SMTP() # 实例化对象
# self.sys = platform.system()
# self.image = image()
def connect(self):
"""
SMTP连接设置
"""
while self._conn_retries_count <= self._max_retries_count:
try:
self._smtp.connect(SMTP_HOST, SMTP_PORT)
print(f"smtp连接success---连接地址{
SMTP_HOST}:{
SMTP_PORT}")
break
except Exception as e:
print(f"smtp连接False---连接地址{
SMTP_HOST}:{
SMTP_PORT}")
raise e
time.sleep(2)
continue
def login(self):
"""
邮箱登录
"""
while self._conn_retries_count <= self._max_retries_count:
try:
self._smtp.login(SMTP_USER, SMTP_PASSWORD)
print(f"smtp邮箱登录success---登录信息{
SMTP_USER}/{
SMTP_PASSWORD}")
break
except Exception as e:
print(f"smtp邮箱登录False---登录信息{
SMTP_USER}/{
SMTP_PASSWORD}")
raise e
time.sleep(2)
continue
def send_message(self):
self.connect()
self.login()
try:
self._smtp.sendmail(SMTP_SENDER, SMTP_RECEIVER + CS_RECEIVER, self.message_config().as_string())
print(f"smtp邮件发送success------")
except Exception as e:
print(f"smtp邮件发送False------")
raise e
finally:
self.quit()
def quit(self):
"""
关闭服务器
"""
self._smtp.quit()
2.4、发送邮件模板:
def message_config(self):
# 计算用例通过率并保留两位小数的方法
PERCENT_CASES = '{:.2%}'.format(int(read_environment('passd_list')[5]) / TOTAL_CASES)
url = LINUX_REPORT
2.4.1、构建邮件表格模板:
"""
配置邮件信息
:return: 消息对象
"""
content = f'''
<html>
<body>
<font style="font-size: 20px" ><p> 一、【测试时间】:<font style="font-size: 15px" >{
Ran().ran_ymd()}</font></p></font></br>
<font style="font-size: 20px"><p>二、【测试模块】</font><br><font style="font-size: 15px">{
test_OBJECT}</p></font><br/>
<font style="font-size: 20px">三、【当前覆盖场景】</font>
<font style="font-size: 15px"><p>{
test_MOUDELS}</p></font>
<font style="font-size: 15px"><p>{
test01_MOUDELS}</p></font>
<font style="font-size: 15px"><p>{
test02_MOUDELS}</p></font>
<font style="font-size: 20px"><p>四、【用例信息】</font><br><font style="font-size: 18px">本次执行总计执行用例:{
TOTAL_CASES}个,用例通过率:{
PERCENT_CASES},具体详情见如下:</P></font>
<font style="font-size: 18px" ><p>用例信息汇总:</p></font>
<table width="1000" bordercolor="black" border="1" cellspacing="0">
<tr bgcolor="#9DBEE2" border="1px solid #ccc" cellspacing="0" cellpadding="0">
<td style="width: 200px;" align="center"><front size="2"><strong><b>模块</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>各模块总用例数</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>当日新增用例数</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>本周新增用例数</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>本月新增用例数</b></strong></front></td>
</tr>
<tr>
<td align="center"><front size="2"><strong><b>test01</b></strong></front></td>
<td align="center"><front size="2">{
cases_dic['test01']}</front></td>
<td align="center"><front size="2">{
rv[0]['test_01']}</front></td>
<td align="center"><front size="2">{
rv[1]['test_02']}</front></td>
<td align="center"><front size="2">{
rv[2]['test_03']}</front></td>
</tr>
</table><br>
<font style="font-size: 20px" ><p>五、执行情况:</font></br><font style="font-size: 18px" >本次执行详情:<a href={
url} style="font-size: 18px">点击链接查看详情</a></p></font>
<table width="1000" bordercolor="black" border="1" cellspacing="0">
<tr bgcolor="#9DBEE2" border="1px solid #ccc" cellspacing="0" cellpadding="0">
<td style="width: 200px;" align="center"><front size="2"><strong><b>模块</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>各模块总用例数</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>执行通过用例数</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>执行失败用例数</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>执行跳过用例数</b></strong></front></td>
<td style="width: 200px;" align="center"><front size="2"><strong><b>执行故障用例数</b></strong></front></td>
</tr>
<tr>
<td align="center"><front size="2"><strong><b>test01</b></strong></front></td>
<td align="center"><front size="2">{
cases_dic['test_01']}</front></td>
<td align="center"><front size="2">{
read_environment('passd_list')[0]}</front></td>
<td align="center"><front size="2">{
read_environment('failed_list')[0]}</front></td>
<td align="center"><front size="2">{
read_environment('skipped_list')[0]}</front></td>
<td align="center"><front size="2">{
read_environment('error_list')[0]}</front></td>
</tr>
</table>
</body>
</html>
'''
2.4.2、在HTML邮件模板中加入文本:
msg = MIMEMultipart('related')
msg["Subject"] = f"{
Ran().ran_ymd()}-KCB接口自动化测试报告-{
read_environment('env')}环境"
msg["From"] = SMTP_SENDER # 发送人
msg["To"] = ";".join(SMTP_RECEIVER) # 接收人
msg["Cc"] = ";".join(CS_RECEIVER) # 抄送人
msg.attach(MIMEText(content, 'html', 'utf-8'))
# # 读取图片
# self.image.count()
# fp = open(IMAGE_PATH + '折线图1.jpg', 'rb') # 打开文件
# msgImage = MIMEImage(fp.read()) # 读入 msgImage 中
# fp.close() # 关闭文件
# # 定义图片 ID,在 HTML 文本中引用
# msgImage.add_header('Content-ID', 'testimage')
# msg.attach(msgImage)
#
# self.image.month_count()
# fp1 = open(IMAGE_PATH + '折线图2.jpg', 'rb') # 打开文件
# msgImage1 = MIMEImage(fp1.read()) # 读入 msgImage 中
# fp1.close() # 关闭文件
#
# # 定义图片 ID,在 HTML 文本中引用
# msgImage1.add_header('Content-ID', 'test1image')
# msg.attach(msgImage1)
return msg
2.4.3、邮件模板加入图片方法:
# # 读取图片
# self.image.count()
# fp = open(IMAGE_PATH + '折线图1.jpg', 'rb') # 打开文件
# msgImage = MIMEImage(fp.read()) # 读入 msgImage 中
# fp.close() # 关闭文件
# # 定义图片 ID,在 HTML 文本中引用
# msgImage.add_header('Content-ID', 'testimage')
# msg.attach(msgImage)
#
# self.image.month_count()
# fp1 = open(IMAGE_PATH + '折线图2.jpg', 'rb') # 打开文件
# msgImage1 = MIMEImage(fp1.read()) # 读入 msgImage 中
# fp1.close() # 关闭文件
#
# # 定义图片 ID,在 HTML 文本中引用
# msgImage1.add_header('Content-ID', 'test1image')
# msg.attach(msgImage1)
return msg
在上述模板中已经定义了:Content-ID,
引用方法:html_img = f’
{content}
三、matplotlib画图并生成图片
3.1、安装matplotlib模块:
pip Install matplotlib == 3.6.2
3.2、导入模块:
import matplotlib.pyplot as plt
import warnings
# 忽略告警
warnings.filterwarnings("ignore")
3.3、画图并生成图片:
class image(object):
def __init__(self):
self.ran = Ran()
self.month_ini = operate_ini(CASE_MONTH + 'mon_nums.ini')
self.month = self.month_ini.read_ini3(self.ran.ran_m())
self.month_1 = self.month_ini.read_ini3(str(int(self.ran.ran_m()) - 1))
self.month_2 = self.month_ini.read_ini3(str(int(self.ran.ran_m()) - 2))
self.month_3 = self.month_ini.read_ini3(str(int(self.ran.ran_m()) - 3))
self.month_4 = self.month_ini.read_ini3(str(int(self.ran.ran_m()) - 4))
def month_count(self):
"""
各模块用例月度新增数量
"""
plt.rcParams['font.sans-serif'] = ['SimHei'] # 显示汉字
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
x = [str(int(self.ran.ran_m()) - 3) + '月', str(int(self.ran.ran_m()) - 2) + '月',
str(int(self.ran.ran_m()) - 1) + '月',
self.ran.ran_m() + '月'] # X轴数据 字符串类型数据
a1 = [int(self.month_3[0][1]) - int(self.month_4[0][1]), int(self.month_2[0][1]) - int(self.month_3[0][1]),
int(self.month_1[0][1]) - int(self.month_2[0][1]),
int(self.month[0][1]) - int(self.month_1[0][1])] # Y轴
a2 = [int(self.month_3[1][1]) - int(self.month_4[1][1]), int(self.month_2[1][1]) - int(self.month_3[1][1]),
int(self.month_1[1][1]) - int(self.month_2[1][1]),
int(self.month[1][1]) - int(self.month_1[1][1])] # Y轴
a3 = [int(self.month_3[2][1]) - int(self.month_4[2][1]), int(self.month_2[2][1]) - int(self.month_3[2][1]),
int(self.month_1[2][1]) - int(self.month_2[2][1]),
int(self.month[2][1]) - int(self.month_1[2][1])] # Y轴
a4 = [int(self.month_3[3][1]) - int(self.month_4[3][1]), int(self.month_2[3][1]) - int(self.month_3[3][1]),
int(self.month_1[3][1]) - int(self.month_2[3][1]),
int(self.month[3][1]) - int(self.month_1[3][1])] # Y轴
a5 = [int(self.month_3[4][1]) - int(self.month_4[4][1]), int(self.month_2[4][1]) - int(self.month_3[4][1]),
int(self.month_1[4][1]) - int(self.month_2[4][1]),
int(self.month[4][1]) - int(self.month_1[4][1])] # Y轴
plt.figure() # 声明一个新画布
plt.style.use('ggplot') # 添加网格线
plt.title('各模块用例月度新增数量') # 折线图标题
plt.xlabel('月份') # X轴标题
plt.ylabel('月度用例新增数量') # Y轴标题
plt.plot(x, a1) # 绘制折线图,添加数据点
plt.plot(x, a2) # 绘制折线图,添加数据点
plt.plot(x, a3) # 绘制折线图,添加数据点
plt.plot(x, a4) # 绘制折线图,添加数据点
plt.plot(x, a5) # 绘制折线图,添加数据点
plt.legend(['test01', 'test02', 'test03', 'test04', 'test05']) # 设置折线名称
plt.savefig(IMAGE_PATH + '折线图2.jpg') # 保存到本地文件夹,当前路径下
这样就可以先调用matplotlib生成图片后,在发送邮件中创建图片节点并添加在HTML文本中,这样就实现了发送的邮件中既有文本又有图片