(2023-05-11) 支持测试完成后,通过yagmail发送pytest-html的测试结果邮件

This commit is contained in:
floraachy
2023-05-17 17:27:12 +08:00
parent 7d11cfd26a
commit 2a8410b32f
4 changed files with 169 additions and 3 deletions

View File

@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
# @Time : 2023/5/10 10:43
# @Author : chenyinhua
# @File : send_result_handle.py
# @Software: PyCharm
# @Desc:
from common_utils.yagmail_handle import YagEmailServe
from config.settings import email
from config.global_vars import NotificationType
from config.settings import SEND_RESULT_TYPE
from common_utils.bs4_handle import SoupAPI
def get_test_info_from_html_report(html_report_path):
"""
从html测试报告中获取测试情况
"""
bs = SoupAPI(html_report_path)
results = {}
# -------------- 获取测试环境信息 --------------
environment_info = bs.get_element_by_id("environment").get_text()
new_environment_info = [element for element in environment_info.split("\n") if element != '']
for key, value in enumerate(new_environment_info):
if value == "Platform":
results['platform'] = new_environment_info[key + 1]
if value == "Python":
results['python_version'] = f"Python {new_environment_info[key + 1]}"
if value == "开始时间":
results['start_time'] = new_environment_info[key + 1]
if value == "项目名称":
results['project_name'] = new_environment_info[key + 1]
if value == "项目环境":
results['project_env'] = new_environment_info[key + 1]
# -------------- 获取测试人员,所属部门,测试用例总数,运行时长 --------------
p_elements = bs.get_elements_by_tag("p")
for p_element in p_elements:
res = p_element.get_text()
if "测试人员:" in res:
results['tester'] = res.replace("测试人员:", "")
if "所属部门: " in res:
results['dept'] = res.replace("所属部门: ", "")
if "tests ran" in res:
new_list = res.split(" ")
results['runs_time'] = f"{new_list[4]}"
# -------------- 获取具体结果 --------------
# 通过的用例个数
passed = bs.select_element('span.passed')[0]
results["passed"] = int(passed.get_text().split(" ")[0])
# 跳过的用例个数
skipped = bs.select_element('span.skipped')[0]
results["skipped"] = int(skipped.get_text().split(" ")[0])
# 失败的用例个数
failed = bs.select_element('span.failed')[0]
results["failed"] = int(failed.get_text().split(" ")[0])
# 错误的用例个数
error = bs.select_element('span.error')[0]
results["error"] = int(error.get_text().split(" ")[0])
# 预期失败的用例个数
xfailed = bs.select_element('span.xfailed')[0]
results["xfailed"] = int(xfailed.get_text().split(" ")[0])
# 意外通过的用例个数
xpassed = bs.select_element('span.xpassed')[0]
results["xpassed"] = int(xpassed.get_text().split(" ")[0])
# 重跑的用例个数
rerun = bs.select_element('span.rerun')[0]
results["rerun"] = int(rerun.get_text().split(" ")[0])
# 用例总数
results['total_cases'] = results["passed"] + results["skipped"] + results["failed"] + results["error"] + results[
"xfailed"] + results["xpassed"]
return results
def send_result(results, attachment_path=None):
"""
根据用户配置,采取指定方式,发送测试结果
"""
# 默认不发送任何通知
if SEND_RESULT_TYPE == NotificationType.DEFAULT.value:
pass
# 发送邮件通知
elif SEND_RESULT_TYPE == NotificationType.EMAIL.value:
email_settings = email
yag = YagEmailServe(user=email_settings.get("user"), password=email_settings.get("password"),
host=email_settings.get("host"))
info = {
"subject": f"{results.get('project_name', None)} 接口自动化报告_{results.get('start_time', None)}",
"contents": f"""
各位同事, 大家好:
    自动化用例于{results.get('start_time', None)}开始运行,运行时长:{results.get('runs_time', None)} 目前已执行完成。
-----------------------------------------------------------------------------------------------------------
    测试人:{results.get('tester', None)} / {results.get('dept', None)}
    测试平台:{results.get('platform', None)} / {results.get('python_version', None)}
    测试环境:{results.get('project_env', None)}
---------------------------------------------------------------------------------------------------------------
    执行结果如下:
        用例运行总数: {results.get("total_cases", None)}
        通过用例个数passed: {results.get("passed", None)}
        失败用例个数failed: {results.get("failed", None)}
        异常用例个数error: {results.get("error", None)}
        跳过用例个数skipped: {results.get("skipped", None)}
        预期失败用例个数xfailed: {results.get("xfailed", None)}
        意外通过用例个数xpassed: {results.get("xpassed", None)}
        失败重试用例个数 * 次数之和rerun: {results.get("rerun", None)}
        成 功 率: {(results.get("passed") / results.get("total_cases")) * 100} %
**********************************
jenkins地址https://xxxxxxxxx
详细情况可登录jenkins平台查看非相关负责人员可忽略此消息。谢谢。
""",
"to": email.get("to"),
"attachments": attachment_path
}
yag.send_email(info)
# 发送钉钉通知
elif SEND_RESULT_TYPE == NotificationType.DING_TALK.value:
pass
# 发送企业微信通知
elif SEND_RESULT_TYPE == NotificationType.WECHAT.value:
pass
# 全部渠道都发送通知
else:
pass

View File

@@ -19,3 +19,13 @@ class CaseFileType(Enum):
YAML = 1
EXCEL = 2
ALL = 0
class NotificationType(Enum):
""" 自动化通知方式 """
DEFAULT = 0
DING_TALK = 1
WECHAT = 2
EMAIL = 3
ALL = 4

View File

@@ -6,9 +6,13 @@
# @Software: PyCharm
# @Desc: 项目配置文件
# ------------------------------------ 配置信息 ----------------------------------------------------#
# 0代表执行Excel和yaml两种格式的用例 1 代表 yaml文件2 用例代表Excel用例
CASE_FILE_TYPE = 0
# 0表示默认不发送任何通知 1代表钉钉通知2代表企业微信通知 3代表邮件通知 4代表所有途径都发送通知
SEND_RESULT_TYPE = 3
# 测试报告的定制化信息展示
REPORT_TITLE = "自动化测试报告"
REPORT_NAME = f"apiautotest-report-"
@@ -19,7 +23,7 @@ DEPARTMENT = "所属部门: 开源中心"
# 指定日志收集级别
LOG_LEVEL = "INFO"
# 测试数据
# ------------------------------------ 测试数据 ----------------------------------------------------#
test = [
{
# 示例测试环境及示例测试账号
@@ -44,3 +48,13 @@ live = [
"project": ""
}
]
# ------------------------------------ 邮件配置信息 ----------------------------------------------------#
# 发送邮件的相关配置信息
email = {
"user": "******", # 发件人邮箱
"password": "******", # 发件人邮箱授权码
"host": "smtp.qq.com",
"to": ["******", "******"] # 收件人邮箱
}

View File

@@ -13,6 +13,7 @@ import pytest
from py._xmlgen import html # 安装pytest-html版本最好是2.1.1
from time import strftime
from config.settings import test, live, REPORT_TITLE, PROJECT_NAME, TESTER, DEPARTMENT
from case_utils.send_result_handle import get_test_info_from_html_report, send_result
# ------------------------------------- START: 配置运行环境 ---------------------------------------#
@@ -54,6 +55,7 @@ def get_config(request):
# ------------------------------------- END: 配置运行环境 ---------------------------------------#
# ------------------------------------- START: 报告处理 ---------------------------------------#
def pytest_collection_modifyitems(items):
"""# 测试用例执行收集完成时将收集到的item的name和nodeid的中文显示在控制台上"""
@@ -71,7 +73,6 @@ def pytest_runtest_makereport(item, call):
report = outcome.get_result()
# TODO由于目前无法动态将用例数据中的title写入测试方法中的文档注释因此该处理方法暂时搁置
# 将测试方法的文档注释作为结果表的Description的值如果文档注释为空则测试方法名作为结果表的Description的值
logger.debug(f"文档注释:{item.function.__doc__}")
report.description = str(item.function.__doc__)
report.nodeid = report.nodeid.encode("utf-8").decode("unicode_escape")
@@ -104,6 +105,15 @@ def pytest_sessionfinish(session, exitstatus):
session.config._metadata['项目环境'] = GLOBAL_VARS.get("host", "")
@pytest.hookimpl(hookwrapper=True)
def pytest_terminal_summary(terminalreporter, exitstatus, config):
yield
# 获取测试报告路径,并发送测试结果
report_path = config.getoption('--html')
results = get_test_info_from_html_report(report_path)
send_result(results, report_path)
def pytest_html_results_summary(prefix, summary, postfix):
"""
修改Summary部分的信息