我目前正在为简单的C中的嵌入式平台开发一些低级驱动程序.我使用unity cmock作为单元测试框架.
然而,在编写低级别的东西时,我经常会遇到以下模式:
测试:
void test_mcp2515_read_register(void)
{
spi_frame_t expected_frame = {{0}};
expected_frame.tx_length = 2;
expected_frame.rx_length = 3;
expected_frame.tx_data[0] = MCP2515_READ_CMD;
expected_frame.tx_data[1] = TEST_ADDR;
expected_frame.callback = callback_test;
spi_transmit_ExpectAndReturn(expected_frame, true);
mcp2515_read_register(TEST_ADDR, callback_test);
}
执行:
void mcp2515_read_register(uint8_t addr, spi_callback callback)
{
spi_frame_t frame = {{0}};
frame.tx_length = 2;
frame.rx_length = 3;
frame.tx_data[0] = MCP2515_READ_CMD;
frame.tx_data[1] = addr;
frame.callback = callback;
spi_transmit(frame);
}
正如您所看到的,测试和实现之间的代码之间存在很多重复.
这是一个问题吗?我写错了吗?或者我不应该为这个低级别的东西打扰测试吗?
最佳答案 测试代码的效率通常并不重要.这取决于您要测试的内容,但重复的代码可能表明存在设计缺陷.
在您的情况下,您可能将mcp2515_read_register函数分为两部分:一部分用于创建结构,另一部分用于处理SPI传输.
最佳的OO程序设计可能涉及以下模块:
> SPI驱动程序仅关注实际通信.
> CAN控制器驱动程序仅关注控制器的细节.
>呼叫者(“主要”或其他).
> CAN控制器驱动程序的测试代码:替换main.
SPI驱动程序将spi_frame_t声明为opaque类型,这是一种仅关注SPI数据和通信的结构. SPI驱动程序外部没有人知道或需要知道此结构的内容.我不知道回调函数的功能,但它看起来与SPI驱动程序无关.它看起来像是与调用SPI驱动程序的代码相关的东西.
CAN控制器驱动程序包含SPI驱动程序.它从SPI驱动程序调用“构造函数”来创建一个帧,然后将帧传递给SPI通信例程.然后,CAN控制器驱动程序与SPI功能没有紧密耦合.例如,重写CAN控制器代码没有意义,因为您在SPI中发现了一个错误.如果您想在另一个项目中重复使用SPI驱动程序,也不需要CAN控制器才能使用SPI.
测试用例要么替换调用者(“main”),要么替换CAN控制器代码,具体取决于您要测试的程序的哪个部分.它使用与生产代码完全相同的功能.