对使用 RTOS 的项目进行单元测试

Unit Testing a project that uses an RTOS

对于我的下一个嵌入式系统项目,我想采用单元测试。它在技术上可能不是测试驱动开发,但我至少想预先对单元测试进行检测并进行全面的单元测试。

我正在使用 IAR EWARM 工具链。我正在考虑使用 cmocka、unity 或 cunit。我正在学习使用 µC/OS-III 作为 RTOS。

这里是问题:单元测试如何与图片中的 RTOS 一起工作?例如:我应该禁用内核并将代码作为单线程应用程序进行单元测试并存根 all/most 内核调用,还是有更好的方法?

示例: 在 µC/OS-III 中,入口点仍然是主要的。从 main 调用任何初始化代码,然后调用 OSStart() 开始多任务处理。因此,当我是 运行 测试工具时,我无法调用 OSStart()

#ifdef UNIT_TEST
test_runner();
#else
OSStart(&err);
#endif

然后在任务中的所有应用程序代码中,我只需要模拟消息传递并延迟对内核的调用。

这是最好的方法吗?或者我会更适合启动内核,为我的测试运行器创建一个任务,然后 运行 所有任务都作为一个线程,或者是否有其他一些好的方法涉及从测试中产生其他任务线束。

您似乎对单元测试有误解。您的代码是否使用 RTOS 并不重要,因为单元测试涉及单独测试代码模块,即 C 函数。 RTOS 在您的测试期间不会运行。

单元测试还假定您正在根据一组定义代码功能的要求进行测试。 大多数单元测试的目标是能够提供各种形式的代码覆盖率。这包括语句、决策和多条件决策覆盖。

语句覆盖表明您已经对函数中的每一行代码进行了练习。

决策覆盖涉及显示所有条件的两边 (true/false)。

多条件决策覆盖率 (MCDC) 用于测试复杂决策,即 if (a && (b || c)) 并确保覆盖所有变化。 MCDC 测试通常仅限于非常关键的应用,例如航空电子设备,其中故障可能会导致灾难性后果。

子例程通常被存根,即被截获和控制,以证明每个子例程都按顺序调用并且传递的参数正确并且各种返回值正确运行。

我承认我对你提到的工具没有任何经验,但有许多商业单元测试工具可用,Cantata、LDRA TestBench、IBM Rational Test Real Time 和其他适合深度单元的工具测试。

RTOS 本身也有商业解决方案。我公司为 µC/OS-II 和 µC/OS-III.

提供现成的单元和集成测试包

斯科特 验证软件

从您自己的软件堆栈中隐藏某些抽象层对 RTOS 特定函数的调用通常是个好主意。如果您需要更改平台(包括 RTOS),这将为您提供更好的可移植性。只需在一处更改 API 调用即可。

进行这一步额外的抽象还有一个好处,这与这个答案相关:它使进行单元测试变得容易得多!为了使代码可链接,您可以模拟所有对 RTOS 函数的调用,以在开发系统上进行 运行 测试,并使用 API!根据您的需要,这些 模拟对象 可以只验证传递的参数是否符合预期。或者对于简单的 API 调用,您甚至可以实现一些功能来进一步扩展您自己代码的测试。

显然,这仍然不能使您测试具有所有依赖项的整个代码。我想对于嵌入式系统来说,这根本不可能。但与不对使用 RTOS API 调用的模块进行任何单元测试相比,它已经走了很长一段路。