Files
ykxmz/_tests/test_double_click_window.py
xmz7891 fc61dad0a3 补两个自检失败:build_exe.ps1 丢 BOM + run_agent 用了未导入的 time
全量回归只剩这两项红,都是我这几步引入的:

1. 编码审计:build_exe.ps1 缺 UTF-8 BOM
   我用 edit 工具改它时把 BOM 丢了。PowerShell 5.1 会按 GBK 读,
   里面的中文注释会变乱码。

2. Python 静态检查:run_agent.py:760 undefined name 'time'
   我在 _restart_background 里用了 time.sleep,但 run_agent.py
   模块级没有 import time(原来只有 run_silent 里局部 import)。
   补上之后顺手在注释里记一笔:pyflakes 这一关是有用的。

顺带:test_double_click_window.py 的注释里我原样写了两个
U+FFFD 替换字符当例子,被编码审计当成乱码 —— 改成用文字描述。

现在全量回归 41 个阶段全部通过。
2026-10-07 21:50:00 +08:00

131 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
r'''验证「双击 exe 会打开设置窗口」。
== 为什么要专门测这个 ==
这条路上踩了两个坑,而且**都是静默失败**(用户只看到"双击没反应"):
1. run_agent.py 的 main() 里,装完之后无参数直接 run_silent
-> 什么都不弹(代码层面的行为问题)
2. 改成弹窗口之后,PyInstaller 的 --hidden-import 里没有 lanremote.ui
-> exe 里根本没有 tkinter 那套代码,一跑就
ModuleNotFoundError,进程立刻退出(打包层面的问题)
第 2 个尤其阴:**源码跑得好好的,只有打包出来的 exe 才会崩**。
所以这个测试必须针对**打包好的 exe** 跑,不能只跑源码。
'''
from __future__ import annotations
import json
import subprocess
import sys
import tempfile
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
EXE = ROOT / "dist_exe" / "ykxmz" / "ykxmz.exe"
passed = 0
failed = 0
def check(name, ok, detail=""):
global passed, failed
if ok:
passed += 1
print(" [PASS] " + name)
else:
failed += 1
print(" [FAIL] " + name + ((" —— " + str(detail)) if detail else ""))
def main() -> int:
print("=" * 58)
print(" 双击 exe 要能弹出设置窗口")
print("=" * 58)
check("打包好的 exe 存在", EXE.is_file(), EXE)
if not EXE.is_file():
return 1
work = Path(tempfile.mkdtemp(prefix="uiwin_"))
data = work / "data"
data.mkdir(parents=True, exist_ok=True)
# 造一个"已经装好"的配置 —— 这正是用户双击时的状态
(data / "settings.json").write_text(json.dumps({
"port": 8765, "server_name": "TEST-PC", "setup_done": True,
"allow_new_pairing": True, "pairing_code": "123456",
"pairing_created": 0, "relay_url": "",
}, ensure_ascii=False, indent=2), encoding="utf-8")
import os
env = dict(os.environ)
env["YKXMZ_DATA"] = str(data)
env["YKXMZ_LOCK_PORT"] = "19931" # 避开用户自己的实例
print(" ── 启动 exe(无参数)──")
out = open(work / "out.txt", "wb")
proc = subprocess.Popen([str(EXE)], env=env, cwd=str(EXE.parent),
stdout=out, stderr=subprocess.STDOUT)
time.sleep(12)
if proc.poll() is not None:
out.close()
text = (work / "out.txt").read_text(encoding="utf-8", errors="replace")
check("进程没有立刻退出", False,
"退出码 %s;输出:%s" % (proc.returncode, text[-400:]))
# 特别指出 hiddenimports 这个坑
if "lanremote.ui" in text or "No module named" in text:
print(" ↑ 这就是 --hidden-import 漏了 lanremote.ui 的典型症状")
return 1
check("进程活着(没崩)", True)
# 有没有窗口:让 PowerShell 把标题**写进文件**再读。
# ⚠ 不能直接读 stdout —— Windows 控制台默认不是 UTF-8,
# 中文标题读出来是两个替换字符(这里不写出来,免得编码审计
# 把它们当成乱码报),于是"标题里带设置"这条会假失败。
try:
title_file = work / "title.txt"
subprocess.run(
["powershell", "-NoProfile", "-Command",
"[Console]::OutputEncoding=[System.Text.Encoding]::UTF8; "
"(Get-Process -Id %d).MainWindowTitle | "
"Set-Content -Encoding UTF8 -Path '%s'"
% (proc.pid, str(title_file).replace("'", "''"))],
capture_output=True, timeout=20)
title = ""
if title_file.is_file():
title = title_file.read_text(encoding="utf-8-sig").strip()
except Exception as exc: # noqa: BLE001
title = ""
print(" (读窗口标题失败:%s)" % exc)
print(" 窗口标题: %r" % title)
check("弹出了窗口(MainWindowTitle 非空)", bool(title),
"标题是空的 —— 窗口没弹出来")
if title:
check("标题里带「设置」", "设置" in title, title)
# 收尾
try:
proc.terminate()
proc.wait(timeout=6)
except Exception: # noqa: BLE001
try:
proc.kill()
except Exception: # noqa: BLE001
pass
out.close()
print()
print("=" * 58)
print(" 通过 %d 项,失败 %d 项" % (passed, failed))
return 0 if failed == 0 else 1
if __name__ == "__main__":
sys.exit(main())