ArduPilot 单元测试

ArduPilot 的单元测试套件允许创建可重复的测试,有助于防止 ArduPilot 内部功能出现倒退。它基于谷歌的 GTest 框架.

使用 ArduPilot 的单元测试可以

  • 通过减少重复运行相同测试以迫使函数重复输入相同内容所花费的时间,提高开发流程的效率

  • 允许您反复复制 ArduPilot 函数中的不良行为,并可能将该测试交付给能够解决问题的开发人员("测试驱动开发)

  • 通过锁定 ArduPilot 函数行为的测试,减少该函数行为发生回归的几率

概述

单元测试套件在 ArduPilot 的自动测试服务器上运行,大部分提交到主分支,但也可在本地运行,以审核软件更改。添加测试非常简单,并鼓励在更改后证明函数的正确性。

运行单元测试

单元测试需要一个可以编译 ArduPilot 可执行文件的环境。最简单的方法是创建 SITL 测试环境。使用 SITL 指令 (SITL)来获取有效环境。建议使用 ArduPilot Vagrant 虚拟机配置文件来获取工作环境。

致词

备注

这些测试在 Linux 下运行良好。在不同环境下的运行情况尚不清楚。

单元测试使用 waf 构建工具:

pbarker@bluebottle:~/rc/ardupilot(master)$ ./waf configure --board=linux --debug 设置顶部为 :/home/pbarker/rc/ardupilot 设置为 :/home/pbarker/rc/ardupilot/build Autoconfiguration : enabled .脚本运行时检查 : 已启用 检查程序 'rsync' : /usr/bin/rsync 'configure' 成功完成 (1.085s)
pbarker@bluebottle:~/rc/ardupilot(master)$ ./waf tests Waf:进入目录 `/home/pbarker/rc/ardupilot/build/linux' Waf:离开目录 `/home/pbarker/rc/ardupilot/build/linux' . . tests/test_polygon 204433 7056 1352 212841 tests/test_segment_intersection 193839 5832 1288 200959 tests/test_vector2 210539 6472 1320 218331 编译命令将保存在 build/linux/compile_commands.json 'tests' 成功完成 (2.249s)

然后,您只需从构建目录运行测试即可:

pbarker@bluebottle:~/rc/ardupilot(master)$ ./build/linux/tests/test_vector2 [==========] 正在运行 1 个测试套件中的 7 个测试。[----------] 设置全局测试环境。[----------] 来自 Vector2Test 的 7 个测试 [ 运行 ] Vector2Test.IsEqual [ 确定 ] Vector2Test.IsEqual (0 毫秒) [ 运行 ] Vector2Test.angle [ 确定 ] Vector2Test.angle (0 毫秒) [ 运行 ] Vector2Test.IsEqual [ 确定 ] Vector2Test.IsEqual (0 毫秒) [ 运行 ] Vector2Test.长度 [ 确定 ] Vector2Test.length (0 ms) [ 运行 ] Vector2Test.normalized [ 确定 ] Vector2Test.normalized (0 ms) [ 运行 ] Vector2Test.reflect [ 确定 ] Vector2Test.reflect (0 ms) [ 运行reflect (0 ms) [ RUN ] Vector2Test.closest_point [ OK ] Vector2Test.closest_point (0 ms) [ RUN ] Vector2Test.circle_segment_intersectionx [ OK ] Vector2Test.circle_segment_intersectionx (0 ms) [----------] 来自 Vector2Test 的 7 个测试 (总共 0 ms) [----------] 全局测试环境拆除 [==========] 来自 1 个测试套件的 7 个测试已运行。 (总共 0 ms) [ PASSED ] 7 个测试。

与 GDB 一起使用

测试可在 GDB 下运行,以跟踪问题:

pbarker@bluebottle:~/rc/ardupilot(master)$ gdb --quiet --args ./build/linux/tests/test_vector2 从 ./build/linux/tests/test_vector2 读取符号......完成。(gdb) break test_vector2.cpp:20 在 0x81b9 处断点 1:文件 .././libraries/AP_Math/tests/test_vector2.cpp,第 20 行。(gdb) r 启动程序:/home/pbarker/rc/ardupilot/build/linux/tests/test_vector2 [启用使用 libthread_db 的线程调试] 使用主机 libthread_db 库 "/lib/x86_64-linux-gnu/libthread_db.so.1"。[==========] 正在运行 1 个测试套件中的 7 个测试。[----------] 全局测试环境设置。[----------] 来自 Vector2Test 的 7 个测试 [ RUN ] Vector2Test.IsEqual [ OK ] Vector2Test.IsEqual (0 ms) [ RUN ] Vector2Test.IsEqual (0 ms) [ RUN ] Vector2Test.IsEqual (0 ms)angle 断点 1, Vector2Test_angle_Test::TestBody (this=0x5555557c2b90) at .../../libraries/AP_Math/tests/test_vector2.cpp:20 20 EXPECT_FLOAT_EQ(M_PI/2, Vector2f(0, 1).angle()); (gdb)
自我.发送调试陷阱()

与 Valgrind 一起使用

这些测试也可以在 Valgrind 的 memcheck 下运行,以追踪内存问题:

pbarker@bluebottle:~/rc/ardupilot(master)$ valgrind --soname-synonyms=somalloc=nouserintercepts ./build/linux/tests/test_vector2 ==7973== Memcheck,内存错误检测器 ==7973== 版权 (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==7973== 使用 Valgrind-3.13.0 和 LibVEX;使用 -h 重新运行以获取版权信息 ==7973== 命令:./build/linux/tests/test_vector2 ==7973==== [==========] 从 1 个测试套件中运行 7 个测试。[----------] 全局测试环境设置。[----------] 来自 Vector2Test 的 7 个测试 [ 运行 ] Vector2Test.IsEqual [ 确定 ] Vector2Test.IsEqual (18 ms) [ 运行 ] Vector2Test.angle [ 确定 ] Vector2Test.angle (11 ms) [ 运行 ] Vector2Test.length [ 确定 ] Vector2Test.length (2 ms) [ 运行 ] Vector2Test.Length [ 确定 ] Vector2Test.Length (2 ms) [ 运行 ] Vector2Test.Length [ 确定 ] Vector2Test.Length (2 ms)length (2 ms) [ RUN ] Vector2Test.normalized [ OK ] Vector2Test.normalized (8 ms) [ RUN ] Vector2Test.reflect [ OK ] Vector2Test.reflect (8 ms) [ RUN ] Vector2Test.closest_point [ OK ] Vector2Test.closest_point (13 ms)closest_point (13 ms) [ RUN ] Vector2Test.circle_segment_intersectionx [ OK ] Vector2Test.circle_segment_intersectionx (9 ms) [----------] 来自 Vector2Test 的 7 个测试(共 81 ms) [----------] 全局测试环境拆除 [==========] 来自 1 个测试套件的 7 个测试运行。(137 ms total) [ PASSED ] 7 tests. ==7973== ==7973== HEAP SUMMARY: ==7973== in use at exit: 0 bytes in 0 blocks ==7973== Total heap usage:234 allocs, 234 frees, 116,474 bytes allocated ==7973== ==7973== 所有堆块都被释放 -- 不可能有泄漏 ==7973== ==7973== 对于检测到的和被抑制的错误计数,请使用 -v 重新运行:-v ==7973== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) pbarker@bluebottle:~/rc/ardupilot(master)$

单元测试结构

ArduPilot 源代码树中的一个目录可以包含一个 wscript 文件,指定它包含单元测试。

然后,该目录中的每个 .cpp 文件都会被视为有效的测试,并会在编译 waf 调用 试验 目标:

在撰写本文时,测试存在于以下目录中:

图书馆/AP_Common/试验
图书馆/AP_Math/试验
图书馆/AP_ADSB/试验
图书馆/AP_GPS/试验
图书馆/AP_HAL/试验
图书馆/AP_HAL/实用/试验
图书馆/AP_HAL_Linux/试验

添加单元测试

一般来说,复制现有文件并将其作为新测试的基础是可行的方法。更多信息,请参阅 GTest 框架文档。