综合平台编程器项目的远程存储
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

6.8 KiB

测试约定

本文件是测试代码的长期约束。新增或修改测试时,先判断被验证的契约、所属生产层和运行环境,再决定测试文件和测试目标。测试数量不是质量指标,重复断言也不是覆盖率;每个测试必须能回答一个明确的失败问题。

测试目标

项目测试分为四种用途,不能互相替代:

用途 证明什么 是否进入普通自动化回归
功能测试 业务规则、服务用例和用户工作流结果正确
性能测试 在固定代表性规模下满足时间、吞吐或资源预算 单独运行
真机/HIL 测试 串口、PLC 响应、接线和现场联动真实有效 手工执行
稳定性/故障测试 断线、超时、非法输入和恢复状态可控 是;真实设备部分除外

功能测试按生产边界分层:

Domain -> Services -> Infrastructure -> UI -> E2E
  • Domain:纯模型和值对象规则,不依赖 Qt Widgets、文件系统或串口
  • Services:业务用例、原子编辑、撤销重做、离线扫描和运行模式,使用内存仓库或 Fake
  • Infrastructure:JSON 文件、PLC 缓存、Modbus 地址规划和错误分类
  • UI:Qt Widgets 事件、动作、投影和窗口生命周期,使用 QT_QPA_PLATFORM=offscreen
  • E2E:少量跨层用户主流程,不重复覆盖每一条领域边界

当前目标映射如下:

测试目标 所属层 主要契约
domain_tests Domain 地址、模型、边界和运行前校验
alarm_service_tests Services 报警编辑和运行记录生命周期
hmi_editor_service_tests Services HMI 编辑、原子删除、历史和导航
logic_editor_service_tests Services 结构化梯形图编辑、归一化和历史
offline_simulation_service_tests Services 扫描语义、定时器、计数器和故障
runtime_mode_service_tests Services 编辑/离线/真机状态转换和准入条件
register_monitor_service_tests Services 监视地址、读写和活动仓库
project_management_tests Infrastructure + Services JSON 往返、非法文件和工程保存状态
plc_runtime_tests Infrastructure + Services PLC 缓存、轮询约束、错误恢复和 Fake gateway
main_window_tests UI 编辑工作流、运行监控窗口和 UI 投影
performance_tests Performance 代表性梯形图扫描和寄存器访问基准

防止冗余

同一业务场景可以在多层出现,但断言必须不同:

  • Domain 断言“什么配置合法”
  • Service 断言“用例如何改变模型或寄存器”
  • UI 断言“用户操作是否调用正确用例并显示结果”
  • 真机断言“设备实际响应和现场动作是否正确”

如果两个测试的输入、执行路径和断言都相同,只保留更低层、更快且失败定位更清晰的那个。UI 测试不得重新复制领域边界矩阵;真机测试不得把软件执行器的内部语义再测一遍。

每个生产契约至少有一个主要测试负责人。跨层回归只保留一条关键链路,例如“运行监控按钮 -> 活动仓库 -> Fake PLC gateway”,不要在每个窗口测试中重复构造完整 PLC 状态机。

测试代码规范

  • 测试名称使用“对象_行为_结果”语义,例如 project_rejectsDuplicatePageIds
  • 一个测试函数只验证一个行为主题;多个边界属于同一规则时可以放在同一函数
  • 失败消息必须说明预期和业务含义,不能只写 failed
  • Fixture 放在 app/tests/support/;只有语义确实不同的 Fake 才允许留在测试文件内
  • TestSupport::requireTestSupport::InMemoryProjectStorage 是通用基础设施,不要重新定义同名版本
  • 测试不得修改 app/src 生产代码来迁就断言;发现难以测试时,优先检查服务契约和依赖注入边界
  • 测试不依赖测试执行顺序;每个函数建立自己的仓库、服务和工程状态
  • 测试使用 UTF-8;中文错误消息和工程样例必须按 UTF-8 读取

当前历史测试仍使用轻量自定义 main(),后续新增测试优先使用 Qt Test:QTEST_APPLESS_MAINQTEST_MAINprivate slotsQVERIFY/QCOMPAREQBENCHMARK。迁移旧测试时按测试目标逐步进行,不为了换框架重写无关业务覆盖。

qmake 组织

  • app/tests/tests.pro 是所有自动化目标的聚合入口
  • app/tests/pri/test_defaults.pri 只放公共 qmake 配置
  • app/tests/pri/test_layers.pri 只放按生产层分组的源码清单
  • 测试 .pro 只选择自己需要的层变量,不得重新手写重复的 ../src 清单
  • 不把所有生产源码放入一个“大而全”测试库;测试目标应能反映真实依赖边界
  • 构建输出放在 build/,不能写入 app/

统一运行:

pwsh -NoLogo -NoProfile -File .\scripts\run_qt_tests.ps1 -Configuration Release

只构建聚合目标而不运行时,可在独立构建目录对 app/tests/tests.pro 执行 qmake 和 mingw32-make。UI 测试必须设置 QT_QPA_PLATFORM=offscreen

性能测试

性能测试必须单独命名为 *_performanceperformance_tests,使用固定规模输入和 QBENCHMARK。每个基准需要说明:

  • 输入规模,例如 100 个控制逻辑、4001 个寄存器
  • 测量对象,例如一次扫描或一次完整读写遍历
  • 不纳入测量的准备工作
  • 结果用途,是观察趋势还是有明确预算

性能基准不是功能断言,不能因为机器差异设置脆弱的毫秒硬阈值。功能前置校验可以使用 QVERIFY,但基准循环只测目标操作。

真机/HIL 测试

真实 PLC 测试不放入普通 tests.pro 的自动执行流程,也不使用自动化 Fake 测试冒充真机结论。真机测试必须记录:

  • COM3 / 9600 / 8E1 / 站号 1 或实际批准的配置
  • 测试前读取的原值、测试动作、读回结果和恢复结果
  • STOP/RUN 状态、接线和现场负载条件
  • 测试是否涉及 PLC 内部程序;本项目不下载或生成 PLC 程序

通信安全验证先读原值,测试后恢复并再次读回。未经确认接线和地址,不执行 RUN 联动。真机记录属于验收证据,不应把设备状态写进可重复的单元测试。

修改测试的决策流程

  1. 写出要保护的业务契约和失败风险
  2. 选择能以最低环境成本证明契约的层
  3. 搜索现有测试,确认不是已有相同断言
  4. 复用 support/ fixture 和 .pri 层变量
  5. 运行受影响目标,再运行完整自动化集合
  6. 涉及 PLC 通信、运行模式或 UI 工作流时扩大回归,并在 docs/ai/handoff.md 记录未做真机测试的原因

提交前至少完成对应自动化测试、Release 构建和 git diff --check。性能结果和真机记录不替代功能测试结果,三者必须分别报告。