增加统一配置发送群聊及邮箱配置信息
This commit is contained in:
parent
cda0cc2b45
commit
9ffdd83d5c
|
@ -16,18 +16,17 @@ from common.exceptions import SendMessageError
|
||||||
class MailSender:
|
class MailSender:
|
||||||
"""发送邮件功能"""
|
"""发送邮件功能"""
|
||||||
|
|
||||||
def __init__(self, mail_subject, sender_mail_address, sender_username, sender_password, receiver_mail_list,
|
def __init__(self, mail_subject, sender_username, sender_password, receiver_mail_list,
|
||||||
smtp_domain, smtp_port):
|
smtp_domain, smtp_port):
|
||||||
self.subject = mail_subject
|
self.subject = mail_subject # 邮件标题
|
||||||
self.sender_mail_address = sender_mail_address
|
self.sender_username = sender_username # 发件人邮箱
|
||||||
self.sender_username = sender_username
|
self.sender_password = sender_password # 发件人邮箱授权码
|
||||||
self.sender_password = sender_password
|
self.receiver_mail_list = receiver_mail_list # 收件人邮箱
|
||||||
self.receiver_mail_list = receiver_mail_list
|
self.smtp_domain = smtp_domain # 发送邮箱的域名
|
||||||
self.smtp_domain = smtp_domain
|
self.smtp_port = smtp_port # 发送邮箱的端口号
|
||||||
self.smtp_port = smtp_port
|
|
||||||
|
|
||||||
self.message = MIMEMultipart()
|
self.message = MIMEMultipart()
|
||||||
self.message['From'] = Header(self.sender_mail_address, 'utf-8')
|
self.message['From'] = Header(self.sender_username, 'utf-8')
|
||||||
self.message['To'] = ';'.join(self.receiver_mail_list)
|
self.message['To'] = ';'.join(self.receiver_mail_list)
|
||||||
self.message['subject'] = Header(self.subject, 'utf-8')
|
self.message['subject'] = Header(self.subject, 'utf-8')
|
||||||
|
|
||||||
|
@ -67,9 +66,9 @@ class MailSender:
|
||||||
return key
|
return key
|
||||||
return 'application/octet-stream' # 一切未知类型
|
return 'application/octet-stream' # 一切未知类型
|
||||||
|
|
||||||
def attach_text(self, text_to_send):
|
def attach_text(self, content):
|
||||||
"""添加邮件正文内容"""
|
"""添加邮件正文内容"""
|
||||||
self.message.attach(MIMEText(text_to_send, 'html', 'utf-8'))
|
self.message.attach(MIMEText(content, 'html', 'utf-8'))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def attach_file(self, file_path):
|
def attach_file(self, file_path):
|
||||||
|
@ -87,7 +86,7 @@ class MailSender:
|
||||||
# 使用with可以加入超时等待30s,并且发送完成后自动关闭链接,省去了smtp_obj.quit()步骤
|
# 使用with可以加入超时等待30s,并且发送完成后自动关闭链接,省去了smtp_obj.quit()步骤
|
||||||
with smtplib.SMTP_SSL(self.smtp_domain, self.smtp_port, timeout=30) as smtp_obj:
|
with smtplib.SMTP_SSL(self.smtp_domain, self.smtp_port, timeout=30) as smtp_obj:
|
||||||
smtp_obj.login(self.sender_username, self.sender_password)
|
smtp_obj.login(self.sender_username, self.sender_password)
|
||||||
smtp_obj.sendmail(from_addr=self.sender_mail_address, to_addrs=self.receiver_mail_list,
|
smtp_obj.sendmail(from_addr=self.sender_username, to_addrs=self.receiver_mail_list,
|
||||||
msg=self.message.as_string())
|
msg=self.message.as_string())
|
||||||
logger.info("发送邮件成功")
|
logger.info("发送邮件成功")
|
||||||
except smtplib.SMTPException as e:
|
except smtplib.SMTPException as e:
|
||||||
|
@ -99,6 +98,6 @@ class MailSender:
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
MailSender('测试邮件发送', 'xxxxx@xxxx.com', 'xxxxx@xxxx.com', 'xxxxxxx',
|
MailSender('测试邮件发送', 'xxxxx@xxxx.com', 'xxxxxxx',
|
||||||
['xxxxx@xxxx.com'], 'smtp.exmail.qq.com', 465).attach_text(
|
['xxxxx@xxxx.com'], 'smtp.exmail.qq.com', 465).attach_text(
|
||||||
'测试邮件').attach_file('/Users/wangjie/SensoroApi/outFiles/pytest_report/report.html').send()
|
'测试邮件').attach_file('/Users/wangjie/SensoroApi/outFiles/pytest_report/report.html').send()
|
||||||
|
|
|
@ -5,23 +5,9 @@
|
||||||
# @File : robot_sender.py
|
# @File : robot_sender.py
|
||||||
# @project : SensoroApi
|
# @project : SensoroApi
|
||||||
|
|
||||||
import os
|
|
||||||
import requests
|
import requests
|
||||||
from common.base_log import logger
|
from common.base_log import logger
|
||||||
from common.exceptions import SendMessageError, ValueTypeError
|
from common.exceptions import SendMessageError, ValueTypeError
|
||||||
from common.settings import ENV
|
|
||||||
from utils.reportdatahandle import ReportDataHandle
|
|
||||||
|
|
||||||
|
|
||||||
def get_env_from_jenkins(name, base=''):
|
|
||||||
"""从Jenkins中获取全局环境变量"""
|
|
||||||
return os.getenv(name) and os.getenv(name).strip() or base
|
|
||||||
|
|
||||||
|
|
||||||
ProjectName = get_env_from_jenkins("JOB_NAME") # Jenkins构建项目名称
|
|
||||||
BUILD_URL = get_env_from_jenkins("BUILD_URL") # Jenkins构建项目URL
|
|
||||||
BUILD_NUMBER = get_env_from_jenkins("BUILD_NUMBER") # Jenkins构建编号
|
|
||||||
ALLURE_URL = BUILD_URL + 'allure/' # Jenkins构建的allure报告地址
|
|
||||||
|
|
||||||
|
|
||||||
class EnterpriseWechatNotification:
|
class EnterpriseWechatNotification:
|
||||||
|
@ -31,7 +17,6 @@ class EnterpriseWechatNotification:
|
||||||
# 企业微信群机器人的hook地址,一个机器人就一个,多个就定义多个,可以写死,也可以写在配置类中
|
# 企业微信群机器人的hook地址,一个机器人就一个,多个就定义多个,可以写死,也可以写在配置类中
|
||||||
self.hook_urls = hook_urls
|
self.hook_urls = hook_urls
|
||||||
self.header = {'Content-Type': 'application/json'}
|
self.header = {'Content-Type': 'application/json'}
|
||||||
self.pytest_result = ReportDataHandle.pytest_json_report_case_count()
|
|
||||||
|
|
||||||
def send_text(self, content, mentioned_mobile_list=None):
|
def send_text(self, content, mentioned_mobile_list=None):
|
||||||
"""
|
"""
|
||||||
|
@ -57,29 +42,12 @@ class EnterpriseWechatNotification:
|
||||||
else:
|
else:
|
||||||
raise ValueTypeError("手机号码列表必须是list类型.")
|
raise ValueTypeError("手机号码列表必须是list类型.")
|
||||||
|
|
||||||
def send_markdown(self, content=''):
|
def send_markdown(self, content):
|
||||||
"""
|
"""
|
||||||
发送markdown消息
|
发送markdown消息
|
||||||
:param content: markdown格式内容
|
:param content: markdown格式内容
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
content = f"""******用例执行结果统计******
|
|
||||||
> 项目名称:{ProjectName}
|
|
||||||
> 构件编号:#{BUILD_NUMBER}
|
|
||||||
> 测试环境:{ENV.name}
|
|
||||||
> 总用例数:<font color=\"info\">{self.pytest_result['total_case']}条</font>
|
|
||||||
> 通过用例数:<font color=\"info\">{self.pytest_result['pass_case']}条</font>
|
|
||||||
> 失败用例数:<font color=\"red\">{self.pytest_result['fail_case']}条</font>
|
|
||||||
> 报错用例数:<font color=\"red\">{self.pytest_result['error_case']}条</font>
|
|
||||||
> 跳过用例数:<font color=\"warning\">{self.pytest_result['skip_case']}条</font>
|
|
||||||
> 预期失败用例数:<font color=\"comment\">{self.pytest_result['xfail_case']}条</font>
|
|
||||||
> 预期通过用例数:<font color=\"comment\">{self.pytest_result['xpass_case']}条</font>
|
|
||||||
> 通过率:<font color=\"info\">{self.pytest_result['pass_rate']}%</font>
|
|
||||||
> 用例执行时长:<font color=\"info\">{self.pytest_result['case_duration']}s</font>
|
|
||||||
> 测试报告,点击查看>>[测试报告入口]({ALLURE_URL})
|
|
||||||
> 构建详情,点击查看>>[控制台入口]({BUILD_URL})
|
|
||||||
> {content}"""
|
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"msgtype": "markdown",
|
"msgtype": "markdown",
|
||||||
"markdown": {
|
"markdown": {
|
||||||
|
@ -130,5 +98,4 @@ class EnterpriseWechatNotification:
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
EnterpriseWechatNotification(
|
EnterpriseWechatNotification(
|
||||||
['hook_url']).send_markdown(
|
['hook_url']).send_markdown('<@汪杰>')
|
||||||
'<@汪杰>')
|
|
||||||
|
|
|
@ -6,8 +6,16 @@
|
||||||
# @project : SensoroApi
|
# @project : SensoroApi
|
||||||
|
|
||||||
from common.models import Environment
|
from common.models import Environment
|
||||||
|
from utils.jenkins_handle import ProjectName, BUILD_NUMBER, ALLURE_URL, BUILD_URL
|
||||||
|
from utils.reportdatahandle import ReportDataHandle
|
||||||
|
|
||||||
# 设置运行的环境变量
|
# 设置运行的环境变量
|
||||||
|
'''
|
||||||
|
开发环境:Environment.DEV
|
||||||
|
测试环境:Environment.TEST
|
||||||
|
生产环境:Environment.PROD
|
||||||
|
点军环境:Environment.DIANJUN
|
||||||
|
'''
|
||||||
ENV = Environment.TEST
|
ENV = Environment.TEST
|
||||||
|
|
||||||
# 设置是否需要发送邮件:Ture发送,False不发送
|
# 设置是否需要发送邮件:Ture发送,False不发送
|
||||||
|
@ -17,7 +25,70 @@ IS_SEND_EMAIL = False
|
||||||
IS_SEND_WECHAT = False
|
IS_SEND_WECHAT = False
|
||||||
|
|
||||||
# 设置是否开启debug日志
|
# 设置是否开启debug日志
|
||||||
LOG_DEBUG = False
|
LOG_DEBUG = True
|
||||||
|
|
||||||
# 设置是否开启控制台日志
|
# 设置是否开启控制台日志
|
||||||
LOG_CONSOLE = True
|
LOG_CONSOLE = True
|
||||||
|
|
||||||
|
# ------------------------------------ 邮件配置信息 ----------------------------------------------------#
|
||||||
|
|
||||||
|
# 发送邮件的相关配置信息
|
||||||
|
email_config = {
|
||||||
|
'mail_subject': '接口自动化测试报告', # 邮件标题
|
||||||
|
'sender_username': 'xxxxx@qq.com', # 发件人邮箱
|
||||||
|
'sender_password': 'ASDsdasda', # 发件人邮箱授权码
|
||||||
|
'receiver_mail_list': ['xxxxx@qq.com', ], # 收件人邮箱
|
||||||
|
'smtp_domain': 'smtp.exmail.qq.com', # 发送邮箱的域名
|
||||||
|
'smtp_port': 465, # 发送邮箱的端口号
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO:使用模板替换的方式替换该部分内容,否则此处会读取上次执行的报告
|
||||||
|
# 邮件通知内容
|
||||||
|
pytest_result = ReportDataHandle.pytest_json_report_case_count()
|
||||||
|
email_content = f"""
|
||||||
|
各位同事, 大家好:<br>
|
||||||
|
|
||||||
|
自动化用例于 <strong>{pytest_result["case_start_time"]}</strong> 开始运行,运行时长:<strong>{pytest_result['case_duration']}s</strong>, 目前已执行完成。<br>
|
||||||
|
---------------------------------------------------------------------------------------------------------------<br>
|
||||||
|
项目名称:<strong>{ProjectName}</strong> <br>
|
||||||
|
构件编号:<strong>#{BUILD_NUMBER}</strong><br>
|
||||||
|
项目环境:<strong>{ENV.name}</strong><br>
|
||||||
|
---------------------------------------------------------------------------------------------------------------<br>
|
||||||
|
执行结果如下:<br>
|
||||||
|
用例运行总数:<strong> {pytest_result['total_case']}条</strong><br>
|
||||||
|
通过用例个数(passed): <strong><font color="green" >{pytest_result['pass_case']}条</font></strong><br>
|
||||||
|
失败用例个数(failed): <strong><font color="red" >{pytest_result['fail_case']}条</font></strong><br>
|
||||||
|
报错用例个数(error): <strong><font color="orange" >{pytest_result['error_case']}条</font></strong><br>
|
||||||
|
跳过用例个数(skipped): <strong><font color="grey" >{pytest_result['skip_case']}条</font></strong><br>
|
||||||
|
预期失败用例个数(xfail): <strong><font color="grey" >{pytest_result['xfail_case']}条</font></strong><br>
|
||||||
|
预期通过用例个数(xpass): <strong><font color="grey" >{pytest_result['xpass_case']}条</font></strong><br>
|
||||||
|
通过率: <strong><font color="green" >{pytest_result['pass_rate']}%</font></strong><br>
|
||||||
|
测试报告,点击查看: <a href='{ALLURE_URL}'>[测试报告入口]</a><br>
|
||||||
|
构建详情,点击查看: <a href='{BUILD_URL}'>[控制台入口]</a><br>
|
||||||
|
|
||||||
|
**********************************<br>
|
||||||
|
附件为具体的测试报告,详细情况可下载附件查看, 非相关负责人员可忽略此消息。谢谢。
|
||||||
|
"""
|
||||||
|
|
||||||
|
# ------------------------------------ 企业微信相关配置 ----------------------------------------------------#
|
||||||
|
# 企业微信通知群聊
|
||||||
|
wechat_webhook_url = ["https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxxx"]
|
||||||
|
|
||||||
|
# 企业微信通知内容
|
||||||
|
wechat_content = f"""******用例执行结果统计******
|
||||||
|
> 项目名称:{ProjectName}
|
||||||
|
> 构件编号:#{BUILD_NUMBER}
|
||||||
|
> 测试环境:{ENV.name}
|
||||||
|
> 总用例数:<font color=\"info\">{pytest_result['total_case']}条</font>
|
||||||
|
> 通过用例数:<font color=\"info\">{pytest_result['pass_case']}条</font>
|
||||||
|
> 失败用例数:<font color=\"red\">{pytest_result['fail_case']}条</font>
|
||||||
|
> 报错用例数:<font color=\"red\">{pytest_result['error_case']}条</font>
|
||||||
|
> 跳过用例数:<font color=\"warning\">{pytest_result['skip_case']}条</font>
|
||||||
|
> 预期失败用例数:<font color=\"comment\">{pytest_result['xfail_case']}条</font>
|
||||||
|
> 预期通过用例数:<font color=\"comment\">{pytest_result['xpass_case']}条</font>
|
||||||
|
> 通过率:<font color=\"info\">{pytest_result['pass_rate']}%</font>
|
||||||
|
> 用例开始时间:<font color=\"info\">{pytest_result["case_start_time"]}</font>
|
||||||
|
> 用例执行时长:<font color=\"info\">{pytest_result['case_duration']}s</font>
|
||||||
|
> 测试报告,点击查看>>[测试报告入口]({ALLURE_URL})
|
||||||
|
> 构建详情,点击查看>>[控制台入口]({BUILD_URL})
|
||||||
|
> <@汪杰>"""
|
||||||
|
|
|
@ -7,31 +7,46 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# 当前项目的路径
|
# 当前项目的根路径
|
||||||
BASE_DIR = os.path.split(os.path.split(os.path.abspath(__file__))[0])[0]
|
BASE_DIR = os.path.split(os.path.split(os.path.abspath(__file__))[0])[0]
|
||||||
|
|
||||||
# common目录的路径
|
# common目录的路径
|
||||||
COMMON_DIR = os.path.join(BASE_DIR, 'common')
|
COMMON_DIR = os.path.join(BASE_DIR, 'common')
|
||||||
|
|
||||||
# configs目录的路径
|
# configs目录的路径
|
||||||
CONFIGS_DIR = os.path.join(BASE_DIR, 'configs')
|
CONFIGS_DIR = os.path.join(BASE_DIR, 'configs')
|
||||||
|
|
||||||
# datas目录的路径
|
# datas目录的路径
|
||||||
DATAS_DIR = os.path.join(BASE_DIR, 'datas')
|
DATAS_DIR = os.path.join(BASE_DIR, 'datas')
|
||||||
|
|
||||||
# pageApi目录的路径
|
# pageApi目录的路径
|
||||||
PAGE_API_DIR = os.path.join(BASE_DIR, 'pageApi')
|
PAGE_API_DIR = os.path.join(BASE_DIR, 'pageApi')
|
||||||
|
|
||||||
# testCase目录的路径
|
# testCase目录的路径
|
||||||
TEST_CASE_DIR = os.path.join(BASE_DIR, 'testCase')
|
TEST_CASE_DIR = os.path.join(BASE_DIR, 'testCase')
|
||||||
|
|
||||||
# utils目录的路径
|
# utils目录的路径
|
||||||
UTILS_DIR = os.path.join(BASE_DIR, 'utils')
|
UTILS_DIR = os.path.join(BASE_DIR, 'utils')
|
||||||
|
|
||||||
# outFiles目录的路径
|
# outFiles目录的路径
|
||||||
OUT_FILES_DIR = os.path.join(BASE_DIR, 'outFiles')
|
OUT_FILES_DIR = os.path.join(BASE_DIR, 'outFiles')
|
||||||
|
|
||||||
# logs目录的路径
|
# logs目录的路径
|
||||||
LOGS_DIR = os.path.join(OUT_FILES_DIR, 'logs')
|
LOGS_DIR = os.path.join(OUT_FILES_DIR, 'logs')
|
||||||
|
|
||||||
# pytest_report目录的路径
|
# pytest_report目录的路径
|
||||||
PYTEST_REPORT_DIR = os.path.join(OUT_FILES_DIR, 'pytest_report')
|
PYTEST_REPORT_DIR = os.path.join(OUT_FILES_DIR, 'pytest_report')
|
||||||
|
|
||||||
# pytest_result目录的路径
|
# pytest_result目录的路径
|
||||||
PYTEST_RESULT_DIR = os.path.join(OUT_FILES_DIR, 'pytest_result')
|
PYTEST_RESULT_DIR = os.path.join(OUT_FILES_DIR, 'pytest_result')
|
||||||
|
|
||||||
# allure_report目录的路径
|
# allure_report目录的路径
|
||||||
ALLURE_REPORT_DIR = os.path.join(OUT_FILES_DIR, 'allure_report')
|
ALLURE_REPORT_DIR = os.path.join(OUT_FILES_DIR, 'allure_report')
|
||||||
|
|
||||||
# screeShot目录的路径
|
# screeShot目录的路径
|
||||||
SCREENSHOT_DIR = os.path.join(OUT_FILES_DIR, 'screeShot')
|
SCREENSHOT_DIR = os.path.join(OUT_FILES_DIR, 'screeShot')
|
||||||
|
|
||||||
# Temp目录的路径
|
# Temp目录的路径
|
||||||
TEMP_DIR = os.path.join(OUT_FILES_DIR, 'Temp')
|
TEMP_DIR = os.path.join(OUT_FILES_DIR, 'Temp')
|
||||||
|
if not os.path.exists(TEMP_DIR):
|
||||||
|
os.makedirs(TEMP_DIR)
|
||||||
|
|
26
run.py
26
run.py
|
@ -17,11 +17,10 @@ from common.base_log import logger
|
||||||
from utils.command_parser import command_parser
|
from utils.command_parser import command_parser
|
||||||
from common.mail_sender import MailSender
|
from common.mail_sender import MailSender
|
||||||
from common.robot_sender import EnterpriseWechatNotification
|
from common.robot_sender import EnterpriseWechatNotification
|
||||||
from common.settings import IS_SEND_EMAIL, IS_SEND_WECHAT
|
from common.settings import IS_SEND_EMAIL, IS_SEND_WECHAT, wechat_webhook_url, wechat_content, email_content, \
|
||||||
from configs.dir_path_config import BASE_DIR, TEMP_DIR, ALLURE_REPORT_DIR, PYTEST_REPORT_DIR, CONFIGS_DIR, \
|
email_config
|
||||||
PYTEST_RESULT_DIR
|
from configs.dir_path_config import BASE_DIR, TEMP_DIR, PYTEST_REPORT_DIR, PYTEST_RESULT_DIR, ALLURE_REPORT_DIR
|
||||||
from utils.file_handle import FileHandle
|
from utils.file_handle import FileHandle
|
||||||
from utils.yaml_handle import YamlHandle
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
logger.info("""
|
logger.info("""
|
||||||
|
@ -45,9 +44,9 @@ if __name__ == '__main__':
|
||||||
'testCase/', # 执行用例的目录
|
'testCase/', # 执行用例的目录
|
||||||
'--alluredir', f'{TEMP_DIR}', '--clean-alluredir', # 先清空旧的alluredir目录,再将生成Allure原始报告需要的数据,并存放在 /Temp 目录
|
'--alluredir', f'{TEMP_DIR}', '--clean-alluredir', # 先清空旧的alluredir目录,再将生成Allure原始报告需要的数据,并存放在 /Temp 目录
|
||||||
f'--html={os.path.join(PYTEST_REPORT_DIR, "pytest_report.html")}', # 指定pytest-html报告的存放位置
|
f'--html={os.path.join(PYTEST_REPORT_DIR, "pytest_report.html")}', # 指定pytest-html报告的存放位置
|
||||||
|
'--self-contained-html', # 将css样式合并到pytest-html报告文件中,便于发送邮件
|
||||||
'--json-report', '--json-report-summary', # 生成简化版json报告
|
'--json-report', '--json-report-summary', # 生成简化版json报告
|
||||||
f'--json-report-file={os.path.join(PYTEST_RESULT_DIR, "pytest_result.json")}', # 指定json报告存放位置
|
f'--json-report-file={os.path.join(PYTEST_RESULT_DIR, "pytest_result.json")}', # 指定json报告存放位置
|
||||||
'--self-contained-html', # 将css样式合并到pytest-html报告文件中,便于发送邮件
|
|
||||||
'--capture=no', # 捕获stderr和stdout,这里是使pytest-html中失败的case展示错误日志,会导致case中的print不打印
|
'--capture=no', # 捕获stderr和stdout,这里是使pytest-html中失败的case展示错误日志,会导致case中的print不打印
|
||||||
# '-p', 'no:logging', # 表示禁用logging插件,使报告中不显示log信息,只会显示stderr和stdoyt信息,避免log和stderr重复。
|
# '-p', 'no:logging', # 表示禁用logging插件,使报告中不显示log信息,只会显示stderr和stdoyt信息,避免log和stderr重复。
|
||||||
'-p', 'no:sugar', # 禁用pytest-sugar美化控制台结果
|
'-p', 'no:sugar', # 禁用pytest-sugar美化控制台结果
|
||||||
|
@ -68,25 +67,22 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
# 发送企业微信群聊
|
# 发送企业微信群聊
|
||||||
if IS_SEND_WECHAT: # 判断是否需要发送企业微信
|
if IS_SEND_WECHAT: # 判断是否需要发送企业微信
|
||||||
EnterpriseWechatNotification(
|
EnterpriseWechatNotification(wechat_webhook_url).send_markdown(wechat_content)
|
||||||
[
|
|
||||||
'hook_url']).send_markdown(
|
|
||||||
"<@汪杰>")
|
|
||||||
|
|
||||||
# 发送邮件
|
# 发送邮件
|
||||||
if IS_SEND_EMAIL: # 判断是否需要发送邮件
|
if IS_SEND_EMAIL: # 判断是否需要发送邮件
|
||||||
file_path = PYTEST_REPORT_DIR + os.sep + 'pytest_report.html'
|
file_path = PYTEST_REPORT_DIR + os.sep + 'pytest_report.html'
|
||||||
with open(file_path, 'rb') as f:
|
# with open(file_path, 'rb') as f:
|
||||||
text_to_send = f.read()
|
# text_to_send = f.read()
|
||||||
|
|
||||||
config = YamlHandle(CONFIGS_DIR + os.sep + 'mail_config.yaml').read_yaml()
|
# config = YamlHandle(CONFIGS_DIR + os.sep + 'mail_config.yaml').read_yaml()
|
||||||
|
config = email_config
|
||||||
ms = MailSender(
|
ms = MailSender(
|
||||||
mail_subject=config['mail_subject'],
|
mail_subject=config['mail_subject'],
|
||||||
sender_mail_address=config['sender_mail_address'],
|
|
||||||
sender_username=config['sender_username'],
|
sender_username=config['sender_username'],
|
||||||
sender_password=config['sender_password'],
|
sender_password=config['sender_password'],
|
||||||
receiver_mail_list=config['receiver_mail_list'],
|
receiver_mail_list=config['receiver_mail_list'],
|
||||||
smtp_domain=config['smtp_domain'],
|
smtp_domain=config['smtp_domain'],
|
||||||
smtp_port=config['smtp_port'],
|
smtp_port=config['smtp_port'],
|
||||||
)
|
)
|
||||||
ms.attach_text(text_to_send).attach_file(file_path).send()
|
ms.attach_text(email_content).attach_file(file_path).send()
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# !/usr/bin/python
|
||||||
|
# -*- coding:utf-8 -*-
|
||||||
|
# @Time : 2023/9/8 19:13
|
||||||
|
# @Author : wangjie
|
||||||
|
# @File : jenkins_handle.py
|
||||||
|
# @project : SensoroApiAutoTest
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def get_env_from_jenkins(name, base=''):
|
||||||
|
"""从Jenkins中获取全局环境变量"""
|
||||||
|
return os.getenv(name) and os.getenv(name).strip() or base
|
||||||
|
|
||||||
|
|
||||||
|
ProjectName = get_env_from_jenkins("JOB_NAME") # Jenkins构建项目名称
|
||||||
|
BUILD_URL = get_env_from_jenkins("BUILD_URL") # Jenkins构建项目URL
|
||||||
|
BUILD_NUMBER = get_env_from_jenkins("BUILD_NUMBER") # Jenkins构建编号
|
||||||
|
ALLURE_URL = BUILD_URL + 'allure/' # Jenkins构建的allure报告地址
|
|
@ -8,6 +8,7 @@ import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from configs.dir_path_config import BASE_DIR, PYTEST_RESULT_DIR
|
from configs.dir_path_config import BASE_DIR, PYTEST_RESULT_DIR
|
||||||
|
from utils.time_utils import TimeUtil
|
||||||
|
|
||||||
|
|
||||||
class ReportDataHandle:
|
class ReportDataHandle:
|
||||||
|
@ -21,7 +22,7 @@ class ReportDataHandle:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def pytest_json_report_case_count():
|
def pytest_json_report_case_count():
|
||||||
"""统计pytest_json_report报告收集的case数量"""
|
"""统计pytest_json_report报告收集的case数量"""
|
||||||
with open(PYTEST_RESULT_DIR + os.sep+'pytest_result.json', 'r', encoding='utf-8') as f:
|
with open(PYTEST_RESULT_DIR + os.sep + 'pytest_result.json', 'r', encoding='utf-8') as f:
|
||||||
pytest_result = json.loads(f.read())
|
pytest_result = json.loads(f.read())
|
||||||
case_count = {}
|
case_count = {}
|
||||||
case_count["total_case"] = pytest_result['summary'].get("total", 0) # 用例总数
|
case_count["total_case"] = pytest_result['summary'].get("total", 0) # 用例总数
|
||||||
|
@ -40,6 +41,7 @@ class ReportDataHandle:
|
||||||
# 如果未运行用例,则成功率为 0.0
|
# 如果未运行用例,则成功率为 0.0
|
||||||
case_count["pass_rate"] = 0.0
|
case_count["pass_rate"] = 0.0
|
||||||
case_count["case_duration"] = round(pytest_result["duration"], 2) # 用例运行时间
|
case_count["case_duration"] = round(pytest_result["duration"], 2) # 用例运行时间
|
||||||
|
case_count["case_start_time"] = TimeUtil.unix_time_to_str(int('%.f' % pytest_result["created"])) # 用例开始时间
|
||||||
|
|
||||||
return case_count
|
return case_count
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue