c - 单元测试和实现之间的重复代码

标签 c unit-testing embedded tdd cmock

我目前正在用纯 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 Controller 驱动程序只关心 Controller 的细节。
  • 来电者(“主要”或其他)。
  • CAN Controller 驱动程序的测试代码:替换 main。

SPI 驱动程序将 spi_frame_t 声明为不透明类型,这是一个只与 SPI 数据和通信有关的结构。 SPI 驱动程序之外的任何人都不知道或不需要知道此结构的内容。我不知道回调函数是干什么的,但看起来不像是和SPI驱动有关的东西。它看起来更像是与调用 SPI 驱动程序的代码相关的东西。

CAN Controller 驱动程序包括 SPI 驱动程序。它从 SPI 驱动程序调用“构造函数”来创建帧,然后将帧传递给 SPI 通信例程。 CAN Controller 驱动程序与 SPI 功能没有紧密耦合。例如,重写您的 CAN Controller 代码是没有意义的,因为您在 SPI 中发现了错误。如果您想在另一个项目中重新使用 SPI 驱动程序,您也不需要 CAN Controller 才能使用 SPI。

测试用例会替换调用程序(“main”)或 CAN Controller 代码,具体取决于您要测试的程序部分。它使用与生产代码完全相同的功能。

关于c - 单元测试和实现之间的重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27039401/

相关文章:

c - 重新分配打印出错误

c - 将多维数组的一行作为参数传递

unit-testing - Grails:Groovy:无法解析类 grails.test.mixin.TestFor

php - 使用 HHVM (HipHop) 运行 phpunit 测试

c - 图映射资源信号量

c - 多线程代码中的结构内存布局

unit-testing - 在 ABAP 单元测试中模拟 sy-uname

c - 我在哪里可以找到任意编译器的对齐要求?

c++ - 递归函数中在堆上分配与在堆栈上分配

c - 十六进制的 unsigned long long 的值是多少