From c6fda262dbef9a31cdb14ac752efc76c0c741401 Mon Sep 17 00:00:00 2001 From: butubb <1422726308@qq.com> Date: Sun, 13 Sep 2026 11:05:44 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=9B=9E=E5=BD=92=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E4=B8=A4=E5=A4=84"=E8=87=AA=E5=B7=B1=E5=9D=8F=E6=8E=89"?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E2=80=94=E2=80=94GBK=20=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E5=8F=B0=E5=B4=A9=E5=9C=A8=E6=B1=87=E6=80=BB=E3=80=81?= =?UTF-8?q?=E5=86=99=E6=AD=BB=E8=BF=87=E6=9C=9F=E8=AE=BE=E5=A4=87=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 MySQL dev 库上跑全量回归时暴露: 1. 汇总里的 ⚠/❌/✅ 在 Windows GBK 控制台抛 UnicodeEncodeError,而且崩在打印 汇总那一步 —— 探测其实全跑完了,看起来却像脚本挂了(stdout 重设为 UTF-8) 2. `100.100.10.11:5555` 是 Tailscale 时代的地址,设备早换了:路径参数与两个关键 POST 都拿它当目标 → 每次回归要等好几轮 30s adb connect 超时,还误报 "关键 POST 测试步骤(wait) 失败"。改为**运行期从设备池挑一台启用设备** 结果(对 MySQL dev 库):99 项检查全通过(38 GET + 60 写探测 + 7 关键业务), 仅 3 条 Tailscale 未配置的业务提示。 --- scripts/regression_test.py | 49 +++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/scripts/regression_test.py b/scripts/regression_test.py index a9afb21..efec4ec 100644 --- a/scripts/regression_test.py +++ b/scripts/regression_test.py @@ -21,6 +21,14 @@ import signal # 项目根加入 sys.path(脚本在 scripts/ 下运行,保证可 import web_server/config) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +# Windows 控制台默认 GBK:汇总里的 ⚠/❌/✅ 会抛 UnicodeEncodeError, +# 而且崩在"打印汇总"这一步 —— 看起来像脚本挂了、其实探测已经全跑完 +try: + sys.stdout.reconfigure(encoding="utf-8", errors="replace") + sys.stderr.reconfigure(encoding="utf-8", errors="replace") +except Exception: + pass + # 测试模式:禁用 cron 调度器(否则 test_client 会按 DB 里的任务 cron 真跑任务, # 干扰回归/占用设备——实测 ocr关键字任务每 30 分钟触发导致回归超时) os.environ["DISABLE_SCHEDULER"] = "1" @@ -59,14 +67,33 @@ _SKIP_PREFIXES = ( "/api/screen/stream", "/api/screen/thumb", "/api/uiauto/screenshot", "/api/device/screenshot", ) +# 测试用的目标设备:运行期从设备池里挑一台真实的(占位串是池空时的兜底)。 +# 以前这里写死 Tailscale 时代的 100.100.10.11:5555,设备早换了 → 每次回归都要等 +# 好几轮 30s 的 adb connect 超时,还会误报"关键 POST 失败"。 +_TEST_SERIAL = "100.100.10.11:5555" +_SERIAL_PH = "@SERIAL@" + + +def _pick_serial(): + """从设备池里挑一台启用的设备当测试目标(池空则返回占位串)。""" + try: + from core.models import Device, db as _db + with app.app_context(): + d = _db.session.query(Device).filter(Device.enabled.is_(True)).order_by( + Device.serial).first() + return d.serial if d else _TEST_SERIAL + except Exception: + return _TEST_SERIAL + + # 关键业务 POST:用真实参数验证(这些覆盖了核心链路) _KEY_POSTS = [ ("一键亮屏", "/api/device/screen_all", {"mode": "on"}), ("一键息屏", "/api/device/screen_all", {"mode": "off"}), ("剪贴板注入", "/api/tools/clipboard/set", - {"serials": ["100.100.10.11:5555"], "text": "回归测试"}), + {"serials": [_SERIAL_PH], "text": "回归测试"}), ("测试步骤(wait)", "/api/steps/test", - {"serial": "100.100.10.11:5555", + {"serial": _SERIAL_PH, "step": {"type": "wait", "label": "等待", "params": {"max": 1, "min": 1, "probability": 100}}}), ("adb 终端执行", "/api/adb/cmd", {"cmd": "adb devices"}), ("adb 红线拦截", "/api/adb/cmd", {"cmd": "adb kill-server"}), @@ -76,10 +103,21 @@ _KEY_POSTS = [ _EXPECT_REJECT = {"/api/adb/cmd"} +def _sub_serial(obj): + """把请求体里的 @SERIAL@ 占位替换成运行期选定的设备串(支持嵌套 list/dict)。""" + if isinstance(obj, str): + return _TEST_SERIAL if obj == _SERIAL_PH else obj + if isinstance(obj, list): + return [_sub_serial(x) for x in obj] + if isinstance(obj, dict): + return {k: _sub_serial(v) for k, v in obj.items()} + return obj + + def _fill_path_params(rule): """把路由路径参数 替换为测试值(serial 用真实设备)。""" url = rule - url = url.replace("", "100.100.10.11:5555") + url = url.replace("", _TEST_SERIAL) url = url.replace("", "x") url = url.replace("", "x") url = url.replace("", "x") @@ -158,7 +196,12 @@ def main(): print(f"写操作路由: {len(write_rules)} 个(空 body 探测)") # ========== 3. 关键业务 POST(真实参数) ========== + global _TEST_SERIAL + _TEST_SERIAL = _pick_serial() + print(f"测试目标设备: {_TEST_SERIAL}") for name, url, body in _KEY_POSTS: + # 占位符换成运行期挑到的真实设备(含嵌套列表) + body = _sub_serial(body) try: r = c.post(url, json=body, headers=H) j = r.get_json() if r.is_json else None