按初级程序员可读、可维护的目标重写项目文档,并定案三项设计决策。 新增 - docs/client/00-getting-started.md 上手指南:装环境、跑起来、常见报错 - docs/client/00-glossary.md 术语表:Outbox、幂等、不可逆阶段等 - docs/templates/task.md 工单与归档模板 - client/requirements.txt 固定依赖版本 - .gitignore 屏蔽 data/、打包产物和调试产物 设计定案 - 本地库只存已领取任务,不再镜像 Admin 任务池;已完成任务永久保留 - 去掉租约、心跳和状态回查;Admin 接口从 5 个降到 3 个 (本项目人工付款,重复下单只产生未付款订单,由人工审核处理) - 打包采用 PyInstaller one-dir:launcher.exe + app/ + data/,便携模式 文档改进 - 补齐可直接抄的代码模板:Worker 线程、事务写库、幂等键、增量加载、错误提示、路径解析 - 状态机由 ASCII 图改为完整转换表,并补充崩溃恢复规则 - 消除文档与现有代码的冲突,02 新增“现状与目标差异”清单 - 待确认事项一律给出临时默认值,避免阻塞开发 - AGENTS.md 新增“小改动直通”,工单必填项由 8 项压缩到 6 项 说明:Gitea 尚未配置,本次无对应工单号;AGENTS.md §0 的 Gitea 信息待补。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
208 lines
10 KiB
Markdown
208 lines
10 KiB
Markdown
# 06 Client 质量、安全与测试基线
|
||
|
||
- 文档状态:基线草案,待质量评审
|
||
- 适用范围:Client 源码、配置、数据库、自动化和发布产物
|
||
|
||
本文档中 `[必须]` / `[建议]` / `[待定]` 的含义见 [文档索引](../README.md#文档标注说明)。没有标注的默认是 `[必须]`。看不懂的词查 [术语表](00-glossary.md)。
|
||
|
||
## 1. 质量目标
|
||
|
||
- 同一台 Client 不重复执行或重复提交同一个采购任务;崩溃重启后也不重复下单。
|
||
- 网络和 Admin 故障不丢失已完成结果。
|
||
- 设备或 PDD 页面异常可诊断,不以错误坐标继续执行高风险操作。
|
||
- 所有阻塞工作离开 Qt 主线程,窗口在长任务期间保持可用。
|
||
- 代码、接口、数据库和诊断产物不泄露凭据及不必要的个人数据。
|
||
|
||
## 2. 测试分层
|
||
|
||
### 2.1 单元测试
|
||
|
||
必须覆盖:
|
||
|
||
- 任务状态转换和非法转换;
|
||
- 金额、数量、价格上限和规格校验;
|
||
- Admin DTO 与 `pdd_data` JSON 验证;
|
||
- SQLite Repository、迁移和默认排序;
|
||
- Outbox 幂等、退避和崩溃恢复;
|
||
- 销量、评价和价格文字解析;
|
||
- 控件树坐标解析、规格匹配和选中状态判断;
|
||
- 订单候选匹配规则。
|
||
|
||
PDD 解析测试优先使用脱敏的 XML 固件,不要求每次连接真实设备。
|
||
|
||
### 2.2 集成测试
|
||
|
||
使用临时 SQLite 和 Mock Admin 覆盖:
|
||
|
||
- 原子领取和重复领取;
|
||
- 提交一个 Admin 侧已取消的任务,仍被接受并标记 `succeeded`;
|
||
- 采集/采购任务分派;
|
||
- 结果先落库再进入 Outbox;
|
||
- Admin 超时后重试相同幂等键;
|
||
- 程序在提交前、下单阶段和提交后异常退出;
|
||
- 窗口关闭后后台结果不会更新已销毁界面。
|
||
|
||
### 2.3 界面测试
|
||
|
||
- Python 语法编译;
|
||
- 离屏实例化主窗口;
|
||
- 表格模型排序、筛选和增量加载;
|
||
- 开始/停止按钮防重复;
|
||
- Ctrl+F、Enter 和 Tab 顺序;
|
||
- 加载、空、错误、离线、运行和人工处理状态;
|
||
- 浅色、深色、高对比度和 100%–200% 缩放。
|
||
|
||
### 2.4 设备测试
|
||
|
||
真实设备测试必须显式标记,不应混入默认快速测试:
|
||
|
||
- PDD 首页、商品页、规格面板和订单列表识别;
|
||
- 不同商品规格数量、滚动方式和缺货状态;
|
||
- 登录失效、验证码、网络慢、页面变化和弹窗;
|
||
- 采集完整性;
|
||
- 采购演练及订单核对。
|
||
|
||
### 2.5 契约和端到端测试
|
||
|
||
- Mock Gateway 与 Http Gateway 对同一接口测试集通过。
|
||
- Admin 提供可测试环境后执行版本、错误和幂等契约测试,含"已取消任务的结果仍被接受"。
|
||
- 端到端测试从任务领取开始,以 Admin 确认结果和本地状态一致结束。
|
||
|
||
## 3. 采购安全门禁
|
||
|
||
真实下单开关默认关闭。全部满足后才能通过独立工单启用:
|
||
|
||
1. Admin 原子领取和结果幂等已经通过联合测试。
|
||
2. Outbox 断网和重启恢复测试通过。
|
||
3. 商品编号、标题、规格、数量、库存和价格保护校验通过。
|
||
4. 最终下单前后均有持久化步骤标记。
|
||
5. 进程在不可逆阶段退出后只执行订单核对,不会重新下单。
|
||
6. 订单匹配能识别唯一候选;多个候选进入人工处理。
|
||
7. 演练模式在代表性商品和设备上通过验收。
|
||
8. 操作人员明确确认真实下单范围和安全设置。
|
||
|
||
真实下单不得通过调试参数、默认配置或界面误操作意外开启。
|
||
|
||
## 4. 自动化防护
|
||
|
||
- 点击前必须确认包名、页面类型、目标语义和坐标边界。
|
||
- 高风险点击应在最新控件树上重新定位,不使用长时间缓存的坐标。
|
||
- 规格选择后读取最新控件树并验证选中状态。
|
||
- 最终下单前重新读取实际价格、数量和规格。
|
||
- 页面出现验证码、登录、支付、权限请求或未知模态层时停止并转人工处理。
|
||
- uiautomator2 连接由单一工作线程独占,任务间清理临时状态。
|
||
- 所有循环具有超时、最大滑动次数和可取消检查。
|
||
|
||
> **运营提醒(不是代码规则):** Admin 超时重派可能导致同一任务被两台 Client 各下一单,
|
||
> 产生重复的未付款订单。人工审核时取消多余订单即可。但未付款订单长期堆积可能触发平台风控,
|
||
> 需要操作人员留意,不要放着不管。
|
||
>
|
||
> 将来若要在程序里防这个,正确的加固点是**最终下单前的最后一次校验**(本节已要求重新读取价格、
|
||
> 数量和规格,顺带确认任务有效性即可),**不要**改回周期性回查 Admin 状态。
|
||
|
||
## 5. 错误分类
|
||
|
||
建议使用稳定错误代码:
|
||
|
||
| 分类 | 示例 |
|
||
|---|---|
|
||
| `ADMIN_*` | 认证失败、超时、请求无效、幂等冲突 |
|
||
| `DEVICE_*` | 设备离线、ADB 失败、应用未启动 |
|
||
| `PDD_PAGE_*` | 页面超时、未知页面、登录失效、验证码 |
|
||
| `PDD_DATA_*` | 标题缺失、规格不完整、价格解析失败 |
|
||
| `PURCHASE_*` | 规格缺货、价格超限、下单状态不确定 |
|
||
| `ORDER_*` | 未找到订单、多个候选、详情不匹配 |
|
||
| `DB_*` | 迁移失败、写入失败、数据库锁超时 |
|
||
| `OUTBOX_*` | 提交失败、幂等冲突、结果被拒绝 |
|
||
|
||
错误反馈必须说明发生了什么、已保留什么以及下一步是什么。原始异常堆栈仅写入诊断日志,不直接展示给普通用户。
|
||
|
||
## 6. 日志与诊断
|
||
|
||
日志至少包含:
|
||
|
||
- 时间、级别、模块和稳定事件名;
|
||
- `client_id`、`remote_task_id`、`attempt_id` 和请求编号;
|
||
- 当前步骤、持续时间、结果和稳定错误代码;
|
||
- Admin 响应状态,但不记录认证头和完整敏感正文。
|
||
|
||
建议事件:
|
||
|
||
- `task_claim_started/succeeded/empty/failed`
|
||
- `task_claimed`
|
||
- `task_step_changed`
|
||
- `task_result_persisted`
|
||
- `outbox_send_started/succeeded/failed`
|
||
- `purchase_irreversible_step_entered`
|
||
- `order_reconcile_completed`
|
||
|
||
失败 Artifact 目录建议:
|
||
|
||
```text
|
||
artifacts/<remote_task_id>/<attempt_id>/
|
||
├── metadata.json
|
||
├── hierarchy.xml
|
||
├── screenshot.png
|
||
└── steps.jsonl
|
||
```
|
||
|
||
Artifact 写入前应脱敏,数据库只保存引用。保留周期由设置控制,删除不得影响任务结果和审计字段。
|
||
|
||
## 7. 凭据与隐私
|
||
|
||
- Admin 必须使用 HTTPS;生产环境不得允许静默忽略证书错误。
|
||
- Token 优先保存到 Windows 凭据管理器或由安全环境注入。
|
||
- **`data/` 目录是明文的,且设计上就是"整个拷走",凭据绝不能写进去**,见 [03](03-data-model.md) §2.1。
|
||
- 设置页只能显示认证状态或掩码值。
|
||
- 日志、数据库、截图、XML、Gitea 工单和 `docs/task` 都不得包含 Token、Cookie、密码或支付信息。
|
||
- 只保存完成任务所需的订单编号和时间,不采集无关收货人、地址、电话等个人数据。
|
||
- 不实现验证码、风控或平台安全机制绕过。
|
||
|
||
## 8. 数据可靠性
|
||
|
||
- 数据库迁移前创建可恢复备份或采用可回滚迁移步骤。
|
||
- 所有可写文件只能落在 `data/` 下,路径一律通过 `data_dir()` 取,见 [03 数据模型](03-data-model.md) §2.2。
|
||
- 每个任务状态变化和执行记录在同一事务内保持一致。
|
||
- `result_pending` 任务必须存在对应结果和 Outbox 记录。
|
||
- Outbox 发送成功前不得删除结果正文。
|
||
- 迟到的 Admin 响应不得覆盖更新的本地执行状态。
|
||
- 数据库损坏、磁盘写满和只读目录必须产生可操作错误,不能继续下单。
|
||
|
||
## 9. 性能和响应性
|
||
|
||
- 表格使用模型/视图和增量加载,不为每个单元格创建 QWidget。
|
||
- 搜索、排序和分页使用索引支持的 SQLite 查询。
|
||
- 高频进度信号需要节流,避免每次 XML 节点变化都刷新界面。
|
||
- 大型 XML 解析、截图和文件写入位于工作线程。
|
||
- 目标基线:普通本地搜索在典型数据量下保持即时反馈,任务运行时界面可持续操作。
|
||
|
||
## 10. 发布门禁
|
||
|
||
每个版本至少满足下面全部条件。**"谁负责"这一列是为了让你知道哪些不用自己扛**——不是你负责的项,去找对应的人,不要自己拍板放行。
|
||
|
||
| # | 门禁项 | 怎么验证 | 谁负责 |
|
||
|---|---|---|---|
|
||
| 1 | 依赖版本已固定,且能重复安装 | `client/requirements.txt` 里每一行都带 `==`;在干净环境执行 `pip install -r requirements.txt` 能装成功 | 开发者 |
|
||
| 2 | 全部默认单元测试和集成测试通过 | 跑测试命令,不允许有跳过而没说明的用例 | 开发者 |
|
||
| 3 | UI 离屏冒烟测试通过 | 见 [client/AGENTS.md](../../client/AGENTS.md) §验证 第 2 条 | 开发者 |
|
||
| 4 | 数据库从上一发布版本迁移成功 | 拿上一版本的 `client.db` 副本启动新版本,数据不丢 | 开发者 |
|
||
| 5 | Mock Admin 契约测试通过 | Mock 和 HTTP 两个实现跑同一套测试 | 开发者 |
|
||
| 6 | Windows 干净环境启动测试通过 | **未打包版本**:找一台没装过本项目的机器,照 [00 上手指南](00-getting-started.md) 从头走一遍。**已打包版本**:把整个文件夹拷到一台**没装 Python** 的机器上双击 `launcher.exe` | 开发者 |
|
||
| 6b | 升级不丢数据(仅打包版本) | 换掉 `launcher.exe` 和 `app/`,`data/` 保留,启动后任务、日志、设置都还在 | 开发者 |
|
||
| 7 | 日志和产物无敏感信息 | 翻一遍日志和 `artifacts/`,确认没有 token、Cookie、密码、收货人信息 | 开发者 |
|
||
| 8 | 开源和商业许可证已确认 | 新增依赖的许可证是否允许本项目的使用方式 | **项目负责人**(不是开发者自己判断) |
|
||
| 9 | 真实下单版本额外满足采购安全门禁 | 逐条核对 §3 的 8 项 | **项目负责人 + 操作人员共同确认** |
|
||
|
||
第 8、9 项开发者**不要自己判断放行**。新增依赖时把包名和许可证类型报给项目负责人;真实下单开关必须由项目负责人和实际操作的人一起确认,见 §3。
|
||
|
||
## 11. 任务完成定义
|
||
|
||
单元任务只有同时满足以下条件才算完成:
|
||
|
||
1. 工单验收标准逐项通过。
|
||
2. 代码、迁移、测试和必要文档同步完成。
|
||
3. 没有静默跳过的测试或未说明的真实设备假设。
|
||
4. 变更不泄露敏感信息,也不扩大自动化权限。
|
||
5. Gitea 工单更新最终结果和提交哈希。
|
||
6. 完成记录归档到 `docs/task`。
|