From d1710cfcd696d07559177bf36be0f84f1abcdd9d Mon Sep 17 00:00:00 2001 From: xst Date: Thu, 23 Jul 2026 16:50:47 +0800 Subject: [PATCH] feat(report): resolve Chinese test names from docstring in cn report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test case docstring 【P0】 prefix is stripped for display. 报告中的用例名现在显示为: 司机APP接单到管理端核算打款完整流程 --- tests/conftest.py | 47 +++++++++++++++++-- .../tests/test_driver_to_settlement.py | 8 +++- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f4c6c04..2a5d748 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -73,7 +73,7 @@ def shipper_ios_config(config): # ═══════════════════════════════════════════════════════════════════ def pytest_sessionfinish(session): - """测试会话结束后,从 junit.xml 生成一份简洁的中文 HTML 报告。""" + """测试会话结束后,生成中文 HTML 报告。""" from datetime import datetime from xml.etree import ElementTree as ET @@ -99,19 +99,56 @@ def pytest_sessionfinish(session): for suite in root: for case in suite: 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") failure = case.find("failure") if failure is not None: failed += 1 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: skipped += 1 - cases.append((name, "跳过", time_elapsed, "")) + cases.append((cn_name, "跳过", time_elapsed, "")) else: 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 now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") diff --git a/tests/cross_end/tests/test_driver_to_settlement.py b/tests/cross_end/tests/test_driver_to_settlement.py index c6eb738..562690a 100644 --- a/tests/cross_end/tests/test_driver_to_settlement.py +++ b/tests/cross_end/tests/test_driver_to_settlement.py @@ -40,6 +40,11 @@ class TestDriverToSettlement: - 司机 APP: 货源浏览、接单、装货(含拍照上传、合同确认)、卸货(含拍照上传) - Web 管理端: 运费核算、运单审核、垫资-财务打款(含验证码)、垫资-货主打款 - 数据库: SQL 更新风控状态(运费核算查询无数据时自动执行) + + 用例ID: TC-D2S-001 + 用例名称: 司机APP接单到管理端核算打款完整流程 + 优先级: P0 + 标签: cross_end, smoke """ def test_driver_to_settlement_full_flow( @@ -52,7 +57,8 @@ class TestDriverToSettlement: cross_end_context, logger, ): - """验证从司机 APP 接单到管理端核算打款的完整跨端业务流程。""" + """【P0】司机APP接单到管理端核算打款完整流程""" + logger.info("=" * 60) logger.info("跨端 E2E: 司机APP → 管理端核算打款 完整流程开始") logger.info("=" * 60)