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

我目前正在为简单的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控制器代码,具体取决于您要测试的程序的哪个部分.它使用与生产代码完全相同的功能.

点赞