使用嵌入式硬件进行测试自动化
有没有人成功地在嵌入式硬件上实现了自动化测试的成功?
具体来说,我正在考虑使硬件层模块的单元测试自动化。我们需要对我们的硬件层代码有更大的信心。我们的许多项目都使用中断驱动的定时器,ADC,串行io,串行SPI设备(闪存)等。
这是否值得付出努力?
我们通常的目标是:
处理器:8或者16位微控制器(一些DSP处理器)
语言:C(有时为c ++)。
解决方案
当然。在汽车行业,我们为每个新产品使用价值100,000美元的定制测试仪,以验证硬件和软件是否正常运行。
但是,开发人员还构建了一种便宜的(低于$ 1,000)测试仪,其中包括一堆USB I / O,A / D,PWM输入/输出等,并且可以在工作站上使用脚本或者专用的HIL / SIL测试软件例如MxVDev。
硬件在环(HIL)测试可能就是意思,它只涉及连接到设备I / O的一些USB硬件I / O,计算机上的软件正在对此进行测试。
是否值得取决于。
在高可靠性行业(飞机,汽车等)中,客户指定了非常广泛的硬件测试,因此我们必须拥有它才能获得标书。
在消费行业中,对于非复杂项目,通常不值得这样做。
但是,对于任何一个涉及多个程序员的项目,在硬件上进行每晚一次的回归测试实在是一件很不错的事情,很难正确地模拟硬件达到所需的程度,以使我们对软件测试足够满意。
当问题进入构建时,测试将立即显示。
通常,我们同时执行黑盒和白盒测试,设备上运行着诊断代码,这些代码可让我们监视硬件中的信号和内存(它们可能只是调试器,或者是我们编写的可对硬件上的消息做出反应的代码)公交车)。这将是白盒测试,我们可以在其中查看内部发生的情况(甚至导致某些事情发生,例如严重的内存错误,如果不自行引入错误就无法进行测试)。
我们还运行了许多"黑匣子"测试,这些测试忽略了诊断路径,仅刺激/读取了I / O。
对于便宜得多的设置,我们可以购买带有USB和/或者以太网(例如Atmel UC3系列)的100美元微控制器板,我们可以将其连接到设备并运行基本测试。
当项目完成,在CD中存储几个工作板,测试器和一整套软件时,它对于产品维护特别有用。当我们需要进行修改或者调试问题时,很容易将其全部备份并在知道一些主要功能(不受测试影响)后(在测试之后)对其进行处理。
-亚当
嵌入式项目的单元测试相当困难,因为它通常需要外部刺激和外部测量。
我们已经成功地开发了基本命令的外部串行协议(rs232或者udp或者tcpip消息),用于在低级驱动程序中通过调试日志记录硬件,以查找错误条件或者什至是轻微异常条件(尤其是用于极限检查)
但是一旦开发完成,我们便可以在需要时在每次构建后运行测试。它一定会为我们提供质量更高的产品。
是的。我已经取得了成功,但这不是一个可以直接解决的问题。简而言之,这是我的团队所做的事情:
- 使用自制的C单元测试框架定义了各种单元测试。基本上,只有大量的宏,其中大多数被命名为
TEST_EQUAL
,TEST_BITSET
,TEST_BITVLR
等。 - 编写了一个启动代码生成器,该生成器接受了这些已编译的测试并将它们编排到执行环境中。这只是一个执行常规启动例程的小型驱动程序-但它不会进入控制循环,而是执行测试套件。完成后,它将最后一个要运行的套件存储在闪存中,然后重置CPU。然后它将运行,然后运行下一个套件。这是为了在套件死亡时提供隔离。 (但是,我们可能要禁用此功能以确保模块能够协作。但这是集成测试,而不是单元测试。)
- 各个测试将使用串行端口记录其输出。这对于我们的设计是可以的,因为串行端口是免费的。如果我们所有的IO都被消耗了,我们将必须找到一种存储结果的方法。
有效!很高兴能拥有。使用我们的自定义数据记录器,我们可以单击"测试"按钮,几分钟后,我们将获得所有结果。我强烈推荐它。
已更新以阐明测试驱动程序的工作方式。
如果目标是制造测试(确保模块正确组装,没有意外的短路/开路/等),则应首先关注测试电缆和连接器,然后再进行插口和焊接连接,然后是PCB本身。可以通过找到将每条线的高电平驱动到相邻的低线的访问模式(反之亦然),然后读回这些线的值,来测试这些项目的短路和断开状态。
在不了解硬件详细信息的情况下,很难具体说明,但是大多数嵌入式处理器都可以将I / O引脚设置为GPIO模式,从而简化了这种测试。
如果我们不在PCA上进行钉床测试,则此测试应被视为新制造电路板的强制性第一步。
如果目标是测试低级驱动程序代码,则可能需要使用环回电缆或者多个互连的单元来创建某种测试夹具,以使我们可以练习每个驱动程序。将一块具有良好性能的软件的电路板与运行开发版本的电路板配对,将使我们能够测试通信协议的回归等。
具体的测试策略取决于我们要测试的硬件。例如,可以通过呈现已知波形并转换一系列样本,然后检查适当的范围,频率,平均值等来测试ADC。
我发现这种类型的测试在过去非常有价值,这使我可以放心地修改和改进驱动程序代码,而不必担心破坏现有应用程序。
是的,尽管我一直有一个可用于测试I / O的串行端口,但我还是这样做。
通常很难使设备完全保持不变。一些测试需要注释掉一行或者添加一个呼叫,例如与看门狗打交道。
恕我直言,这比根本没有单元测试要好。当然,我们还需要进行完整的集成/系统测试。
是的。
难度取决于我们要测试的硬件类型。正如其他人之前所说,问题将是我们需要应用的外部刺激的复杂性。外部刺激可能最好通过某种外部测试装置来实现(如Adam Davis所描述的)。
但是,要考虑的一件事就是我们要验证的东西。
极具诱惑力的是假设要验证硬件和固件的交互作用,那么我们实际上别无选择,只能直接应用外部刺激(即,将DAC应用于所有ADC输入等)。但是,在这些情况下,我们真正想测试的极端情况经常会遇到计时问题(例如,在执行函数foo()时出现中断),这在测试中非常困难。一种有意义的方式,甚至很难从中获得有意义的结果。 (即,我们进行此测试的前10万次很好。最后一次运行它失败了,为什么?!?)
但是,硬件验证应单独进行。完成此操作后,除非定期更改(通过可下载的fpga映像等),否则我们应该能够假定硬件可以正常工作,并且可以纯粹测试固件。
因此,在这种情况下,我们可以集中精力验证用于处理外部刺激的算法。例如,以固定值调用ADC转换例程,就好像它们直接来自ADC。这些测试是可重复的,因此是有益的。他们将需要特殊的测试版本。
测试设备的通信路径将相对简单,并且不需要特殊的代码构建。
在嵌入式系统上进行自动化测试,我们取得了良好的结果。我们已经以高级(易于编程和调试)语言编写了测试,这些语言可以在专用测试机上运行。这些测试通常会进行完整性检查或者向设备中生成随机输入,然后检查行为是否正确。生成和维护这些测试有很多工作。我们设计了一个框架,然后让实习生自己进行测试。
这不是一个完美的解决方案,测试肯定容易出错,但是最重要的部分是改善现有的覆盖范围。找到最大的孔并设计一些东西以自动方式覆盖它,即使它不是完美的或者无法覆盖整个功能。稍后,当我们涵盖所有内容时,我们可以返回并解决最差的覆盖范围或者最关键的功能。
要考虑的一些事情:
- 固件错误的代价是什么?在现场更新固件有多容易。
- 我的测试提供什么样的承保范围?这是简单的健全性检查吗?它是否具有足够的可配置性,可以测试许多不同的场景?
- 一旦测试失败,我们将如何重现该值以对其进行调试?我们是否记录了所有设备和测试设置,以便可以消除尽可能多的变量?设备配置,固件版本,测试软件版本,所有外部输入,所有观察到的行为?
- 我们要针对什么进行测试?规范是否对要测试的设备的预期行为是否足够清晰,或者我们是否正在根据代码认为的功能进行验证?