unit testingembedded式软件

你在embedded式系统特有的embedded式软件unit testing中使用了哪些最佳实践?

embedded式软件在过去的十年中可能走过了很长的一段路,但是我们通常做了以下工作:

  • 对于不依赖于目标硬件的algorithm,我们只需要在非embedded式平台上构build和testingunit testing。
  • 对于那些确实需要硬件的东西,unit testing被有条件地编译成代码来使用任何可用的硬件。 在我们的例子中,目标是一个串口,将结果推送到另一个更有能力的机器上,在这台机器上检查testing的正确性。
  • 根据硬件的不同,有时可能会在非embedded式平台上虚拟出一个“虚拟”设备。 这通常包含另一个执行线程(或信号function)改变程序使用的内存。 用于内存映射I / O,但不是IRQ等。
  • 通常情况下,一次只能对整个代码的一小部分进行unit testing(由于内存限制)。
  • 为了testing时间敏感的东西,我们没有。 干净利落。 如果运行速度太慢,我们使用的硬件(8051和68302)并不总能正常工作。 这种debugging最初必须用CRO(示波器)和(当我们有更多的钱)ICE(在线仿真器)来完成。

自从我上次做了这个以后,希望情况有所改善。 我不希望我最大的敌人感到痛苦。

PC环境下的unit testing(用PC C编译器编译代码,并在PCunit testing框架中运行代码)可以获得很多好处,其中有几个附带条件:

  1. 这不适用于testing您的低级代码,包括启动代码,RAMtesting,硬件驱动程序。 你将不得不使用更直接的unit testing。
  2. 您的embedded式系统的编译器必须是值得信赖的,所以您不需要寻找编译器创build的错误。
  3. 你的代码必须是分层的体系结构,硬件抽象。 您可能需要为您的PCunit testing框架编写硬件驱动程序模拟器。
  4. 你应该总是使用stdint.htypes,如uint16_t而不是普通的unsigned int

我们遵循这些规则,发现在PCunit testing框架中对应用层代码进行unit testing之后,我们可以有很好的信心。

PC平台上unit testing的优点:

  1. 由于添加了unit testing框架,您不必面临embedded式平台上ROM空间不足的问题。
  2. 在PC平台上,编译链接运行周期通常更快,更简单(避免可能需要几分钟的“写/下载”步骤)。
  3. 你有更多的可视化进程的选项(一些embedded式应用程序有限的I / O外设),存储input/输出数据进行分析,运行更耗时的testing。
  4. 您可以使用现有的基于PC的unit testing框架,这些框架不适用于embedded式平台。

embedded式系统是一个广泛的话题,但总的来说,让我们把它看作是一个结合了硬件和软件的特定用途的产品。 我的embedded式背景是来自手机,这只是所有embedded式系统的一小部分。 我会尽量在抽象方面保留以下几点:

  • 尽可能抽象出硬件依赖关系。 通过这种方式,您可以在嘲弄的“硬件”上运行unit testing,还可以testing各种罕见/特殊的情况,这些情况在目标上难以testing。 为了防止抽象成本,可以使用例如条件编译。

  • 尽可能less的依靠硬件。

  • 在仿真器或交叉编译器环境中运行的unit testing仍不能保证代码在目标硬件上工作。 你也必须testing目标。 尽早testing目标。

您可能想查看James W. Grenning的embedded式Ctesting驱动开发 。 这本书计划于2010年8月发行,但现在已经在“实用书架 ”上提供了该书。

这里没有经验的声音,但是这也是我最近一直在思考的问题。 在我看来,最好的方法也是

A)尽可能在硬件独立的应用程序代码中写下你在PC环境下的代码,然后再写到目标上,同时编写unit testing(先在PC上执行这个操作应该可以强制你分开硬件独立的东西)。 通过这种方式,您可以使用您select的unit testing仪,然后以旧式的方式testing硬件相关的东西 – 使用RS-232和/或示波器和I / O引脚发信号通知与时间有关的数据,具体取决于运行速度。

B)把它全部写在目标硬件上,但有一个目标是有条件地编译一个unit testing版本,它将运行unit testing,并通过RS-232或其他方式输出结果(或可以分析结果的数据)。 如果你没有很多的内存,这可能是棘手的。

编辑7/3/2009我只是想了解如何unit testing硬件相关的东西。 如果您的硬件事件发生得太快而无法用RS-232进行logging,但是您不希望手动筛选大量示波器数据检查,以查看I / O引脚标志是否像预期的那样上升和下降,则可以使用PC (如NI的数据采集卡系列)来自动评估这些信号的时序。 然后,您只需在PC上编写软件,以控制数据采集卡与当前正在运行的unit testing同步。

我们设法使用模拟器获得相当多的硬件相关代码,我们使用Keil的模拟器和IDE(不附属于使用他们的工具)。 我们编写模拟器脚本来驱动“硬件”,并以我们期望的方式作出反应,并且能够非常可靠地testing我们的工作代码。 当然,对于某些testing来说,可能需要花费一些努力来对硬件进行build模,但是对于大多数情况来说,这可以很好地工作,并且可以在没有任何硬件的情况下完成很多工作 在访问硬件之前,我们已经能够在模拟器中完成几乎完整的系统工作,并且一旦把代码放在真实的东西上,几乎没有什么问题需要处理。 这也可以显着加快代码的生成速度,因为在模拟芯片的同时,可以在PC上使用更深入的debugging器,并尝试在硬件上执行所有操作。

已经得到了这个可靠的工作,用于复杂的控制系统,存储器接口,自定义SPI驱动IC甚至单显示器。

这里有很多很好的答案,有些没有提到的东西是为了:

    loggingHAL事件(中断,总线消息等)
    有代码来跟踪你的资源,(所有活动的信号量,线程活动)
    使用捕获ram机制将堆和内存内容复制到持久性存储(硬盘或等价物),以检测和debugging死锁,活锁,内存泄漏,缓冲区溢出等。

当我去年面对这个时候,我真的想在embedded式平台上进行testing。 我正在开发一个库,我正在使用embedded式平台的RTOS调用和其他function。 没有什么具体的东西,所以我改编了UnitTest ++代码来达到我的目的。 我在NetBurner系列上编程,由于它有一个embedded式Web服务器,所以编写一个基于Web的GUItesting运行器,给出经典的RED / GREEN反馈非常简单。 结果非常好 ,现在unit testing更容易,而且我知道代码在实际的硬件上工作,我感到更加自信。 我甚至使用unit testing框架来做集成testing。 起初,我嘲笑/存根硬件,并注入该接口进行testing。 但是最终我会写一些运行实际硬件的man-in-the-looptesting。 事实certificate,这是一个更简单的方法来了解硬件,并有一个简单的方法来从embedded式陷阱中恢复。 由于testing全部从AJAXcallback运行到Web服务器,所以陷阱只发生在手动调用testing的结果,系统总是在陷阱几秒后干净地重新启动。

NetBurner速度足够快,写入/编译/下载/运行testing周期约为30秒。

在评估板上有许多embedded式处理器,所以尽pipe你可能没有真正的I / O设备,但是通常你可以在这些types的东西中执行大量的algorithm和逻辑,通常可以通过硬件debuggingJTAG。 而“单元”testing通常更多的是关于你的逻辑,而不是你的I / O。 问题通常是让您的testing工件退出其中一个环境。

在设备相关和设备无关的情况下拆分代码。 独立的代码可以进行unit testing,没有太多的痛苦。 依赖代码只需要手动testing,直到你有一个stream畅的通信接口。

如果你正在编写通信界面,我很抱歉。