# -*- coding: utf-8 -*-
|
"""
|
@File : message_template.py
|
@Time : 2023/11/21 17:29
|
@Author : geekbing
|
@LastEditTime : -
|
@LastEditors : -
|
@Description : 消息模板
|
"""
|
from typing import Dict
|
from django.conf import settings
|
import time
|
|
|
def parse_message(summary: Dict, **kwargs):
|
"""
|
解析消息模板
|
|
:param summary: 测试报告摘要
|
:param kwargs: 其他参数
|
:return:
|
"""
|
task_name = summary["task_name"]
|
rows_count = summary["stat"]["testsRun"]
|
pass_count = summary["stat"]["successes"]
|
fail_count = summary["stat"]["failures"]
|
error_count = summary["stat"]["errors"]
|
duration = "%.2fs" % summary["time"]["duration"]
|
report_id = summary["report_id"]
|
base_url = settings.IM_REPORT_SETTING.get("base_url")
|
port = settings.IM_REPORT_SETTING.get("port")
|
report_url = f"{base_url}:{port}/api/lunarlink/reports/{report_id}"
|
executed = rows_count
|
fail_rate = "{:.2%}".format(fail_count / executed)
|
case_count = kwargs.get("case_count")
|
|
return {
|
"task_name": task_name,
|
"duration": duration,
|
"case_count": case_count,
|
"pass_count": pass_count,
|
"error_count": error_count,
|
"fail_count": fail_count,
|
"fail_rate": fail_rate,
|
"report_url": report_url,
|
}
|
|
|
def email_msg_template(
|
task_name,
|
duration,
|
case_count,
|
pass_count,
|
error_count,
|
fail_count,
|
fail_rate,
|
report_url,
|
):
|
"""
|
定制邮件报告消息模板(高级优化版)
|
|
:param task_name: 任务名称
|
:param duration: 总耗时
|
:param case_count: 用例个数
|
:param pass_count: 成功接口个数
|
:param error_count: 异常接口个数
|
:param fail_count: 失败接口个数
|
:param fail_rate: 失败比例
|
:param report_url: 报告链接
|
:return: 邮件主题及 HTML 内容
|
"""
|
email_subject = f"【自动化测试报告】{task_name}"
|
email_content = f"""<!DOCTYPE html>
|
<html lang="zh-CN">
|
<head>
|
<meta charset="UTF-8">
|
<title>自动化测试报告</title>
|
<!-- 引入 Google 字体 -->
|
<link href="https://fonts.googleapis.com/css?family=Roboto:400,500,700&display=swap" rel="stylesheet">
|
<style>
|
body {{
|
margin: 0;
|
padding: 0;
|
background-color: #f5f7fa;
|
font-family: 'Roboto', sans-serif;
|
color: #333;
|
}}
|
.container {{
|
max-width: 700px;
|
margin: 40px auto;
|
background: #fff;
|
border-radius: 12px;
|
overflow: hidden;
|
box-shadow: 0 8px 24px rgba(0,0,0,0.1);
|
}}
|
.header {{
|
background: linear-gradient(135deg, #4facfe, #00f2fe);
|
padding: 30px;
|
text-align: center;
|
color: #fff;
|
}}
|
.header h1 {{
|
margin: 0;
|
font-size: 28px;
|
font-weight: 700;
|
}}
|
.header p {{
|
margin: 8px 0 0;
|
font-size: 16px;
|
}}
|
.content {{
|
padding: 30px 40px;
|
}}
|
.summary-grid {{
|
display: grid;
|
grid-template-columns: repeat(3, 1fr);
|
gap: 20px;
|
margin-top: 20px;
|
}}
|
.card {{
|
background: #f9fafc;
|
border-radius: 8px;
|
padding: 20px;
|
text-align: center;
|
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
|
}}
|
.card .label {{
|
font-size: 14px;
|
color: #777;
|
margin-bottom: 8px;
|
display: block;
|
}}
|
.card .value {{
|
font-size: 24px;
|
font-weight: 700;
|
}}
|
.value.success {{
|
color: #2ecc71;
|
}}
|
.value.error {{
|
color: #e74c3c;
|
}}
|
.value.warning {{
|
color: #f39c12;
|
}}
|
.report-btn {{
|
display: block;
|
width: 240px;
|
margin: 30px auto 0;
|
text-align: center;
|
padding: 15px;
|
background-color: #4a90e2;
|
color: #fff;
|
text-decoration: none;
|
border-radius: 6px;
|
font-weight: 500;
|
transition: background 0.3s ease;
|
}}
|
.report-btn:hover {{
|
background-color: #3b7dd8;
|
}}
|
.footer {{
|
text-align: center;
|
font-size: 12px;
|
color: #aaa;
|
padding: 20px;
|
background: #f0f2f5;
|
}}
|
@media (max-width: 768px) {{
|
.container {{
|
margin: 20px;
|
}}
|
.summary-grid {{
|
grid-template-columns: 1fr 1fr;
|
}}
|
}}
|
@media (max-width: 480px) {{
|
.summary-grid {{
|
grid-template-columns: 1fr;
|
}}
|
}}
|
</style>
|
</head>
|
<body>
|
<div class="container">
|
<div class="header">
|
<h1>自动化测试报告</h1>
|
<p>{task_name}</p>
|
</div>
|
<div class="content">
|
<div class="summary-grid">
|
<div class="card">
|
<span class="label">总耗时</span>
|
<span class="value">{duration}</span>
|
</div>
|
<div class="card">
|
<span class="label">用例个数</span>
|
<span class="value">{case_count}</span>
|
</div>
|
<div class="card">
|
<span class="label">失败比例</span>
|
<span class="value warning">{fail_rate}</span>
|
</div>
|
<div class="card">
|
<span class="label">成功接口</span>
|
<span class="value success">{pass_count}</span>
|
</div>
|
<div class="card">
|
<span class="label">异常接口</span>
|
<span class="value error">{error_count}</span>
|
</div>
|
<div class="card">
|
<span class="label">失败接口</span>
|
<span class="value error">{fail_count}</span>
|
</div>
|
</div>
|
<a href="{report_url}" class="report-btn">点击查看详细报告</a>
|
</div>
|
<div class="footer">
|
本邮件由系统自动发出,请勿回复
|
</div>
|
</div>
|
</body>
|
</html>
|
"""
|
return {
|
"subject": email_subject,
|
"html_message": email_content,
|
}
|
|
|
def qy_msg_template(
|
task_name,
|
duration,
|
case_count,
|
pass_count,
|
error_count,
|
fail_count,
|
fail_rate,
|
report_url,
|
msg_type: str = "markdown",
|
):
|
"""
|
定制企业微信消息模板
|
|
:param task_name:
|
:param duration:
|
:param case_count:
|
:param pass_count:
|
:param error_count:
|
:param fail_count:
|
:param fail_rate:
|
:param report_url:
|
:param msg_type:
|
:return:
|
"""
|
if msg_type == "markdown":
|
msg_template = {"msgtype": "markdown", "markdown": {"content": ""}}
|
content = f"""<font color=\'warning\'>**接口自动化测试报告**</font> \n
|
>任务名称: <font color=\'comment\'>{task_name}</font>
|
>总共耗时: <font color=\'comment\'>{duration}</font>
|
>用例个数: <font color=\'comment\'>{case_count}</font>
|
>成功接口: <font color=\'info\'>**{pass_count}**</font>
|
>异常接口: <font color=\'comment\'>**{error_count}**</font>
|
>失败接口: <font color=\'comment\'>**{fail_count}**</font>
|
>失败比例: <font color=\'comment\'>**{fail_rate}**</font>
|
>测试报告: <font color=\'comment\'>[点击查看]({report_url})</font>"""
|
msg_template["markdown"]["content"] = content
|
return msg_template
|
text = f" 任务名称: {task_name}\n 总共耗时: {duration}\n 成功接口: {pass_count}个\n 异常接口: {error_count}个\n 失败接口: {fail_count}个\n 失败比例: {fail_rate}\n 查看详情: {report_url}"
|
return text
|
|
def dd_msg_template(
|
task_name,
|
duration,
|
case_count,
|
pass_count,
|
error_count,
|
fail_count,
|
fail_rate,
|
report_url,
|
msg_type: str = "markdown",
|
creator=None,
|
updater=None,
|
):
|
"""
|
定制钉钉消息模板:包含自动评价、图标提示、markdown美观布局
|
|
:param task_name: 任务名称
|
:param duration: 总耗时
|
:param case_count: 用例个数
|
:param pass_count: 成功接口个数
|
:param error_count: 异常接口个数
|
:param fail_count: 失败接口个数
|
:param fail_rate: 失败比例(字符串或百分比)
|
:param report_url: 报告链接
|
:param msg_type: 消息类型,默认 markdown
|
:return: 钉钉消息内容(字典格式)
|
"""
|
|
# 安全转换失败比例
|
try:
|
fr = float(str(fail_rate).strip().replace("%", "").replace("%", ""))
|
except Exception:
|
fr = 0.0
|
|
# 状态图标
|
status_icon = "✅" if fail_count == 0 and error_count == 0 else ("⚠️" if fail_count == 0 else "❌")
|
|
# 自动评价等级
|
if error_count == 0 and fail_count == 0:
|
evaluation = "测试结果优秀"
|
evaluation_icon = "🟢"
|
elif fr <= 5:
|
evaluation = "测试结果良好"
|
evaluation_icon = "🟡"
|
elif fr <= 10:
|
evaluation = "测试结果一般"
|
evaluation_icon = "🟠"
|
else:
|
evaluation = "测试结果严重异常"
|
evaluation_icon = "🔴"
|
|
if msg_type == "markdown":
|
content = (
|
f"## {status_icon} **接口自动化测试完成通知**\n\n"
|
f"### 📌 任务名称:**{task_name}**\n"
|
f"### 📈 自动评价:{evaluation_icon} `{evaluation}`\n\n"
|
f"> ⏱️ **总耗时:** {duration} \n"
|
f"> 📊 **执行用例数:** {case_count} \n"
|
f"> ✅ **成功接口数:** {pass_count} \n"
|
f"> ⚠️ **异常接口数:** {error_count} \n"
|
f"> ❌ **失败接口数:** {fail_count} \n"
|
f"> 📉 **失败比例:** {fail_rate} \n\n"
|
f"> 👤 **创建人:** {creator if creator else '未记录'} \n" # 新增创建人显示
|
f"> ✏️ **更新人:** {updater if updater else '未记录'} \n\n" # 新增更新人显示
|
f"🔗 [👉 点击查看详细报告]({report_url})\n\n"
|
f"📬 详细内容也可通过邮件查看。\n\n"
|
"---\n"
|
"如有异常,请及时处理!🎉"
|
)
|
return {"msgtype": "markdown", "markdown": {"content": content}}
|
|
else:
|
# 普通 text 消息 fallback
|
content = (
|
f"{status_icon} 接口自动化测试完成通知\n"
|
f"任务名称:{task_name}\n"
|
f"自动评价:{evaluation_icon} {evaluation}\n"
|
f"总耗时:{duration}\n"
|
f"执行用例数:{case_count}\n"
|
f"成功接口数:{pass_count}\n"
|
f"异常接口数:{error_count}\n"
|
f"失败接口数:{fail_count}\n"
|
f"失败比例:{fail_rate}\n"
|
f"创建人:{creator}\n"
|
f"更新人:{updater}\n"
|
f"报告地址:{report_url}\n"
|
f"详细内容请查看邮件,如有异常,请及时处理!。"
|
)
|
return {"msgtype": "text", "text": {"content": content}}
|