如何编写机器人(和其他机械设备)的单元测试?


22

我是高中机器人俱乐部的成员,并且负责对机器人进行编程。我不断听到各种各样的成年人的建议是,我应该编写单元测试来帮助验证我的代码。代码基础变得越来越大,我同意单元测试对帮助我更快地发现错误确实很有帮助。

但是,我不完全确定如何实现这一目标。据我所知,单元测试是通过采用一个函数(或代码的子系统)并向其提供一组输入以确保每次输出都具有相同的输出来完成的。我目前拥有的代码不会进行繁琐的数据处理,而是直接操作机器人上的硬件组件。大多数复杂性来自确保电子设备健全,当前代码与机器人上的实际硬件相匹配等等。通常,我只能通过将代码加载到机器人本身来查看是否存在问题,并尝试运行它。

通过扩展,如何为旨在操作任何机械设备的代码编写单元测试?在我看来,您只能通过肉眼观察机器的运行来捕获错误。

还是我只是误解了单元测试应该如何工作?

如果重要的话,这里是代码,它是用C ++编写的,我正在参加FRC

Answers:


21

您将需要模拟硬件层以进行此测试。这样的想法是,您无需与实际的硬件对话,而是与可以控制的伪造硬件对话,然后用来验证您的代码是否正常工作。

不幸的是,您必须克服一些问题:

  • 用相对低级的语言模拟事物更加困难(因此,需要做更多的工作)
  • 模拟硬件级别的东西更加困难(因此,需要做更多的工作)

另外,自动化的单元测试的大部分价值在于能够在编写原始代码后随时运行测试以长时间捕获回归错误。在这类竞赛中,竞赛结束后根本不会使用您的代码,因此您不会真正从测试中获得大部分价值。考虑到为您的特定案例添加测试有多困难,最好花些时间进行手动测试并专注于比赛的功能。


1
好答案。特别是关于以下事实:竞赛结束后将不再使用该代码,并且在编写测试后,自动单元测试的巨大好处就会显现出来。如果发现一遍又一遍地运行相同的测试,则可以考虑使某些测试自动化。但是直到发生这种情况之前,没有多大意义。
达伍德说要恢复莫妮卡(Monica)

完全不需要模拟硬件。如果机器人已记录日志,请运行测试程序并观察日志。最终测试需要观察日志中的“向左转”,应该与机器人向左转相一致。您将需要编写一个测试工具来模拟输入设备-将输入设备代码尽可能靠近硬件层进行
挂接

4
@DavidWallace有点值得深思的是,在使用TDD / BDD时,单元测试的好处会立即显现出来。首先,允许立即可靠地重构代码,其次,通过鼓励将实现方式限制为满足测试所需的最小实现方式。
S.Robins

4
@mattnz不好的主意,我从经验中知道。如果要测试的代码非常失败并且机械手崩溃在墙上,破坏了xxxx $硬件,该怎么办?
stijn 2012年

2
@mattnz:我们的机器人大约2英尺乘3英尺乘4英尺,重约150磅。套件/注册每年的费用为5,000美元,我们通常会再筹集5到10k来购买其他零件。最坏的情况可能会花费超过$ 10;)
Michael0x2a 2012年

10

我可以想到您需要考虑的几件事。首先是使硬件访问层尽可能薄,即使这意味着为其创建基本的包装类型的层。这为您提供了两个优势。第一个是它使您可以将代码的特定于硬件的行为与硬件访问本身隔离开,这意味着您可以测试直到硬件通讯最底层的所有内容,而无需访问硬件本身。

例如,如果您需要设计基于I2C的信令协议,则可以测试代码是否生成正确的I2C信号,而无需将硬件连接到测试中。

对于对实际硬件的调用,您可以通过模拟硬件层来测试它们的行为是否正确,这是保持非常薄的硬件层真正奏效的地方,因为您可以减少模拟过程,从而只需要处理所需的最小功能即可。实际上是针对硬件的,但是您不一定需要自己测试单个信号,因为所有信号都应该可以在更高级别上进行测试。这意味着您可以使用模拟来检查是否对导致将信号发送到硬件的特定硬件方法进行了调用。如果您需要轮询硬件,则您的模拟只需要能够触发代码中的事件或方法,因为同样,您的返回信号也应在更高的层进行处理。

这基本上与Oleksi在他的回答中所说的相吻合,因为通常需要更多的工作来模拟硬件级的东西,但是如果您保持尽可能精简的最小代码/调用层并不难,硬件。

当您的代码通过了所有测试后,您仍然需要进行一系列手动测试,以确保您在硬件层正确地进行了调试。

除了模拟和分层之外,我想到的另一件事是使用测试优先的开发实践。本质上,您将需求编码为测试标准,并且将实现基于测试。这将帮助您确保将实现代码降至最低,同时确保所有测试用例都在推动开发工作。通过在您可能会因为“仅仅因为”而被诱使去做的其他潜在非关键代码上浪费太多时间,测试首先可以帮助您保持专注,并且可以在调试时更轻松地更改代码,使用起来也一样您的单元测试和模拟。众所周知,通过硬件调试软件错误非常复杂,并且会浪费大量时间,您会发现自己在其他任务上花费了更多时间。


2

我可以告诉你他们如何在飞行模拟器上做到这一点

首先,如果您仅向程序员提出这个问题,您将只会得到一半的答案,因此,您可能应该将其交叉张贴在http://electronics.stackexchange.com上。

我没有使用机器人做任何工作,但是我确实花了5年的时间在飞行模拟器上做硬件,所以我可以告诉您它们的架构是如何工作的。

硬件层笨

它包含一个基本界面,您可以在其中调整简单的输入/输出值并设置模拟信号的插值断点。当您使用“新”硬件时,几乎不需要校准就可以正常工作,但是随着时间的流逝,零件将遭受机械磨损,需要进行调整。

校准是一个简单的表格,其中包含最小/最大值之间的分段。为了测量这些输入,通常使用一个伺服器(例如线性电位计,传感器,加速度计等)。或在使用仪器的情况下,您只需直观地判断准确性并进行调整,直到校准完毕。

软件层相反

一切都很复杂且相互关联,因此隔离一些变量以测试功能很重要。无需费心思量场景,因为运行一些现实的场景以收集数据要容易得多。运行测试时,基本上是在根据当前输出测量存储的数据。

在飞行模拟器上,这称为QTG(资格测试指南)。它的核心是在二维网格上绘制数据,其中一维是时间,另一维是输出。

信不信由你,这就是他们开发模型的本质。真实的飞机配备有大量的传感器,并在受控场景中飞行。由于无需人工干预即可驱动所有控件,因此计算机可以运行测试(即模拟飞行本身)并比较数据。

即使创建的机器人技术规模大不相同,其原理也相同。传统方法是完全切断硬件和软件层,以便可以分别进行测试。硬件输入通过伺服收集,并通过独立的接口进行设置。可以通过独立测量和比较可能会发往硬件的信号并将其与已知的“良好”数据作图来设置/读取软件输入。

只要结果是可预测的,可测量的和可重复的,测试本身并不一定需要很复杂。


1

如前所述,模拟并存根硬件部分。例如,如果您有机器人的接口,则可以从该接口继承,然后对其进行简单的存根实现。然后,您可以测试是否已按预期调用存根实现。如果是预期的功能或预期的参数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.