分层方法论 + 脚手架模板 + 单一编排入口 · 可自动化 / 可量化 / 可自定义
make test / test.sh)按 profile 跑对应层,输出一份合并报告。前不久的「mac 实时统计恒为 0」就是典型反例:原生侧产出统计、Dart 侧消费统计,两端的 pangolin/vpn/stats 契约没有任何自动化测试守门,触发条件一变(隧道已连接才启动 app)就静默失效。L0 契约层防的正是这类 bug。
图 1 · 五层金字塔:L0 契约为地基,L1→L4 自底向上
统计/记账数据沿一条跨进程链路流动。每段接缝标注其契约,以及哪一层测试在此下刀——这张图就是「该测什么、在哪测」的地图。
图 2 · 契约接缝:从节点数据面一路回到客户端 UI
实时上下行走 ①(libbox→EventChannel→Dart);累计流量/周柱走 ④→③→DB→②(节点统计→agent→控制面入库→客户端拉取)。两条流共用同一张接缝图,测试各自归位。
把你提出的四类测试诉求逐条落到层、工具、量化指标与现状:
| 诉求 | 层 | 工具 | 量化指标 | 现状 |
|---|---|---|---|---|
| ① 界面设计一致 每端一致 |
L3 | Flutter golden(字体锁定,host 无关→天然每端一致);design-distill pixelmatch 对照 HTML 原型真相源 | 像素不一致比例 vs 阈值 0.05;golden 通过/失败 |
素材齐 · CI 没跑 |
| ② 前端交互 连接 / 登陆 / 登出 |
L2 | flutter_test 进程内驱动整树 + VpnBridgeMock + http MockClient + ProviderScope 覆盖 | 流程通过/失败;覆盖率 lcov | 素材齐 · 待组装 |
| ③ 数值型 统计 / 实时速度 / 时延 |
L1 + L4 | L1:格式化/换算纯逻辑单测;L4:连真节点拉 stats 断言 bytes 增长、延迟 >0 | 实测 vs 期望容差;时延 ms;速率 B/s >0 | L1 可补 L4 缺 |
| ④ 后端网络 按租户流量 / 限流 |
L2 + L4 | L2:SQLite 真库 + testcontainers MySQL(已覆盖并发/重放/跨日/配额);L4:全链路真流量计数 | 记账数值断言;限流是否触发;覆盖率 go cover | L2 强 L4 缺 |
pangolin/vpn/stats EventChannel 字段、gRPC UsageEntry proto、/v1/me·/v1/usage JSON 形态;静态:analyze/vet、OpenAPI 结构、红线词。ci/scan-redline.sh。flutter_test;go test + testify。go test -cover)。pumpWidget(真 App 树) 驱动 登陆→重启续登→点连接→状态流转→登出,把原生隧道换 VpnBridgeMock、服务端换 MockClient,ProviderScope 覆盖注入。httptest.Server(鉴权路径需补);gRPC bufconn + 自签 CA/CRL(已强)。flutter_test_config.dart 字体锁定→host 无关,所以「每端效果一致」天然成立);design-distill shoot-prototype.mjs + diff.mjs(pixelmatch)。0.05。golden 阻塞守门;权威环境脚本 scripts/update-goldens.sh。tablet/desktop-stats golden 待并入——它们与 stats-overhaul dirty 工作区耦合(基线/测试/被测 widget 同在 dirty),待其合并后跑 update-goldens.sh 生成 Linux 基线并加进 golden job。scripts/e2e-smoke.sh + server/test/e2e/——进程级:真 server 二进制 + sqlite + 内嵌 miniredis + gRPC enroll/ReportUsage → /v1/usage 断言统计真入库真读出(CI job e2e-smoke)。真 sing-box 出网流量留后续。一个入口按 profile 分流:CI 每 push 只跑快而稳的 fast;视觉与 E2E 按需触发。
图 4 · 单一入口 → 三 profile 泳道
图 5 · docker-compose 真链路 + 测试驱动器(推荐边界 a)
| 维度 | 指标 | 工具 / 口径 |
|---|---|---|
| 覆盖率 | 行/分支 % | flutter test --coverage + go test -coverprofile → 合并 lcov |
| 视觉 | 不一致像素比例 vs 阈值 0.05 | pixelmatch(diff.mjs);golden 通过/失败 |
| 数值精度 | 实测 vs 期望容差 | L4 断言 bytes/速率/累计落在容差带内 |
| 时延 | 毫秒 ms | urltest 延迟 >0 且在合理区间 |
| 稳定性 | 通过率 / flaky 率 | 多次重跑统计;flaky 用例隔离 |
跨项目模板(复制即用,按接缝微调):
VpnBridge 接口 + Mock)→ 任何「原生/外部依赖」都可照此切假。flutter_test_config.dart)→ 视觉回归通用骨架。run_sqlite_test.sh)+ testcontainers 集成套 → 任何 DB 项目通用。每项目按接缝定制:契约字段、API 路径、compose 服务清单、golden 屏清单、数值容差阈值。
| 序 | 动作 | 性价比 | 起点 |
|---|---|---|---|
| 1 | 补 L0 契约快照 + 把现有 golden 接进 CI | 最高(防回归) | 素材已有,组装即可 |
| 2 | 组装 L2 前端 flow 测试(登陆/续登/连接/登出) | 高 | Mock/覆盖素材全齐 |
| 3 | 建 L4 后端全链路冒烟 (a) | 中(覆盖"真不真") | 需新建 compose + 驱动器 |
| 4 | 补 L1 数值单测 + L2 HTTP 鉴权测试 | 中 | 增量补齐 |
| 5 | (b) desktop 真连 / (c) 真机——本地按需 | 低(贵·脆) | 需常驻 Mac / 真机 |
本文档仅为架构说明(设计真相源)。具体落地拆解(契约快照实现、前端 flow 用例、L4 冒烟脚本)走各自实现计划(writing-plans)。