如何对Arduino代码进行单元测试?

224

我希望能够对我的Arduino代码进行单元测试。理想情况下,我希望能够运行任何测试而不必上传代码到Arduino。有哪些工具或库可以帮助我完成这个任务?

目前正在开发一款Arduino模拟器(Arduemu),这可能会有所帮助,但它似乎还没有准备好供使用。

Atmel的AVR Studio包含了一个芯片模拟器,这可能是有用的,但我不知道如何将其与Arduino IDE配合使用。


1
这个问题在2011年的Arduino论坛上有另一个帖子,链接为http://arduino.cc/forum/index.php?action=printpage;topic=54356.0。 - Jakob
1
感谢@Jakob。该线程中提到了一个Arduino模拟器(页面底部还有其他可能有用的链接):http://www.arduino.com.au/Simulator-for-Arduino.html - Matthew Murdoch
6
很遗憾,这只适用于Windows系统,我希望能找到一种在没有任何闭源或硬件依赖的情况下,通过命令行编译和运行Arduino代码的方法。 - Jakob
4
5年后的小更新:Simavr 仍然非常活跃,并且自提出该问题以来已经有了很大的改进,因此我认为它应该被推到更靠前的位置。它可能是回归测试、场景测试以及单元测试的合适工具。这样,你测试的代码就与目标硬件上的代码“相同”。 - zmo
1
现在有一个适用于此目的的GitHub操作,我是其作者。 - Ian
显示剩余2条评论
20个回答

5

5
我在编写Arduino代码时使用Searduino。Searduino是一个Arduino模拟器和开发环境(Makefiles,C代码...),可让您使用喜欢的编辑器轻松进行C / C ++黑客活动。您可以导入Arduino草图并在模拟器中运行它们。
Searduino 0.8的屏幕截图:http://searduino.files.wordpress.com/2014/01/jearduino-0-8.png Searduino 0.9将发布,并且视频将在最后的测试完成后录制...大约一两天。
在模拟器上进行测试不能视为真正的测试,但它确实帮助我找到了很多愚蠢/逻辑错误(例如忘记执行pinMode(xx, OUTPUT)等)。
顺便说一下:我是Searduino的开发人员之一。

5
保持硬件特定代码与其他部分分离或抽象出来,这样您就可以在任何您熟悉且具备良好工具的平台上测试和调试更大的“剩余”部分。基本上,尝试从尽可能多的已知可行的构建块中构建尽可能多的最终代码。剩下的硬件特定工作将会更加容易和快速。您可以通过使用现有的模拟器和/或自己模拟设备来完成它。然后,当然,您需要以某种方式测试真正的东西。根据情况,这可能很难自动化(即谁或什么将按下按钮并提供其他输入?谁或什么将观察和解释各种指示器和输出?)。

3
有一个名为ncore的项目,它为Arduino提供了本地核心,并允许您编写Arduino代码的测试。
从项目描述中可以得知:
本地核心允许您在PC上编译和运行Arduino草图,通常不需要进行修改。它提供了标准Arduino函数的本地版本,以及命令行解释器,以便为您的草图提供通常来自硬件本身的输入。
另外,在"what do I need to use it" section上也有相关说明:
如果要构建测试,您需要从http://cxxtest.tigris.org获取cxxtest。 NCORE已经与cxxtest 3.10.1进行过测试。

这是一个有趣的项目。不幸的是,它看起来已经死了,因为它已经没有进展了6年。 - Cerin

2
如果你想在桌面上测试MCU之外的代码,可以使用libcheck: https://libcheck.github.io/check/ 我曾多次使用它来测试我的嵌入式代码。这是一个相当健壮的框架。

唯一的缺点是它不支持g++,这使得它对于测试大多数使用C++特性的Arduino库毫无用处。 - Cerin

1
尝试使用Autodesk电路模拟器。它允许测试Arduino代码和电路,与许多其他硬件组件一起使用。

1
使用Proteus VSM与Arduino库来调试代码或测试代码。
在将代码上传到板子之前这是最佳实践,但要注意时间因为模拟运行不像在板子上那样实时运行。

1
您可以使用emulare — 在图表上拖放微控制器并在Eclipse中运行您的代码。网站上的文档会告诉您如何设置它。

0

基本上,Arduino是用C和C++编写的,甚至Arduino的库也是用C和C++编写的。因此,简单来说,只需将代码处理为C和C++并尝试进行单元测试。在这里,“处理”一词的意思是更改所有基本语法,例如将serial.println更改为sysout,pinmode更改为变量,void loop更改为while()循环,该循环在按键或经过某些迭代后中断。

我知道这是一个有点长的过程,不太直接。根据我的个人经验,一旦你开始使用它,它就会变得更加可靠。

-Nandha_Frost


0

如果您有兴趣运行一个INO草图并检查串行输出,我在我的Arduino NMEA checksum项目中有一个可用的实现。

以下脚本获取文件并使用Arduino CLI将其编译为HEX文件,然后加载到SimAVR中评估并打印串行输出。由于所有的Arduino程序都能够永久运行,而没有真正终止的选项(exit(0)无效), 我让草图运行几秒钟,然后将捕获的输出与预期的输出进行比较。

下载并提取Arduino CLI(在本例中为版本0.5.0 - 当写作时最新):

curl -L https://github.com/arduino/arduino-cli/releases/download/0.5.0/arduino-cli_0.5.0_Linux_64bit.tar.gz -o arduino-cli.tar.gz
tar -xvzf arduino-cli.tar.gz

现在你可以更新索引并安装适当的核心。
./arduino-cli core update-index
./arduino-cli core install arduino:avr

假设您的草稿命名为 nmea-checksum.ino,要获取 ELF 和 HEX,请运行:
./arduino-cli compile -b arduino:avr:uno nmea-checksum.ino

接下来,使用SimAVR运行HEX(或ELF)文件 - 我从源代码构建,因为最新版本对我来说无法工作:
sudo apt-get update
sudo apt-get install -y build-essential libelf-dev avr-libc gcc-avr freeglut3-dev libncurses5-dev pkg-config
git clone https://github.com/buserror/simavr.git
cd simavr
make

编译成功后,您将获得simavr/run_avr,您可以使用它来运行草图。像我说的那样,否则就超时,否则它将永远不会终止:

cd simavr
timeout 10 ./run_avr -m atmega168 -f 16000000 ../../nmea-checksum.ino.arduino.avr.uno.elf &> nmea-checksum.ino.clog || true

生成的文件将具有 ANSI 颜色代码控制字符包装串行输出,要消除这些字符:

cat nmea-checksum.ino.clog | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" > nmea-checksum.ino.log
cat nmea-checksum.ino.log

现在你需要做的就是将这个文件与一个已知的好文件进行比较:
diff nmea-checksum.ino.log ../../nmea-checksum.ino.test

如果没有差异,diff会以0代码退出,否则脚本将失败。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接