Jenkins教程-12-发送html邮件测试报告

news2024/12/27 17:36:37

上一小节我们学习了发送钉钉测试报告通知的方法,本小节我们讲解一下发送html邮件测试报告的方法。

1、自动化用例执行完后,使用pytest_terminal_summary钩子函数收集测试结果,存入本地status.txt文件中,供Jenkins调用

#conftest.py 

def pytest_terminal_summary(terminalreporter, exitstatus, config):
    """收集测试报告summary,并存入status.txt文件中,供Jenkins调用"""
    print("pytest_terminal_summary")
    passed_num = len([i for i in terminalreporter.stats.get('passed', []) if i.when != 'teardown'])
    failed_num = len([i for i in terminalreporter.stats.get('failed', []) if i.when != 'teardown'])
    error_num = len([i for i in terminalreporter.stats.get('error', []) if i.when != 'teardown'])
    skipped_num = len([i for i in terminalreporter.stats.get('skipped', []) if i.when != 'teardown'])
    total_num = passed_num + failed_num + error_num + skipped_num
    test_result = '测试通过' if total_num == passed_num + skipped_num else '测试失败'
    duration = round((time.time() - terminalreporter._sessionstarttime), 2)

    # 定义目录路径
    directory_path = './reports/'
    # 确保文件所在的目录存在
    os.makedirs(os.path.dirname(directory_path), exist_ok=True)
    # 定义文件路径
    file_path = os.path.join(directory_path, 'status.txt')
    with open(file_path, 'w', encoding='utf-8') as f:
        f.write(f'TEST_TOTAL={total_num}\n')
        f.write(f'TEST_PASSED={passed_num}\n')
        f.write(f'TEST_FAILED={failed_num}\n')
        f.write(f'TEST_ERROR={error_num}\n')
        f.write(f'TEST_SKIPPED={skipped_num}\n')
        f.write(f'TEST_DURATION={duration}\n')
        f.write(f'TEST_RESULT={test_result}\n')

本地文件status.txt中收集测试结果示例:

2、Jenkins中安装Environment Injector 和description setter 插件

Environment Injector插件用于注入环境变量

自动化测试任务配置中,添加构建步骤

填写测试结果收集文件status.txt的路径

description setter用于构建后设置任务描述

将status.txt中的的测试结果字段映射到任务描述中

执行任务构建后,任务描述中会有显示构建的测试结果,如下

3、安装python-jenkins 库,读取自动化测试任务构建后的测试结果描述信息

pip install python-jenkins

代码如下

# email_remind.py
import json
from datetime import datetime
import jenkins
import requests
import jmespath

host = "http://localhost:8080/"
username = 'admin'
password = 'xxxxxxxxxx'
webhook = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=f4444444444-c1d3-47f2-be78-098f80c2d194"
env = "test"
stage = "回归测试"
job = "auto_api_test"
maintainer = "米兔1号"
server = jenkins.Jenkins(host, username=username, password=password)
last_build_number = server.get_job_info(job)['lastCompletedBuild']['number']
build_info = server.get_build_info(job, last_build_number)
console_url = build_info['url'] + "console"
report_url = build_info['url'] + 'allure'
# report_url = ip_host + report_url.split(":")[-1]
test_status = json.loads(build_info['description'])
print("构建测试结果描述信息:", test_status)

total = test_status["total"]
passed = test_status["passed"]
passed_ratio = round(passed / total, 4) * 100
failed = test_status["failed"]
failed_ratio = round((100 - passed_ratio), 2)
error = test_status["error"]
skipped = test_status["skipped"]
duration = test_status["duration"]
build_time = datetime.fromtimestamp(build_info['timestamp'] / 1000).strftime('%Y-%m-%d %H:%M:%S')
success = total == (passed + skipped) if passed != 0 else False

执行上述代码,可以看出,已经获取到jenkins任务的测试结果信息了

4、上一步获取到的测试结果信息,包装成消息体,调用python 发送邮件的相关方法,发送邮箱消息

import json
import html
from datetime import datetime
import jenkins
import smtplib
from email.mime.text import MIMEText
from bs4 import BeautifulSoup, NavigableString

host = "http://localhost:8080/"
username = 'admin'
password = 'xxxxxxxxxxxx'
webhook = "https://oapi.dingtalk.com/robot/send?access_token=bffb1003f5b0ac9d9be5f8c863a38e2d646a69cd231147524829ffbba10e0fa3"
env = "test"
stage = "回归测试"
job = "auto_api_test"
maintainer = "米兔1号"
server = jenkins.Jenkins(host, username=username, password=password)
last_build_number = server.get_job_info(job)['lastCompletedBuild']['number']
build_info = server.get_build_info(job, last_build_number)
print("构建信息:", build_info)
console_url = build_info['url'] + "console"
print("console:", console_url)
report_url = build_info['url'] + 'allure'
print("report_url:", report_url)
test_status = json.loads(build_info['description'])
print("测试结果:", test_status)
total = test_status["total"]
passed = test_status["passed"]
passed_ratio = round(passed / total, 4) * 100
print("passed_ratio", passed_ratio)
failed = test_status["failed"]
failed_ratio = round((100 - passed_ratio),2)
print("failed:", failed_ratio)
error = test_status["error"]
skipped = test_status["skipped"]
duration = test_status["duration"]
build_time = datetime.fromtimestamp(build_info['timestamp'] / 1000).strftime('%Y-%m-%d %H:%M:%S')
success = total == (passed + skipped) if passed != 0 else False

sender = user = '1450xxxxxxx@qq.com'  # 发送方的邮箱账号
passwd = 'y222222xpbjkrdupxugcbg'  # 授权码
receiver = '19345678901@139.com'  # 接收方的邮箱账号,不一定是QQ邮箱

# 读入 html 文件的内容
html_content = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>钉钉oapi接口测试报告</title>
</head>
<body>
<h3>钉钉oapi接口测试报告</h3>
<li>【任务名称】:{job}</li>
<li>【测试阶段】:{stage}</li>
<li>【测试结果】:{'通过' if success else '失败'}</li>
<li>【用例总数】:{total}个</li>
<li>【通过数】:{passed}个</li>
<li>【通过率】:{passed_ratio}%</li>
<li>【失败数】:{failed}个</li>
<li>【失败率】:{failed_ratio}%</li>
<li>【错误数】:{error}个</li>
<li>【跳过数】:{skipped}个</li>
<li>【执行人】:{maintainer}</li>
<li>【执行时间】:{build_time}</li>
<li>【执行耗时】:{duration}</li>
<li><a href={report_url}>Allure详细报告,请点击查看</a></li>
<br>
(本邮件由系统自动发出,请勿回复!)
</body>
</html>
"""
print("html_content",html_content)
# with open('1.html', mode='r', encoding='utf-8') as f:
#     html_content = f.read()
# 指定类型是 html
msg = MIMEText(html_content, 'html', 'utf-8')
msg['From'] = user
msg['To'] = receiver
msg['Subject'] = '钉钉oapi接口测试任务执行报告通知'
smtp = smtplib.SMTP_SSL('smtp.qq.com', 465)
smtp.login(user, passwd)
smtp.sendmail(user, receiver, msg.as_string())

查看邮件如下:

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走,希望可以帮助到大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1884072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Optional类方法

Optional类 方法empty()方法of(T value)ofNullable(T value)filter(Predicate<? super T> predicate)get()ifPresent(Consumer<? super T> consumer)isPresent()map(Function<? super T,? extends U> mapper)orElse(T other)orElseGet(Supplier<? ex…

如何实现Action菜单

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"自定义标题栏"相关的内容&#xff0c;本章回中将介绍自定义Action菜单.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里提到的…

Swift 中的 StoreKit 测试

文章目录 前言创建一个 StoreKit Demo使用 SKTestSessionaskToBuyEnabled 属性总结前言 StoreKit 框架的第二次迭代是我在过去几年中应用程序中最重大的变化。最近版本的 StoreKit 框架已完全采用了 Swift 语言特性,如 async 和 await。本篇内容我们将讨论 StoreKitTest 框架…

AutoGen 两个agent讲相声

Lesson 1: Multi-Agent Conversation and Stand-up Comedy 第 1 课&#xff1a;多人对话和单口相声 Setup from utils import get_openai_api_key OPENAI_API_KEY get_openai_api_key() llm_config {"model": "gpt-3.5-turbo"}Define an AutoGen agent…

教育心理学期末考试重点

人本主义学习理论 人本主义主张&#xff0c;心理学应当把人作为一个整体来研究&#xff0c;而不是将人的心理肢解为不完整的几个部分&#xff0c;应该研究正常的人&#xff0c;而且更应该关注人的高级心理活动&#xff0c;如热情、信念、生命、尊严等内容。人本主义的学习理论…

线性代数|机器学习-P20鞍点和极值

文章目录 1 . 瑞利商的思考1.1 瑞利商的定义1.2 投影向量 2. 拉格朗日乘子法3. 鞍点4. 线性拟合4.1 范德蒙矩阵线性拟合4.2 python 代码4.3 范德蒙矩阵缺点 5. 均值和方差5.1 样本均值和方差5.2 总体期望 μ \mu μ,总体方差 σ 2 \sigma^2 σ2 1 . 瑞利商的思考 1.1 瑞利商…

算法金 | Transformer,一个神奇的算法模型!!

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 抱个拳&#xff0c;送个礼 在现代自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;Transformer 模型的出现带来了革命性的变…

算法 —— 滑动窗口

目录 长度最小的子数组 无重复字符的最长子串 最大连续1的个数 将x减到0的最小操作数 找到字符串中所有字母异位词 长度最小的子数组 sum比target小就进窗口&#xff0c;sum比target大就出窗口&#xff0c;由于数组是正数&#xff0c;所以相加会使sum变大&#xff0c;相减…

云计算与生成式AI的技术盛宴!亚马逊云科技深圳 Community Day 社区活动流程抢先知道!

小李哥最近要给大家分享7月7日在深圳的即将举办的亚马逊云科技生成式AI社区活动Community Day &#xff0c;干货很多内容非常硬核&#xff0c;不仅有技术分享学习前沿AI技术&#xff0c;大家在现场还可以动手实践沉浸式体验大模型&#xff0c;另外参与现场活动还可以领取诸多精…

高优先线程

你开发的时候有么有遇到过一个问题&#xff1a;服务器的一个服务线程过几个小时断连一次&#xff0c;断连之后会马上重连这种情况。这是由于CPU负载较高,线程调度时将处理数据的线程挂起了一段时间导致的。 因此&#xff0c;我有考虑到把cpu的核心进行分散开来&#xff0c;就类…

关于发那科机器人系统升级方法

首先需要镜像备份和全备份&#xff0c;最好把机器人要到刻度线位置&#xff0c;零点位置 选择控制器启动&#xff0c;也可以按preevnext进入控制器模式

技术革新:如何用数据中台实现数字化转型

作为程序员&#xff0c;我们总是对技术如何改变企业运作充满好奇。今天&#xff0c;我们将深入探讨森马集团如何利用数据中台技术&#xff0c;实现从传统数据分析到数字化转型的华丽转身。 1. 技术背景&#xff1a;森马集团的数字化挑战 森马集团&#xff0c;一个在服饰行业占…

幻兽帕鲁服务器如何安装模组安装

由于模组多数为Window版本的&#xff0c;所以本教程以服务端为Window的作为演示&#xff08;Linux服务端的也是一样的操作&#xff09;百度莱卡云开服 如果你你是Linux版本的&#xff0c;请点击跳转切换服务端教程 接下来是本地安装模组包的方法&#xff08;服务器自带&#xf…

浅谈定时器之同步定时器

浅谈定时器之同步定时器 “同步定时器”&#xff08;Synchronizing Timer&#xff09;是一个特别的定时器&#xff0c;它用于确保在特定时间点上多个线程&#xff08;或虚拟用户&#xff09;同时发起请求&#xff0c;这对于测试系统在高并发情况下的表现尤为重要。本文将深入解…

通义灵码 Visual Studio 小白上手指南

一、下载和安装指南 本安装步骤适用于 Windows 10 及以上操作系统中安装和使用通义灵码。 步骤 1&#xff1a;准备工作 操作系统&#xff1a;Windows 10 及以上&#xff1b;下载并安装 ****Visual Studio 2022 17.3.0 及以上版本。 步骤 2&#xff1a;在 Visual Studio 202…

【Linux】:命令行参数

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux命令行参数的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入…

分享一个超级实用的东西——巴比达远程访问

前言 &#x1f388;家人们&#xff0c;今天我要和你们分享一个超级实用的东西——巴比达远程访问&#xff01;&#x1f389; &#x1f4bb;有了它&#xff0c;无论你身在何处&#xff0c;都能轻松访问家中的电脑&#x1f4bb;&#xff0c;就像在身边一样方便&#xff01;&…

C++类型转换可调用对象

目录 C的四种可视性类型转换 1.static_cast 2.reinterpret_cast 3.const_cast 4.dynamic_cast C中的可调用对象 普通函数 函数指针 仿函数 Lambda表达式 包装器function bind C的四种可视性类型转换 C语言中的类型转换是不安全、不明确的&#xff0c;于是C就出了更…

JavaFX布局-BorderPane

JavaFX布局-BorderPane 实现方式Java实现FXML实现 综合案例 将容器空间分成五个区域&#xff1a;顶部&#xff08;Top&#xff09;、底部&#xff08;Bottom&#xff09;、左侧&#xff08;Left&#xff09;、右侧&#xff08;Right&#xff09;和中心&#xff08;Center&#…

专题六:Spring源码之初始化容器BeanFactory

上一篇咱们通过一个例子介绍初始化容器上下文相关内容&#xff0c;并通过两个示例代码看到了Spring在设计阶段为我预留的扩展点&#xff0c;和我们应该如何利用这两个扩展点在Spring初始化容器上下文阶段为我们提供服务。这一篇咱们接着往下看。 老这样子下回到refresh方法上来…