如何为嵌入式代码编写单元测试?

6
我正在使用C++为基于Cortex-M4的微控制器编写软件。我有很多高度依赖机器的代码(驱动程序等)。而且,我有更高级别的代码,通过直接使用驱动程序与低级别代码密切相关。例如:低级部分是例如UART驱动程序,它非常硬件特定,而高级部分是基于UART的通信协议。(此软件在“裸机”上运行,即底层没有操作系统。)
目前,这些代码紧密耦合,因此无法进行单元测试。
我想让它可测试。
因此,我想创建低级部分的抽象,并使高级部分仅依赖于该抽象。然后,我可以创建抽象的模拟,用于单元测试,并创建一个真实的实现,可在微控制器上运行。
  • 这是正确的方法吗?
  • 我该如何创建这样的抽象层?
    我找到的大部分资料 强烈反对 在嵌入式系统中使用继承和虚函数。还有其他什么方法吗?

所以,总之,我想创建一个硬件抽象层(HAL),但我想知道怎么做?我应该在C++中使用虚继承,还是有其他更好的方法?


2
你所建议的抽象化将是一个硬件抽象层,这并不罕见,事实上非常合适。你可以在每个 HAL 上定义接口并实现它们。对于 Mocks,你只需实现该接口并提供所需的行为即可。 - Samer Tufail
1
如果您不想使用虚拟化,仍然可以有两个实现。由于您从未同时需要两者,请指示您的工具链构建和链接正确的实现。 - user4581301
1
通常的争论,除了性能影响之外,是通过使用函数指针,调用图不再是静态的。因此,在安全关键系统中,最大堆栈使用和分支覆盖等事项的静态工具辅助证明变得困难。- @Samer Tufail - doynax
1
@doynax:这是一个安全关键系统吗?如果是,那么您将面临一整套问题,其中动态内存是最重要的。 - Samer Tufail
1
@Samer Tufail:当然。不过我对楼主的应用程序一无所知。 - doynax
显示剩余3条评论
2个回答

6

对于C++,我建议使用接口。比如我们有一个名为HAL.hpp的文件,在其中定义了我们想要实现的纯虚函数:

class HAL
{
    virtual void func1() = 0;
    virtual void func2() = 0;
};

然后你可以让你的 Mock.cpp 实现这个功能,同时你也可以让一个 Real.cpp 实现同样的功能:

Mock.cpp:
class Mock : HAL
{
        virtual void func1(){ }
        virtual void func2(){ }
}

现在另外一种方式是在HAL.h中定义您的函数,但不提供实现如下:
void func1();
void func2();

你需要创建一个名为HAL.cpp的文件,并在其中添加你希望在目标设备上看到的功能。将所有内容作为名为HAL的库创建,然后将该库链接到主项目中。
现在是关于模拟和测试的部分。为你的测试创建一个单独的项目。添加你想要测试的源文件,但不要链接HAL库。相反,创建另一个源文件Mock.cpp,包含HAL.h并为其提供实现。这样,调用的是Mock的实现,而不是来自HAL库的功能。

3
将微控制器HAL与模拟HAL分别放在不同的文件中。对于微控制器,将微控制器HAL源文件包含在项目中。对于单元测试系统,请将模拟HAL源文件包含在项目中。
您还可以使用编译器宏定义在目标上进行测试,以切换模拟HAL的部分内容,并切换微控制器HAL的部分内容。
您甚至可以使用调试器在接口点处强制值以触发所有路径;使用代码覆盖工具进行此操作将让您知道是否已经执行了所有路径(如果需要MC/DC)。这有时是模拟硬件故障或异常情况的唯一方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接