如何测试无返回值的Arduino代码?Platformio+VSCode环境求助
测试Arduino
flashXTimes 函数的两种有效方案 针对你需要验证numberOfFlashes=3时函数执行3次闪烁的需求,以下是基于PlatformIO + Unity测试框架的两种可行方案,解决C++中无法直接替换函数指针的问题:
方案一:预处理宏替换(无需修改业务代码)
通过编译阶段的宏替换,将digitalWrite和delay替换为我们的Mock函数,无需改动原有业务逻辑。
1. 编写测试文件(test/test_flash.cpp)
#include <unity.h> #include "flash.h" // 记录Mock函数的调用信息 static uint32_t digitalWriteCallCount = 0; static uint8_t lastUsedPin = 0; static uint8_t lastOutputVal = 0; // Mock digitalWrite:记录调用次数、引脚和电平 void digitalWriteMock(uint8_t pin, uint8_t val) { digitalWriteCallCount++; lastUsedPin = pin; lastOutputVal = val; } // Mock delay:测试时跳过实际等待 void delayMock(uint16_t ms) {} // 宏替换:编译阶段将原函数指向Mock实现 #define digitalWrite digitalWriteMock #define delay delayMock // 测试前置操作:每次测试重置计数器 void setUp(void) { digitalWriteCallCount = 0; lastUsedPin = 0; lastOutputVal = 0; } // 测试后置清理 void tearDown(void) {} // 核心测试用例:验证3次闪烁的调用逻辑 void test_flash_3_times(void) { const uint8_t TEST_LED_PIN = 13; flashXTimes(TEST_LED_PIN, 3, 100, 100); // 验证调用次数:3次闪烁 → 每次HIGH+LOW,共6次调用 TEST_ASSERT_EQUAL(6, digitalWriteCallCount); // 验证最后一次调用是关闭LED(LOW电平) TEST_ASSERT_EQUAL(TEST_LED_PIN, lastUsedPin); TEST_ASSERT_EQUAL(LOW, lastOutputVal); } // 测试入口 int main(int argc, char **argv) { UNITY_BEGIN(); RUN_TEST(test_flash_3_times); UNITY_END(); return 0; }
2. 配置PlatformIO(platformio.ini)
添加测试环境配置,确保Unity框架生效:
[env:your_board] platform = atmelavr board = uno # 替换为你的目标开发板 framework = arduino test_framework = unity test_build_project_src = true # 编译项目源代码用于测试
执行测试
在VSCode终端运行命令:
pio test -e your_board
方案二:依赖注入(可测试性优化方案)
修改业务函数,通过可选函数指针参数注入引脚控制和延迟逻辑,既保留原有功能,又提升测试灵活性。
1. 修改业务代码
flash.h:
#ifndef FLASH_H #define FLASH_H #include <Arduino.h> // 定义函数指针类型 typedef void (*PinWriteFunc)(uint8_t, uint8_t); typedef void (*DelayFunc)(uint16_t); // 添加可选参数:默认使用Arduino原生函数 void flashXTimes( uint8_t LEDPin, uint16_t numberOfFlashes, uint16_t onDuration, uint16_t offDuration, PinWriteFunc pinWrite = digitalWrite, DelayFunc delayFunc = delay); #endif
flash.cpp:
#include "flash.h" void flashXTimes( uint8_t LEDPin, uint16_t numberOfFlashes, uint16_t onDuration, uint16_t offDuration, PinWriteFunc pinWrite, DelayFunc delayFunc) { for (uint16_t i = 0; i < numberOfFlashes; i++) { pinWrite(LEDPin, HIGH); delayFunc(onDuration); pinWrite(LEDPin, LOW); delayFunc(offDuration); } }
2. 编写测试文件(test/test_flash.cpp)
#include <unity.h> #include "flash.h" static uint32_t pinWriteCallCount = 0; static uint8_t recordedPin = 0; static uint8_t recordedVal = 0; // Mock引脚写入函数 void mockPinWrite(uint8_t pin, uint8_t val) { pinWriteCallCount++; recordedPin = pin; recordedVal = val; } // Mock延迟函数 void mockDelay(uint16_t ms) {} void setUp(void) { pinWriteCallCount = 0; recordedPin = 0; recordedVal = 0; } void tearDown(void) {} void test_flash_3_times(void) { const uint8_t TEST_PIN = 13; // 测试时传入Mock函数 flashXTimes(TEST_PIN, 3, 100, 100, mockPinWrite, mockDelay); TEST_ASSERT_EQUAL(6, pinWriteCallCount); TEST_ASSERT_EQUAL(TEST_PIN, recordedPin); TEST_ASSERT_EQUAL(LOW, recordedVal); } int main(int argc, char **argv) { UNITY_BEGIN(); RUN_TEST(test_flash_3_times); UNITY_END(); return 0; }
额外测试扩展建议
如果需要验证电平变化的顺序,可以扩展Mock函数,用数组记录每次调用的电平值,再断言数组内容是否符合[HIGH, LOW, HIGH, LOW, HIGH, LOW]的预期。
内容的提问来源于stack exchange,提问作者Thomas J
相关产品推荐
相关产品推荐

