Wow 应用测试
本页面面向使用 Wow 构建业务应用的团队。领域 DSL 回答“模型是否按不变量工作”,应用测试回答“这个模型能否在实际装配、协议和基础设施中安全运行”。两者是连续门禁,不能互相替代。
完成信号
应用测试完成时,应有当前构建产生的元数据证据、至少一个端到端业务入口、生产同型 Adapter 的重启/重投证据和安全反例。下一层是在目标环境执行发布、恢复与可观测性验收,而不是运行 Wow 框架仓库的基准。
三类测试不要混在一起
| 范围 | 证明什么 | 不证明什么 |
|---|---|---|
| 领域 DSL | 命令决策、拒绝、事件、溯源状态、Saga 命令 | Spring、HTTP、KSP 打包、真实存储或 Broker |
| 应用集成门禁 | 应用自己的模块、配置、入口和生产 Adapter 能闭环 | Wow 框架在其他配置下的通用性能或正确性 |
| 框架仓库测试与基准 | Wow 源码、TCK、容器集成和指定 JMH 工作负载 | 你的应用已具备发布条件或生产容量 |
业务应用不需要复制 allLocalTest、allContractTest、allIntegrationTest 或 Codecov flag 结构。这些是 Wow 仓库的维护任务。应用应按自己的模块和发布风险设置门禁。
应用测试阶梯
| 层次 | 最小证据 | 失败时先查 |
|---|---|---|
| 领域规格 | 所属领域模块的 test/check 通过 | 不变量、事件和溯源函数 |
| 编译元数据 | 注解模块生成非空 META-INF/wow-metadata.json | KSP 与 wow-compiler 是否应用在正确模块 |
| 运行时装配 | 服务加载元数据并暴露预期命令/状态入口 | Starter capability、模块运行时依赖、配置 |
| 协议垂直切片 | 一个业务命令从入口到持久化结果可观察 | 请求契约、路由、等待语义、错误映射 |
| 真实 Adapter | 生产同型存储/Broker 上读写和重投正确 | 序列化、版本冲突、幂等和网络边界 |
| 恢复与安全 | 重启/重放后状态一致,越权请求 fail closed | 快照、位点、租户/owner/space 与 ABAC |
每天先运行最窄的受影响模块,合并或发布前再逐层扩大。不要因为根 build 很大就跳过能直接指向失败层的模块任务。
1. 领域门禁
每条聚合不变量至少覆盖:
- 成功命令产生的事件和最终状态;
- 业务拒绝及状态不变;
- 关键生命周期转换;
- 删除、恢复或其他启用的框架生命周期;
- Saga 对正反两类输入事件产生正确命令或不产生命令。
本仓库的可运行参考是:
./gradlew :example-domain:check业务应用应替换为自己的领域模块。详细 DSL 见领域测试套件。
2. 生成元数据门禁
含 Wow 注解模型的模块必须应用 KSP 和 wow-compiler,并把生成资源带入服务运行时 classpath。可用仓库示例验证完整生成链路:
./gradlew :example-domain:clean :example-domain:kspKotlin :example-domain:test
test -s example/example-domain/build/generated/ksp/main/resources/META-INF/wow-metadata.json在业务应用中替换模块路径,并检查每个含注解的模块。完成信号不只是 KSP 任务退出 0:文件必须非空,服务模块必须依赖该模块,启动证据必须显示资源已被加载。不要手写或提交生成文件。
3. 运行时与协议垂直切片
为至少一个真实业务聚合保留应用级测试,覆盖以下闭环:
- 使用与生产入口相同的 Spring 配置启动应用;
- 通过公开协议发送一个带唯一聚合 ID 和请求 ID 的命令;
- 断言协议状态、命令结果和错误映射;
- 从公开状态或查询入口读取结果;
- 证明读到的状态来自刚才持久化的事件,而不是测试内共享对象。
这个切片应使用应用现有的 Cart、Order 或其他真实模型,不要另造一个只为测试路由的“演示聚合”。内存 Adapter 可以作为快速门禁,但测试报告必须明确它没有覆盖生产存储、Broker、重启和鉴权。
4. 真实 Adapter 与失败语义
生产使用的每种持久化或传输能力至少有一个容器或隔离环境测试:
- 使用与生产一致的 Starter capability 和序列化配置;
- 写入真实 EventStore 后能加载同一事件流;
- 相同请求 ID 或 Broker 重投不会重复产生业务副作用;
- 乐观锁或版本冲突以应用定义的方式返回,不丢失已成功数据;
- 外部依赖失败不会把部分结果报告为完整成功;
- SnapshotStore 启用时,快照加载结果与完整事件重放一致。
按应用拥有的 Adapter 取舍,不要为了“完整”测试未使用的数据库或 Broker。
5. 重启、重放与升级
进程内成功不等于可恢复。至少证明:
- 写入事件后停止应用;
- 使用同一持久化数据重新启动;
- 读取状态并与重启前结果比较;
- 在禁用或清除快照后从完整事件历史得到相同状态;
- 投影、消费者位点和补偿任务能够按已记录步骤恢复;
- 若事件 revision 或序列化形状发生变化,旧历史数据有明确的兼容或迁移证据。
恢复测试必须保留输入数据版本和环境配置,否则一次成功截图无法作为后续发布证据。
6. 安全与隔离反例
安全测试优先覆盖失败路径:
| 场景 | 期望 |
|---|---|
| 匿名访问受保护命令或查询 | 401 或 403 |
| 伪造 tenant、owner 或 space | 请求被拒绝且作用域不扩大 |
| 主体缺少必要 ABAC 标签 | fail closed,不退化为全量匹配 |
| 跨租户或跨 owner 查询 | 不返回越权数据 |
| 普通请求尝试访问原始查询工厂 | 没有可达入口 |
完整边界见数据权限。安全通过需要实际应用的 Spring Security/CoSec 配置,领域规格无法替代。
发布前证据表
| 证据 | 完成条件 |
|---|---|
| 领域 | 成功、拒绝、关键生命周期规格通过 |
| 生成 | 每个注解模块的元数据非空并被运行时加载 |
| 协议 | 公开入口到可读取结果的垂直切片通过 |
| 基础设施 | 生产同型 Adapter 的写入、重投、冲突和失败路径通过 |
| 恢复 | 重启与无快照重放得到一致状态 |
| 安全 | 鉴权、租户隔离和 ABAC 反例全部 fail closed |
| 运维 | 备份、恢复、回滚、Trace、指标与告警在目标环境有证据 |
只有修改 Wow 框架源码、实现 Adapter 或调查框架性能时,才进入框架测试与基准。框架 CI 绿色或历史基准数字都不能替代这张应用证据表。