hyb
2025-05-14 87453ffd761425b9f363a09a0f8fe07d770cb325
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# -*- 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}}