跳到主要内容

测试体系概述

ElenixOS 的分层架构使得任何一层的回归都可能以间接方式传播到上层,而作为嵌入式 GUI 操作系统,运行时深度依赖 LVGL,测试代码无法脱离图形运行时单独执行。测试体系需要同时处理两个性质不同的需求:对逻辑密集的子系统的确定性回归验证,以及对 UI 交互行为的可视化验证。

两层模型

测试体系由框架层和 GUI 层组成,二者在设计意图上明确分工。

框架层负责测试的注册、调度、执行和结果记录。它将每个测试建模为一个命名函数,该函数返回布尔值表达通过/失败。框架层不关注测试的具体逻辑,只管理测试的生命周期和结果聚合——按名字注册与去重、按注册顺序或分组前缀调度执行、集中记录并通过日志系统输出每项结果、维护通过/失败计数和进度状态。框架层同时提供一套断言宏,在宏内封装条件判断和结果记录调用,使测试函数保持简洁。

GUI 层在 LVGL 上构建复选框清单页面,将框架层的测试集以可选列表呈现,提供按分组折叠/展开、单选或全选/取消、执行进度条和当前运行测试的实时展示,以及通过/失败汇总与状态图标。GUI 层是可选的前端——框架层本身不依赖 GUI 即可完成注册和执行。二者的边界是框架层的批量执行和结果记录接口。

命名约定与自动分组

测试名采用冒号分隔的前缀体系:前缀标识测试所属的子系统或子分类,冒号后描述具体测试场景。框架在构建 GUI 清单时扫描所有已注册的测试名,将相同前缀的测试聚合为一个分组,为每个分组生成包含组级复选框和折叠/展开控制的组头。

这种设计的出发点是避免维护额外的分组元数据——分组信息完全由命名约定推导,新增测试只需遵循命名规范即可自动归入正确分组。

聚合模式

每个子系统模块提供自己的注册函数,内部按模块局部顺序注册测试。这些注册函数由统一的 runner 模块按序调用,runner 还负责启动 GUI 页面。

聚合分两个时机完成:注册阶段,runner 调用所有子系统的注册函数,将全部测试收集到框架层的静态表中;执行阶段,框架遍历该表,跳过未选中的条目,按序执行选中的测试。子系统只需暴露一个注册函数,无需感知框架层的内部表结构或其他子系统的存在。

编译期门控

所有测试模块通过 EOS_ENABLE_TEST_APP 宏进行条件编译,该宏由 Kconfig 配置项控制。关闭后,测试相关的全部源文件、头文件及框架 API 调用均被预处理器移除,不对生产固件产生任何影响。隔离发生在预处理阶段而非链接阶段——即使测试模块引用了仅在测试上下文中存在的符号,也不会在禁用测试时引发编译错误。

Activity 生命周期集成

框架层的 GUI 页面和单独的交互式测试页面均基于 Activity 模型构建。每个测试页面是一个 Activity 实例,通过 on_enter/on_destroy 管理 UI 对象的创建与清理,通过 on_pause/on_resume 处理页面切换时的状态保存与恢复。框架层在销毁回调中将指向页面内 UI 对象的静态指针置空以避免悬空引用;独立的交互式测试页面同样遵循此模式,各自管理自身的 UI 状态。

当前约束

框架层在执行模型和运行环境上存在几项固有限制:

  • 无 headless 模式。当前测试执行依赖 LVGL 运行时初始化,无法在纯控制台环境或 CI 流水线的无头节点上直接运行。框架层接口在逻辑上可脱离 GUI 调用,但没有独立的命令行入口。
  • 同步执行模型。框架层按注册顺序依次调用测试函数,每个函数必须在其调用栈内完成全部判断并返回结果。不能直接支持需要跨多个 LVGL tick 完成的异步场景(如等待服务状态变更后验证)。
  • 容量上限。框架层使用固定大小的静态数组存储测试条目和分组信息,数量和分组容量在编译期确定。

待完善

待完善

该部分内容正在构建中,请稍后查看。

  • headless 执行模式:提供不依赖 GUI 启动的入口,将结果通过日志或串口输出,使测试可在 CI 中自动化运行
  • 异步测试支持:对需要跨帧或多轮事件循环的测试场景,提供状态机或回调模式的标准化执行框架
  • 测试间依赖声明:允许声明测试的执行前置条件,前置失败时自动跳过依赖测试
  • 测试覆盖率度量:集成代码覆盖率工具,量化各子系统的测试覆盖情况