嵌入式 TDD:在硬件上进行单元测试
“我的代码只有刷到板子上才能跑。” —— 这句话阻碍了无数嵌入式项目的自动化测试进程。每改一行代码都要烧录、重启、按按钮,这种开发效率极其低下。
TDD (Test-Driven Development) 并不是纯软件的专利。
1. 为什么嵌入式难测?
核心痛点在于硬件依赖。你的代码里充斥着 #include "stm32f4xx.h",充斥着对外设寄存器的直接读写。这导致你的代码无法在 PC (x86) 上编译运行。
2. 解耦:Mock 掉硬件
要让代码可测,首先要分离业务逻辑和硬件驱动。
Bad Code:
1
2
3
4void LED_Blink(void) {
GPIOB->ODR ^= (1 << 5); // 直接操作硬件,锁死了平台
HAL_Delay(100);
}Testable Code:
1
2
3
4
5// 注入硬件操作接口
void LED_Blink(LedDriver_t *driver) {
driver->toggle(LED_PIN_5);
driver->delay_ms(100);
}
在 PC 上跑测试时,我们可以注入一个“假”的 driver(Mock Object),在这个假 driver 里记录函数是否被调用。
3. 测试框架:Unity + CMock
ThrowTheSwitch 组织提供的 Unity 和 CMock 是嵌入式领域的神器。
- Unity:极简的 C 语言单元测试框架。
1
2
3
4TEST(LedControl, BlinkShouldTogglePin) {
LED_Blink();
TEST_ASSERT_EQUAL_HEX(0x20, MockGPIO_GetLastState());
} - CMock:自动扫描你的头文件 (
led_driver.h),自动生成 Mock 实现 (Mockled_driver.c)。- 你可以在测试代码中设定期望:
LedDriver_Toggle_ExpectAndReturn(LED_PIN_5, OK); - 如果代码运行时没有按期望调用该函数,测试直接失败。
- 你可以在测试代码中设定期望:
4. 持续集成 (CI)
一旦代码能在 PC 上编译运行,就可以接入 GitLab CI 或 GitHub Actions。
每次提交代码,服务器自动运行所有用例:
- 编译(GCC for x86)。
- 运行单元测试。
- 生成覆盖率报告 (gcov/lcov)。
- (可选)交叉编译通过(GCC for ARM)。
总结
不要等到量产前一天才发现 Bug。TDD 虽然前期编写测试代码很“烦”,但它能给你重构代码的底气,和睡个安稳觉的权利。
- Title: 嵌入式 TDD:在硬件上进行单元测试
- Author: Evek Golden
- Created at : 2025-01-05 23:33:00
- Updated at : 2026-06-12 08:57:02
- Link: https://blog.cocodemo.uno/posts/tdd8j2w/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments