4

我目前正在用纯 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);
}

如您所见,测试和实现之间的代码有很多重复。

这是一个问题吗?我写错了我的测试吗?或者我不应该为这些低级的东西编写测试?

4

1 回答 1

2

测试代码的效率通常并不重要。这取决于您要测试的内容,但重复的代码可能表明存在设计缺陷。

在您的情况下,您也许可以将 mcp2515_read_register 函数分为两部分:一个创建结构,另一个处理 SPI 传输。

最佳的 OO 程序设计可能会涉及以下模块:

  • SPI 驱动只关心实际的通信。
  • CAN 控制器驱动程序只关心控制器的细节。
  • 来电者(“主要”或其他)。
  • CAN 控制器驱动程序的测试代码:替换 main。

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

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

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

于 2014-11-20T12:40:11.027 回答