From 2e86d2ce2734608cf04cd4d3bebfa3556feccf43 Mon Sep 17 00:00:00 2001 From: guke Date: Fri, 7 Aug 2026 18:05:39 +0800 Subject: [PATCH] =?UTF-8?q?test(compare-alert):=20=E8=A1=A5=20review=20?= =?UTF-8?q?=E7=BC=BA=E5=8F=A3=E2=80=94=E2=80=94continue=20=E5=88=86?= =?UTF-8?q?=E6=94=AF=E5=9B=9E=E5=BD=92=20+=20<1s=20=E8=BE=B9=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - read_stuck_points 最忙平台末帧损坏 → last fallthrough 到干净平台 (重构最险分支的回归测试,原只在一次性验证脚本里) - _fmt_last round 边界:500→<1s、999→停留1s - continue 注释点明与旧版 _platform_stuck→None 等价 Co-Authored-By: Claude Opus 4.8 (1M context) --- app/services/trace_stuck.py | 4 +++- tests/test_compare_alert_stuck_worker.py | 7 +++++++ tests/test_trace_stuck.py | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/services/trace_stuck.py b/app/services/trace_stuck.py index 943bbf9..63e5cd1 100644 --- a/app/services/trace_stuck.py +++ b/app/services/trace_stuck.py @@ -136,7 +136,9 @@ def read_stuck_points(trace_dir: Path, *, threshold: int, max_tail: int) -> Stuc any_frames = True seg = _last_segment(step_files, max_tail) # 每平台只扫一次末段 if seg is None: - continue # 末帧抠不出:不判卡死、也不当末帧候选 + # 末帧抠不出:整段跳过(不判卡死、也不当末帧候选)——与旧版 _platform_stuck→None + # + 独立 _read_head(末帧)→ps None 两处一并跳过等价(旧版两者都 key off 末帧) + continue ps, pg, count, dwell_ms = seg if count >= threshold: points.append(StuckPoint(pdir.name, ps, count, dwell_ms, detected_page=pg)) diff --git a/tests/test_compare_alert_stuck_worker.py b/tests/test_compare_alert_stuck_worker.py index 0cab10b..6a21822 100644 --- a/tests/test_compare_alert_stuck_worker.py +++ b/tests/test_compare_alert_stuck_worker.py @@ -167,6 +167,13 @@ def test_fmt_last_sub_second(): sp = StuckPoint("meituan", "checkout", frames=480, detected_page="checkout_page", dwell_ms=300) assert _fmt_last(sp) == "美团·结算·checkout_page 停留<1s" + # <1s 阈值边界:round(500/1000)=0 → <1s;round(999/1000)=1 → 停留1s + sp500 = StuckPoint("meituan", "checkout", frames=480, + detected_page="checkout_page", dwell_ms=500) + assert _fmt_last(sp500) == "美团·结算·checkout_page 停留<1s" + sp999 = StuckPoint("meituan", "checkout", frames=480, + detected_page="checkout_page", dwell_ms=999) + assert _fmt_last(sp999) == "美团·结算·checkout_page 停留1s" def test_fmt_last_without_dwell(): diff --git a/tests/test_trace_stuck.py b/tests/test_trace_stuck.py index 2a3a49b..25518c2 100644 --- a/tests/test_trace_stuck.py +++ b/tests/test_trace_stuck.py @@ -222,3 +222,21 @@ def test_read_stuck_points_last_has_dwell(tmp_path): assert res.last.pipeline_step == "checkout" assert res.last.frames == 5 # 总帧数 assert res.last.dwell_ms == 4000 # 末段 :00→:04 = 4s + + +def test_read_stuck_points_last_falls_through_when_busiest_last_frame_corrupt(tmp_path): + # 最忙平台末帧损坏(抠不出环节)→ _last_segment=None → 整段跳过(重构 continue 分支) + # → last 落到次忙的干净平台。锁定 read_stuck_points 重构的最险等价分支。 + m = tmp_path / "meituan" + m.mkdir() + for i in range(7): + _frame(m, i, "add_one_dish", "menu") + (m / "step_007.json").write_bytes(b'{"pipeline_step": "add\xff') # 末帧截断 UTF-8 + e = tmp_path / "eleme" + for i in range(3): + _frame(e, i, "enter_store", "store") + res = read_stuck_points(tmp_path, threshold=15, max_tail=40) + assert res.points == [] # 谁都没卡死 + assert res.last is not None + assert res.last.platform == "eleme" # 最忙的 meituan(8帧)末帧损坏被跳过,last 落到 eleme + assert res.last.pipeline_step == "enter_store"