Move project test environments into the workspace

This commit is contained in:
2026-10-01 21:48:49 +08:00
parent f011d8357d
commit c2756ca4d6
23 changed files with 834 additions and 6 deletions
@@ -8,6 +8,8 @@ WiFi 加速与回退专项见 [WiFi 传输测试](WiFi传输测试.md),必须
远端联调脚本在电脑端使用 `requirements-host.txt` 的 Paramiko;它不属于核桃派离线安装依赖,不能加入设备端 `requirements-dev.txt` 或 OTA wheelhouse。
项目 SSH 环境、独立测试 SDK、AVD 和私有主机密钥统一放在仓库内被忽略的本机 `.local/`,不再写入全局工具目录。复建、版本锁定与中文路径模拟器入口见 [本机环境说明](../../../测试相关资料/如何测试/本机测试环境/README.md)。SSH 用其中 `.local/ssh/venv/Scripts/python.exe` 运行本目录脚本;凭据/登记门禁不变。普通 UI 使用 `local_env.py build-ui android` 和 `ui-smoke android` 做定向验证,不涉及真机或核桃派。
## 1. 门禁
- 用户授权主测试机可安装覆盖本 App、清理 App 测试数据、操作权限及蓝牙;自动测试点击使用 root,也不操作其他应用数据。
@@ -0,0 +1,12 @@
"""Workspace-owned private host-test state; importing this performs no I/O."""
from pathlib import Path
ROOT = Path(__file__).resolve().parents[3]
LOCAL = ROOT / '测试相关资料/如何测试/本机测试环境/.local'
PRIVATE = LOCAL / 'private'
SSH_KNOWN_HOSTS = PRIVATE / 'qms-mobile-known_hosts'
def private_directory():
PRIVATE.mkdir(parents=True, exist_ok=True)
return PRIVATE
@@ -7,6 +7,7 @@ from pathlib import Path
import re
import paramiko
from local_test_paths import SSH_KNOWN_HOSTS
ROOT = Path(__file__).resolve().parents[3]
@@ -23,7 +24,7 @@ def connect():
host = fields["IP"].strip()
port_match = re.search(r"(?:^|\s)-p\s+(\d+)", fields["SSH"])
port = int(port_match.group(1)) if port_match else 22
trust = Path.home() / ".codex-tools/tmp/qms-mobile-known_hosts"
trust = SSH_KNOWN_HOSTS
trust.parent.mkdir(parents=True, exist_ok=True)
client = paramiko.SSHClient()
if trust.exists():
@@ -321,7 +321,8 @@ def main() -> int:
raise RuntimeError("当前设备地址不是电脑热点网段")
import paramiko
keys = paramiko.HostKeys()
keys.load(str(Path.home() / ".codex-tools/tmp/qms-mobile-known_hosts"))
from local_test_paths import SSH_KNOWN_HOSTS
keys.load(str(SSH_KNOWN_HOSTS))
expected_key = next(iter(keys.lookup(fields["IP"].strip()).values()))
board = connect_at(current_ip, expected_key, fields)
original, backup_root, backup_unit = resume_configuration(board, fields)
@@ -355,8 +356,8 @@ def main() -> int:
"static_address": static_address, "hotspot_gateway": hotspot["gateway"],
"wrong_password": "qms-invalid-password-2026",
}
private_tmp = Path.home() / ".codex-tools/tmp"
private_tmp.mkdir(parents=True, exist_ok=True)
from local_test_paths import private_directory
private_tmp = private_directory()
path = private_tmp / ("qms-wifi-test-" + secrets.token_hex(8) + ".json")
path.write_text(json.dumps(values, ensure_ascii=False), encoding="utf-8")
host_secret = path
@@ -82,7 +82,7 @@ Compose 的禁用语义可能位于父节点,文字节点自身仍 enabled。
## 13. 按影响选测与独立模拟器(2026-09-29)
- 先读 [按影响选测](按影响选测.md),选中场景后才执行环境门禁。不能因为手机登记/网络不可用而阻塞不依赖它们的 JVM、模拟器或文档检查。需要真机但环境不可用时仍是“未验证”。
- `--list-scenarios` / `--dry-run` 不导入远端联调依赖、不访问凭据或 ADB。电脑系统 Python 未装 Paramiko 时,优先复用本机测试环境的 `.venv` 并检查 import;不要给核桃派添加主机依赖。
- `--list-scenarios` / `--dry-run` 不导入远端联调依赖、不访问凭据或 ADB。电脑系统 Python 未装 Paramiko 时,使用本机 `local_env.py setup ssh` 重建 `.local/ssh/venv` 并检查 import;不要给核桃派添加主机依赖。
- com.android.test 插件已由同版本 AGP 放入 classpath 时,uiTest 使用无版本 `id("com.android.test")`;显式重复版本可能导致 unknown version 冲突。uiTest 的 Compose 测试库与现有 Compose Multiplatform 锁定版本一致。
- 独立 uiTest 使用 self-instrumenting APK 和实际 Controller,不从反射篡改内部状态。fake RPC 必须遵循真实字段契约:内容条目需要 revision,缺失会在 thumbnailKey 中失败。此类夹具错误应修夹具,不弱化产品断言。
- 真机 navigation 临时撤销扫描/连接权限,防止已有记忆触发自动重连;finally 恢复原权限并回读,不访问板端身份。不将此场景用于权限允许/拒绝的产品验收。
@@ -94,3 +94,14 @@ Compose 的禁用语义可能位于父节点,文字节点自身仍 enabled。
真实用户动画的首帧可能是 `path` 指向持久图片,演示动画则可能是内嵌 `image`。新增 BLE 图片接口时要先检查 `animations.playback_snapshot` 的实际首帧结构,并沿设备既有路径验证与解码规则读取两种形式;不能把 `path` 当作无图或错误参数。空动画仍应按不可播放条目处理。复测须覆盖用户动画和演示动画,并做全库图片只读读取;本轮修正和实测见 [内容缓存验收](../测试结果归档/2026-09-29_内容缓存/README.md)。
模拟器 AVD 名称若存在但启动提示系统目录不存在,先核对该名称的配置指向和镜像登记。保留旧配置,使用已安装镜像新建专用 AVD 再测试;不要因名称存在就反复启动,也不要擅自清空原 AVD。真机 instrumentation 前同时确认产品 APK 与 androidTest APK 已构建,只有测试 APK 时先补产品构建,再运行选中场景。
## 15. 项目本机环境迁移与中文路径(2026-10-01)
- 本项目专用 venv、AVD/系统镜像和私有主机状态使用 [本机环境入口](../../../测试相关资料/如何测试/本机测试环境/README.md),不再依赖全局项目目录。旧全局 AVD 索引存在不代表 AVD 数据存在,先检查实际目录;缺失的数据和主机密钥不能写成迁移成功。
- venv 不能直接搬动后作为可移植环境:`pyvenv.cfg` 和入口脚本可能仍引用原位置。保留旧目录,用完整版本/哈希锁定 wheel 在新位置重建,再检查依赖与解释器。
- 本机 Emulator 在中文路径下报告 `Could not write file`、损坏的中文路径和无法读取 kernel;同一系统镜像通过 ASCII 目录联接启动后 settings/baseline 通过,确认本次启动失败属于路径访问问题。用 `local_env.py ui-smoke android` 自动创建短期入口,镜像/AVD 留在项目内,不移动到全局目录或再次下载镜像。临时入口结束后移除,AVD 的持久 image 路径恢复为项目内位置。
- AGP 构建入口传入 ASCII 目录联接时,不应先 `resolve()` 展开为中文目标;`build_android.py` 保留用户传入的 ASCII 拼写,构建实际写入项目 `.local/work/`。只读路径解析使用常规 resolve,不把此规则扩展到其他环境。
- Emulator 可能把 `config.ini` 重写成 `key = value`,读取时应修剪键值空白,不能把格式变化误报为失效路径。复制项目后 setup 只刷新本工具管理的路径,保留用户数据。
- Windows Python 控制台在诊断输出包含替换字符时可能触发 GBK 编码错误;仅对本次 Python 进程使用 `-X utf8`,不全局调整系统设置。
单次启动失败与复测结果记录在 `各种归档/2026-10-01_本机环境迁移/README.md`;模拟器结果不代表任何真机或板端验收。
@@ -29,6 +29,8 @@ python "移动端相关内容/安卓app/构建与发布/build_android.py" --work
路径实测:AGP 默认拒绝非 ASCII 路径;启用 `android.overridePathCheck=true` 后编译继续,但当前 JBR/Gradle 下 JVM 测试出现类加载失败。在 ASCII 隔离目录同一测试通过,故当前使用该回退。2026-09-25 已在全新且包含空格的 ASCII 构建根目录重新执行全部 92 个任务,JVM 测试及两个 debug APK 均成功;保留中文源码位置。
项目专用 UI 构建现使用 [本机环境入口](../../../测试相关资料/如何测试/本机测试环境/README.md) 的 `local_env.py build-ui android`:缓存与构建实际保存在项目 `.local/work/`,短期 ASCII 目录联接只作调用入口并在结束后移除。`build_android.py --work-root` 保留显式 ASCII 联接的拼写,避免先 resolve 展开为中文路径。产品 APK 原有版本、签名和交付流程不变。
## APK 与签名
- 应用名“奇妙小屏幕”,applicationId 为 `org.qimiaoscreen.controller`,minSdk 26,首版版本 0.1.0。
@@ -17,7 +17,9 @@ def main():
parser.add_argument('--gradle', type=Path, help='Optional verified Gradle executable; otherwise use Wrapper')
parser.add_argument('tasks', nargs='*', default=[':sharedCore:jvmTest', ':androidApp:assembleDebug'])
args = parser.parse_args()
root = args.work_root.resolve()
# Keep an explicitly supplied ASCII junction spelling. Resolving it first
# would expose the Chinese workspace path to AGP despite the alias.
root = Path(os.path.abspath(args.work_root))
if not str(root).isascii():
parser.error('work-root must use ASCII characters')
if not (args.jdk / 'bin/java.exe').is_file() or not (args.sdk / 'platforms').is_dir():