有没有人成功地直接在嵌入式硬件上进行自动化测试?
具体来说,我正在考虑为硬件层模块自动执行一系列单元测试。我们需要对我们的硬件层代码有更大的信心。我们的很多项目都使用中断驱动定时器、ADC、串行 io、串行 SPI 设备(闪存)等。
这还值得努力吗?
我们通常针对:
处理器:8 位或 16 位微控制器(一些 DSP 的东西)
语言:C(有时是 c++)。
有没有人成功地直接在嵌入式硬件上进行自动化测试?
具体来说,我正在考虑为硬件层模块自动执行一系列单元测试。我们需要对我们的硬件层代码有更大的信心。我们的很多项目都使用中断驱动定时器、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 被激发/读取。
对于更便宜的设置,您可以获得 100 美元的带有 USB 和/或以太网的微控制器板(例如 Atmel UC3 系列),您可以将其连接到您的设备并运行基本测试。
它对产品维护特别有用——项目完成后,将一些工作板、测试仪和一整套软件存储在 CD 上。当您需要进行修改或调试问题时,很容易将其全部备份并使用一些知识(测试后)主要功能不受您的更改影响。
-亚当
是的。我取得了成功,但这不是一个急需解决的问题。简而言之,这是我的团队所做的:
使用自制的 C 单元测试框架定义了各种单元测试。基本上,只有很多宏,其中大部分被命名为TEST_EQUAL
、TEST_BITSET
、TEST_BITVLR
等。
编写了一个引导代码生成器,它采用这些编译的测试并将它们编排到执行环境中。它只是一个执行我们正常启动例程的小驱动程序——但它不是进入控制循环,而是执行一个测试套件。完成后,它将最后一个要运行的套件存储在闪存中,然后重置 CPU。然后它将运行下一个套件。这是为了在套件死亡时提供隔离。(但是,您可能希望禁用此功能以确保您的模块能够配合。但这是一个集成测试,而不是一个单元测试。)
个别测试将使用串行端口记录其输出。这对我们的设计来说是可以的,因为串口是空闲的。如果您的所有 IO 都被消耗,您将不得不找到一种方法来存储您的结果。
有效!拥有它真是太好了。使用我们的自定义数据记录器,您可以点击“测试”按钮,几分钟后,您将获得所有结果。我强烈推荐它。
更新以阐明测试驱动程序的工作原理。
是的。
难度取决于您要测试的硬件类型。正如其他人之前所说,问题将是您需要应用的外部刺激的复杂性。外部刺激可能最好通过一些外部测试装置来实现(正如亚当戴维斯所描述的那样)。
但是,要考虑的一件事就是您要验证的内容。
很容易假设要验证硬件和固件的交互,那么您实际上别无选择,只能直接应用外部刺激(即,将 DAC 应用到所有 ADC 输入等)。但是,在这些情况下,您真正想要测试的极端情况通常会受到时间问题的影响(例如,当您执行函数 foo() 时会出现中断),这将非常难以测试一种有意义的方式——甚至更难从中获得有意义的结果。(即。我们运行这个测试的前 100K 次很好。我们最后一次运行它失败了。为什么?!?)
但是硬件的验证应该单独进行。完成此操作后,除非它定期更改(通过可下载的 fpga 映像等),否则您应该能够假设硬件可以正常工作并纯粹测试您的固件。
因此,在这种情况下,您可以专注于验证用于处理外部刺激的算法。例如,使用固定值调用您的 ADC 转换例程,就好像它们直接来自您的 ADC 一样。这些测试是可重复的,因此是有益的。不过,他们将需要特殊的测试版本。
测试设备的通信路径将相对简单,不需要特殊的代码构建。
我们在嵌入式系统上进行了自动化测试,取得了不错的成绩。我们有在专用测试机器上运行的高级(易于编程和调试)语言编写的测试。这些测试通常会进行完整性检查或生成随机输入到设备中,然后检查正确的行为。生成和维护这些测试需要做很多工作。我们设计了一个框架,然后让实习生自己进行测试。
这不是一个完美的解决方案,测试肯定容易出错,但最重要的部分是改进现有的覆盖漏洞。找到最大的洞并设计一些东西以自动方式覆盖它,即使它不完美或不会覆盖整个功能。稍后,当您的所有内容都被覆盖时,您可以回来解决最差的覆盖范围或最关键的功能。
需要考虑的一些事项:
如果您的目标是测试您的低级驱动程序代码,您可能需要创建某种测试夹具,使用环回电缆或多个互连单元来允许您运行每个驱动程序。将具有已知良好软件的电路板与运行开发版本的电路板配对,将允许您测试通信协议等方面的回归。
具体的测试策略取决于您要测试的硬件。例如,可以通过呈现已知波形并转换一系列样本来测试 ADC,然后检查适当的范围、频率、平均值等。
过去我发现这种类型的测试非常有价值,让我可以自信地修改和改进驱动程序代码,而不必担心破坏现有应用程序。
是的,我这样做了,尽管我一直有一个可用于测试 I/O 的串行端口。
通常很难让设备完全保持原样。有些测试需要注释掉一行或添加一个调用,例如处理看门狗。
恕我直言,这总比没有单元测试好。当然,您还需要进行完整的集成/系统测试。
单元测试嵌入式项目非常困难,因为它通常需要外部刺激和外部测量。
我们已经成功地开发了一个外部串行协议(rs232 或 udp 或 tcpip 消息),其中包含基本命令,用于在低级驱动程序中通过调试日志来执行硬件,以寻找错误条件甚至轻微异常条件(尤其是用于限制检查)
但是一旦开发完成,如果需要,我们就可以在每次构建后运行测试。它绝对可以让您提供更优质的产品。
如果您的目标是制造测试(确保模块正确组装,没有意外短路/开路/等),您应该首先关注测试电缆和连接器,然后是插座和焊接连接,然后是 PCB 本身。这些项目都可以通过查找驱动每条单独线路高而其相邻线路低(反之亦然)的访问模式来测试短路和开路,然后读回线路的值。
如果不了解硬件的更多细节,很难更具体,但大多数嵌入式处理器可以将 I/O 引脚设置为 GPIO 模式,从而简化此类测试。
如果您没有在 PCA 上执行针床测试,则应将此测试视为新制造电路板的强制性第一步。
我知道这已经过时了,但也许它会有所帮助。是的,你可以做到,但这取决于你想在你想要的解决方案上投资多少。两年多以来,我一直致力于 AUTOSAR 的 MCAL 层的测试和验证。在软件测试方面,这是您可以获得的最低水平。这是一种组件级别的测试。有些人可能称它为单元级别,但它比这略高,因为我们正在测试 MCAL 组件的 API。诸如:ADC、SPI、ICU、DIO 等。
使用的解决方案涉及: - 在目标 micro 上运行的测试框架 - 一个 dSPACE 盒,用于在需要时向目标提供和读取信号 - 通过 Vector CANape 进行 XCP 访问以触发测试执行和结果收集 - python 框架执行测试控制和结果验证
测试用例是用 C 语言编写的,它们与被测软件一起闪现到目标上。这是一个黑盒测试,因为我们没有以任何方式改变 MCAL 的实现。而且我认为甚至没有触及启动顺序。空闲任务用于连续检查标志的状态,该标志是开始执行测试的信号。一个 10 毫秒的任务用于实际运行测试。测试用例实际上是一个开关用例。此开关中的每个案例都是一个测试步骤。Python 在测试步骤级别触发了测试执行。这种方法的一个好处是可以重复使用具有不同参数的步骤。这个测试控制,执行什么以及如何执行,是由 Python 通过一个测试控制数据结构完成的,该结构充当测试实现与测试触发和评估机制之间的 API。这就是 CANape 的用途。设置要执行的测试并读取测试结果。通过测试步骤获得的每个值都存储在数据结构的数组部分中。测试步骤本身不涉及任何验证,因为目标被认为是测试环境的不可信组件。验证是由 Python 根据测试规范完成的。Python 正在解析这些规范,并能够自动创建测试触发脚本,包括每个测试步骤的验证标准。每个测试用例的规范是一系列测试步骤描述及其验证标准。其中一些步骤是与 dSPACE 相关的步骤。例如,一个步骤是初始化一些东西,并要求在已经配置的通道上捕获一些边缘,
A cheaper solution would involve using an in-house board instead of the dSPACE equipment. To some extent, even a programmable signal generator can be used, but that would not help if you need to validate signals output-ed by the target.