# 嵌入式测试开发标准流程(基于 STM32F4 + CH395F 经验) > 适用范围:STM32 裸机/FreeRTOS 项目,Keil MDK-ARM v5 (ARMCC),串口日志输出测试结果。 --- ## 1. 测试规划(文档先行) 在 `docs/` 下创建测试规范文档,定义以下结构: ### 1.1 阶段概览表 | 阶段 ID | 类型 | 耗时 | 入口 | 出口 | |---------|------|------|------|------| | TM-PHY-01 | 独立运行 | ~1s | 宏启用 | 串口汇总 | ### 1.2 每个测试用例 | 字段 | 说明 | |------|------| | **ID** | `TC-NET-NNN`,唯一编号 | | **优先级** | P0(核心)/ P1(重要) | | **类型** | 功能测试 / 边界测试 / 负向测试 / 压力测试 / 恢复测试 | | **标题** | 一句话描述 | | **前置条件** | 硬件状态、PC 端命令、依赖的其他用例 | | **测试步骤** | 编号操作序列 | | **成功标准** | 精确到"返回值 == 0x00"、"延迟 >= 60000ms" | | **失败标准** | 每种失败对应的现象 | | **覆盖原则** | 对应哪个设计原则 | 关键原则:**先写判定标准,再写测试代码**,避免"测了但不知道算不算过"。 --- ## 2. 测试框架搭建 ### 2.1 目录结构 ``` test/ ch395f_test.h # 宏定义 + TEST_CHECK/TEST_REPORT + test_stats_t ch395f_test_task.h # 仅导出 StartCh395fTestTask ch395f_test_task.c # 全 Phase 实现 ``` ### 2.2 模板文件 #### `ch395f_test.h` — 宏+类型 ```c // 阶段使能开关(取消注释即启用) #define ENABLE_PHASE1_TESTS // 测试统计 typedef struct { uint16_t total; uint16_t passed; uint16_t failed; } test_stats_t; extern test_stats_t g_test_stats; #define TEST_CHECK(cond, fmt, ...) do { \ g_test_stats.total++; \ if (cond) { \ g_test_stats.passed++; \ DBG_INFO("[PASS] " fmt, ##__VA_ARGS__); \ } else { \ g_test_stats.failed++; \ DBG_ERROR("[FAIL] " fmt, ##__VA_ARGS__); \ } \ } while (0) #define TEST_REPORT(name) do { \ DBG_INFO("=== %s: %d/%d PASSED (failed=%d) ===", \ name, g_test_stats.passed, g_test_stats.total, g_test_stats.failed); \ } while (0) ``` #### `ch395f_test_task.c` — 每个 Phase 的模板 ```c #ifdef ENABLE_PHASEX_TESTS /* * Phase X — 功能说明 * * 测试目的:(概括) * 前置条件:(硬件/软件/PC 端) * 通过:(整体判定条件) * 失败:(整体判定条件) */ static void phaseX_run(void) { DBG_INFO("=== CH395F Phase X Tests ==="); /* ---- TC-NET-NNN: 用例标题 ---- */ { // 原理说明 // 通过:精确条件 // 失败:精确条件 ret = some_api(); DBG_INFO(" expect: ..."); DBG_INFO(" actual: ..."); TEST_CHECK(ret == EXPECTED, "description"); } TEST_REPORT("Phase X"); } #endif ``` --- ## 3. 编码规范 ### 3.1 DBG_INFO 三行输出 每个判定点输出三行,一眼看出"期望什么、拿了什么、过没过": ``` [P1-01] ch395f_check_exist() expect: 0x00 (~0x57 = 0xA8) actual: 0x00 [PASS] P1-01 check_exist = 0x00 (expect 0x00) ``` ### 3.2 硬编码值加注释 ```c // 好: ch395f_status_t ret = ch395f_check_exist(); // SPI 写入 0x06 (CMD_CHECK_EXIST) + 0x57 (测试字节) // 成功:回复 == ~0x57 == 0xA8(CH395F_ERR_SUCCESS = 0x00) // 失败:回复 != 0xA8(CH395F_STATUS_NOT_DETECTED = 0xFF) // 不好: ch395f_status_t ret = ch395f_check_exist(); TEST_CHECK(ret == 0, "check_exist OK"); ``` ### 3.3 无中文字符串 ARMCC v5 不识别 UTF-8 多字节字符。`DBG_INFO`/`DBG_ERROR` 中只写 ASCII。注释可以写中文。 ### 3.4 栈安全 大缓冲区(如 64KB)用 `static` 全局,不放任务栈: ```c #define TEST_BUF_SIZE 65536 static uint8_t s_rx_buf[TEST_BUF_SIZE]; ``` ### 3.5 条件编译消除未使用变量警告 ```c static uint8_t s_rx_buf[TEST_BUF_SIZE]; #if defined(ENABLE_PHASE5_TESTS) || defined(ENABLE_PHASE8_TESTS) static uint8_t s_tx_buf[TEST_BUF_SIZE]; #endif ``` --- ## 4. 统一入口 ### 4.1 所有测试在 FreeRTOS 任务中串行执行 ``` ch395fTestTask: 1. 等待 g_net_ready(netTask 初始化完成) 2. 阻塞执行 Phase 1/2/3/6/9(内部循环,无需外部连接) 3. 创建 TCP 监听 Socket(端口 8080,单连接模式) 4. 事件驱动循环 Phase 4/5/7/8/10(等待 PC 连接) ``` ### 4.2 不要在 main.c 中直接调用测试 main.c 只做硬件初始化和启动 OS,不包含任何测试逻辑。 ### 4.3 测试文件的手动注册 新测试文件需: 1. 添加到 `test/` 目录 2. 修改 `MDK-ARM/STM32F407-Demo.uvprojx` 添加文件引用和 IncludePath --- ## 5. 文档与代码同步 - 文档中的入口函数名、宏名、流程描述必须与代码一致 - 代码变更后立即更新文档,否则文档两天内就会失效 - 测试用例的通过/失败标准在**文档和代码注释中都写清楚** - 文档使用标准 Markdown 表格,避免复杂嵌套导致渲染异常 --- ## 6. 编译验证 ### 6.1 底线 **`0 Error(s), 0 Warning(s)`**,不可妥协。 ### 6.2 常见警告处理 | 警告 | 原因 | 解决 | |------|------|------| | `#177-D: variable was declared but never referenced` | 条件编译导致 | 加 `#ifdef` 包裹变量声明 | | `#870-D: invalid multibyte character sequence` | DBG_INFO 中有中文 | 改为纯 ASCII | | 隐式类型转换 | 参数类型不匹配 | 加显式 `(uint8_t)` 等 cast | ### 6.3 构建命令 ```bat MDK-ARM\build.bat :: 或项目根目录执行 @build ``` 退出码:0 = 成功 | 1 = 有警告(不通过)| 2+ = 错误 --- ## 7. 迭代节奏 ``` 文档(规划 + 判定标准) → 代码(添加 Phase 实现) → @build(0 Error(s), 0 Warning(s)) → 烧录验证(串口观察 PASS/FAIL) → 根据实际结果修正判定标准 → 更新文档(保持同步) → 下一阶段 ``` --- ## 附录:本项目的测试文件清单 | 文件 | 作用 | |------|------| | `test/ch395f_test.h` | 测试宏、类型定义、Phase 使能开关 | | `test/ch395f_test_task.h` | 导出 `StartCh395fTestTask` | | `test/ch395f_test_task.c` | 全 10 个 Phase 实现 | | `docs/CH395F_Test_Guide.md` | 测试规范、用例表格、通过/失败标准 | | `docs/CH395F_Trap_Records.md` | 已知硬件/软件陷阱及修复 |