feat(report): resolve Chinese test names from docstring in cn report

Test case docstring 【P0】 prefix is stripped for display.
报告中的用例名现在显示为: 司机APP接单到管理端核算打款完整流程
This commit is contained in:
xst
2026-07-23 16:50:47 +08:00
parent f287c93cce
commit d1710cfcd6
2 changed files with 49 additions and 6 deletions
+42 -5
View File
@@ -73,7 +73,7 @@ def shipper_ios_config(config):
# ═══════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════
def pytest_sessionfinish(session): def pytest_sessionfinish(session):
"""测试会话结束后,从 junit.xml 生成一份简洁的中文 HTML 报告。""" """测试会话结束后,生成中文 HTML 报告。"""
from datetime import datetime from datetime import datetime
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
@@ -99,19 +99,56 @@ def pytest_sessionfinish(session):
for suite in root: for suite in root:
for case in suite: for case in suite:
total += 1 total += 1
name = case.attrib.get("name", "") func_name = case.attrib.get("name", "")
cn_name = _resolve_cn_name(session, func_name)
time_elapsed = case.attrib.get("time", "0") time_elapsed = case.attrib.get("time", "0")
failure = case.find("failure") failure = case.find("failure")
if failure is not None: if failure is not None:
failed += 1 failed += 1
msg = failure.attrib.get("message", "")[:300] msg = failure.attrib.get("message", "")[:300]
cases.append((name, "失败", time_elapsed, msg)) cases.append((cn_name, "失败", time_elapsed, msg))
elif case.find("skipped") is not None: elif case.find("skipped") is not None:
skipped += 1 skipped += 1
cases.append((name, "跳过", time_elapsed, "")) cases.append((cn_name, "跳过", time_elapsed, ""))
else: else:
passed += 1 passed += 1
cases.append((name, "通过", time_elapsed, "")) cases.append((cn_name, "通过", time_elapsed, ""))
pass_rate = (passed / total * 100) if total > 0 else 0
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
html = _build_cn_report_html(total, passed, failed, skipped, pass_rate, cases, now)
(report_dir / "report_cn.html").write_text(html, encoding="utf-8")
def _resolve_cn_name(session, func_name: str) -> str:
"""从 pytest session 中查找函数的中文 display_name。
策略:
1) 查找测试函数上的 display_name 属性 (test_xxx.display_name = "中文名")
2) 使用 item.name (含 nodeid),提取函数名并取 docstring 第一行去掉 【P0】 前缀
3) 兜底返回原始函数名
"""
for item in session.items:
item_func_name = getattr(item, "originalname", None) or item.name.rsplit("::", 1)[-1]
if item_func_name == func_name:
test_cls = item.cls if hasattr(item, "cls") else None
test_func = getattr(test_cls, item_func_name, None) if test_cls else None
# 策略1: display_name 属性
if test_func and hasattr(test_func, "display_name"):
return test_func.display_name
# 策略2: docstring 第一行
doc = (test_func.__doc__ or "") if test_func else ""
if doc:
first_line = doc.strip().split("\n")[0].strip()
if first_line.startswith(""):
idx = first_line.find("")
if idx > 0:
first_line = first_line[idx + 1:]
if first_line and len(first_line) > 2:
return first_line
break
return func_name
pass_rate = (passed / total * 100) if total > 0 else 0 pass_rate = (passed / total * 100) if total > 0 else 0
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@@ -40,6 +40,11 @@ class TestDriverToSettlement:
- 司机 APP: 货源浏览、接单、装货(含拍照上传、合同确认)、卸货(含拍照上传) - 司机 APP: 货源浏览、接单、装货(含拍照上传、合同确认)、卸货(含拍照上传)
- Web 管理端: 运费核算、运单审核、垫资-财务打款(含验证码)、垫资-货主打款 - Web 管理端: 运费核算、运单审核、垫资-财务打款(含验证码)、垫资-货主打款
- 数据库: SQL 更新风控状态(运费核算查询无数据时自动执行) - 数据库: SQL 更新风控状态(运费核算查询无数据时自动执行)
用例ID: TC-D2S-001
用例名称: 司机APP接单到管理端核算打款完整流程
优先级: P0
标签: cross_end, smoke
""" """
def test_driver_to_settlement_full_flow( def test_driver_to_settlement_full_flow(
@@ -52,7 +57,8 @@ class TestDriverToSettlement:
cross_end_context, cross_end_context,
logger, logger,
): ):
"""验证从司机 APP 接单到管理端核算打款完整跨端业务流程""" """【P0】司机APP接单到管理端核算打款完整流程"""
logger.info("=" * 60) logger.info("=" * 60)
logger.info("跨端 E2E: 司机APP → 管理端核算打款 完整流程开始") logger.info("跨端 E2E: 司机APP → 管理端核算打款 完整流程开始")
logger.info("=" * 60) logger.info("=" * 60)