【发布时间】:2010-11-06 21:27:13
【问题描述】:
您在对嵌入式系统特有的嵌入式软件进行单元测试时使用了哪些最佳实践?
【问题讨论】:
标签: unit-testing embedded
您在对嵌入式系统特有的嵌入式软件进行单元测试时使用了哪些最佳实践?
【问题讨论】:
标签: unit-testing embedded
嵌入式软件在过去 10 年中可能取得了长足的进步,但我们通常做了以下工作:
希望自从我上次这样做以来情况有所改善。我不希望我最大的敌人遭受这种痛苦。
【讨论】:
在 PC 环境中进行单元测试(使用 PC C 编译器编译代码并在 PC 单元测试框架中运行代码)可以获得很多好处,但有以下几个条件:
stdint.h 类型,例如uint16_t,而不是普通的unsigned int 等。我们遵循了这些规则,发现在 PC 单元测试框架中对应用层代码进行单元测试后,我们可以确信它运行良好。
PC平台单元测试的优势:
【讨论】:
嵌入式系统是一个广泛的话题,但总的来说,让我们将其视为结合了硬件和软件的特定用途产品。我的嵌入式背景来自手机,这只是所有嵌入式系统的一小部分。我会尽量在抽象方面保留以下几点:
尽可能抽象出硬件依赖关系。通过这种方式,您可以在模拟的“硬件”上运行单元测试,还可以测试各种难以在目标上测试的罕见/异常情况。为了防止抽象成本,您可以使用例如条件编译。
尽可能少地依赖硬件。
在模拟器或交叉编译器环境中运行的单元测试仍然不能保证代码在目标硬件上工作。您还必须在目标上进行测试。尽早对目标进行测试。
【讨论】:
您可能想查看 James W. Grenning 的 Test Driven Development for Embedded C。该书计划于 2010 年 8 月出版,但测试版书现已在The Pragmatic Bookshelf 上提供。
【讨论】:
这里是缺乏经验的声音,但这也是我最近一直在考虑的事情。在我看来,最好的方法是
A) 在 PC 环境中尽可能多地编写与硬件无关的应用程序代码,然后再将其写入目标,同时编写单元测试(首先在 PC 上执行此操作应该会有所帮助强迫你分离与硬件无关的东西)。通过这种方式,您可以使用您选择的单元测试器,然后以老式方式测试硬件相关的东西 - 使用 RS-232 和/或示波器以及 I/O 引脚发送与时间相关的数据,具体取决于它的运行速度.
B) 将它全部写在目标硬件上,但是有一个 make 目标来有条件地编译一个单元测试构建,该构建将运行单元测试并通过 RS-232 或一些输出结果(或可以分析结果的数据)其他手段。如果你没有很多内存,这可能会很棘手。
编辑 2009 年 7 月 3 日 我刚刚想到了如何对硬件相关的东西进行单元测试。如果您的硬件事件发生得太快而无法使用 RS-232 记录,但您不想手动筛选大量示波器数据来检查您的 I/O 引脚标志是否按预期上升和下降,您可以使用 PC带有集成 DIO 的卡(例如 National Instruments 的数据采集卡系列)来自动评估这些信号的时序。然后您只需要在您的 PC 上编写软件来控制数据采集卡与当前运行的单元测试同步。
【讨论】:
我们设法使用模拟器测试了相当多的硬件相关代码,我们使用 Keil 的模拟器和 IDE(不附属只是使用他们的工具)。我们编写模拟器脚本以我们期望它做出反应的方式驱动“硬件”,并且我们能够非常可靠地测试我们的工作代码。诚然,为某些测试建模硬件可能需要一些努力,但对于大多数事情来说,这工作得很好,并且允许我们在没有任何可用硬件的情况下完成很多工作。在访问硬件之前,我们已经能够在模拟器中接近完整的系统工作,并且一旦将代码放在真实的东西上,我们几乎没有需要处理的问题。这也可以显着加快代码的生成速度,因为一切都可以在 PC 上完成,使用更深入的调试器,同时模拟芯片而不是尝试在硬件上完成所有事情。
使其能够可靠地用于复杂的控制系统、存储器接口、定制 SPI 驱动 IC 甚至单显示器。
【讨论】:
这里有很多很好的答案,一些没有提到的事情是运行诊断代码以便:
【讨论】:
当我去年遇到这个问题时,我真的很想在嵌入式平台本身上进行测试。我正在开发一个库,我正在使用嵌入式平台的 RTOS 调用和其他功能。没有任何具体可用的东西,所以我根据我的目的调整了 UnitTest++ 代码。我在NetBurner 系列上编程,因为它有一个嵌入式 Web 服务器,所以编写一个基于 Web 的 GUI 测试运行程序来提供经典的 RED/GREEN 反馈非常简单。它turned out pretty well,现在单元测试更容易了,我对知道代码在实际硬件上工作更有信心。我什至使用单元测试框架进行集成测试。起初我模拟/存根硬件并注入该接口进行测试。但最终我编写了一些运行实际硬件的人在循环测试。事实证明,这是一种更简单的了解硬件的方法,并且可以轻松地从嵌入式陷阱中恢复。由于测试都是从 AJAX 回调到 Web 服务器运行的,因此陷阱仅作为手动调用测试的结果发生,并且系统总是在陷阱后几秒钟干净地重新启动。
NetBurner 足够快,写入/编译/下载/运行测试周期约为 30 秒。
【讨论】:
评估板上提供了许多嵌入式处理器,因此尽管您可能没有真正的 i/o 设备,但通常您可以在其中一种设备上执行大量算法和逻辑,通常带有硬件可通过 jtag 进行调试。无论如何,“单元”测试通常更多的是关于你的逻辑而不是你的 i/o。问题通常是让您的测试工件退出这些环境之一。
【讨论】:
在设备相关和设备无关之间拆分代码。可以对独立代码进行单元测试而不会有太多痛苦。依赖代码只需要手动测试,直到您拥有流畅的通信接口。
如果您正在编写通信接口,我很抱歉。
【讨论】: