构建测试

This commit is contained in:
2026-08-22 19:53:24 +08:00
parent a7f367f6a3
commit fc88bc8752
15 changed files with 2050 additions and 1578 deletions

View File

@@ -0,0 +1,244 @@
# 嵌入式测试开发标准流程(基于 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 == 0xA8CH395F_ERR_SUCCESS = 0x00
// 失败:回复 != 0xA8CH395F_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_readynetTask 初始化完成)
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 实现)
→ @build0 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` | 已知硬件/软件陷阱及修复 |