单元测试
我们鼓励开发人员在开发的每个模块时编写单元测试,包括添加新功能,修复错误和重构。
或者,也可以直接从 bash 运行完整的单元测试:
- Unit tests with Google Test ("GTest") - tests that have minimal, internal-only dependencies
- 在 test_[description].cpp 中包括基本 unittest-class
<unit_test.h>
以及为新功能编写测试所需的所有文件。 - 软件在环(SITL)单元测试。 这些测试需要运行在完整的SITL环境中, 运行起来更慢,更难调试,所以建议尽可能使用GTest代替。
编写测试
Tip: In general, if you need access to advanced GTest utilities, data structures from the STL or need to link to parameters
or uorb
libraries you should use the functional tests instead.
创建新的单元测试步骤如下:
- 单元测试分成三个部分:设置、运行、检查结果。 每个单元测试都应该测试一个特定行为或设置案例,如果测试失败,则很明显你的测试代码有错误。 请尽可能遵循这些标准。
- Copy and rename the example unit test AttitudeControlTest to the directory the code to be tested is in.
- Add the new file to the directory's
CMakeLists.txt
. It should look something likepx4_add_unit_gtest(SRC MyNewUnitTest.cpp LINKLIBS <library_to_be_tested>)
- 添加你想要的测试功能。 这包括了添加所需的头文件、新测试(每个测试都应该有单独的名称),并加入相关逻辑,运行测试代码并验证其行为是否符合预期。
- If additional library dependencies are required, they should also be added to the CMakeLists after the
LINKLIBS
as shown above.
Tests can be run via make tests
, after which you will find the binary in build/px4_sitl_test/unit-MyNewUnit
. 也可以直接通过调试器中运行。
写一个GTest功能测试
当测试或测试的组件依赖参数、uORB 消息、或更高级的GTest功能的时候,应当使用GTest功能测试。 Additionally, functional tests can contain local usage of STL data structures (although be careful of platform differences between e.g. macOS and Linux).
创建一个新的功能测试步骤如下:
- 一般来说(与单元测试类似)功能测试应分为三个部分:设置,运行,检查结果。 每个单元测试都应该测试一个特定行为或设置案例,如果测试失败,则很明显你的测试代码有错误。 请尽可能遵循这些标准。
- Copy and rename the example functional test ParameterTest to the directory the code to be tested is in.
- 将ParameterTest 重命名为更符合你正在测试的代码功能。
- Add the new file to the directory's
CMakeLists.txt
. It should look something likepx4_add_functional_gtest(SRC MyNewFunctionalTest.cpp LINKLIBS <library_to_be_tested>)
- 添加你想要的测试功能。 这包括了,添加特定的头文件、新测试(每个测试都应该使用不同的命名),并设置相关逻辑,运行测试代码并验证是否符合预期。
- If additional library dependencies are required, they should also be added to the CMakeLists after the
LINKLIBS
as shown above.
Tests can be run via make tests
, after which you will find the binary in build/px4_sitl_test/functional-MyNewFunctional
. It can be run directly in a debugger, however be careful to only run one test per executable invocation using the --gtest_filter=<regex> arguments, as some parts of the uORB and parameter libraries don't clean themselves up perfectly and may result in undefined behavior if set up multiple times.
写一个软件在环(SITL)单元测试
当需要所有的飞行控制组件:驱动、时间或者更多时,应该SITL单元测试。 这些测试运行较慢(每个模块至少1秒+),同时难以测试,所以仅在必要时使用它们。
创建一个新的SITL单元测试步骤如下:
Examine the sample Unittest-class.
Create a new .cpp file within tests with name test_[description].cpp.
Within test_[description].cpp include the base unittest-class
<unit_test.h>
and all files required to write a test for the new feature.Within test_[description].cpp create a class
[Description]Test
that inherits fromUnitTest
.Within
[Description]Test
class declare the public methodvirtual bool run_tests()
.Within
[Description]Test
class declare all private methods required to test the feature in question (test1()
,test2()
,...).Within test_[description].cpp implement the
run_tests()
method where each test[1,2,...] will be run.Within test_[description].cpp, implement the various tests.
At the bottom within test_[description].cpp declare the test.
cpput_declare_test_c(test_[description], [Description]Test)
下面是一个模板:
cpp#include <unit_test.h> #include "[new feature].h" ... class [Description]Test : public UnitTest { public: virtual bool run_tests(); private: bool test1(); bool test2(); ... }; bool [Description]Test::run_tests() { ut_run_test(test1) ut_run_test(test2) ... return (_tests_failed == 0); } bool [Description]Test::test1() { ut_[name of one of the unit test functions](... ut_[name of one of the unit test functions](... ... return true; } bool [Description]Test::test2() { ut_[name of one of the unit test functions](... ut_[name of one of the unit test functions](... ... return true; } ... ut_declare_test_c(test_[description], [Description]Test)
Note that
ut_[name of one of the unit test functions]
corresponds to one of the unittest functions defined within unit_test.h.Within tests_main.h define the new test:
cppextern int test_[description](int argc, char *argv[]);
Within tests_main.c add description name, test function and option:
cpp... } tests[] = { {... {"[description]", test_[description], OPTION}, ... }
OPTION
can beOPT_NOALLTEST
,OPT_NOJIGTEST
or0
and is considered if within px4 shell one of the two commands are called:shpxh> tests all
或
shpxh> tests jig
If a test has option
OPT_NOALLTEST
, then that test will be excluded when callingtests all
. The same is true forOPT_NOJITEST
when commandtest jig
is called. Option0
means that the test is never excluded, which is what most developer want to use.Add the test
test_[description].cpp
to the CMakeLists.txt.
在本地计算机上进行测试
Run the complete list of GTest Unit Tests, GTest Functional Tests and SITL Unit Tests right from bash:
sh
make tests
The individual GTest test binaries are in the build/px4_sitl_test/
directory, and can be run directly in most IDEs' debugger.
使用以下命令对ctest名称使用正则表达式对要运行的测试子集进行筛选:
sh
make tests TESTFILTER=<regex filter expression>
例如:
make tests TESTFILTER=unit
only run GTest unit testsmake tests TESTFILTER=sitl
only run simulation testsmake tests TESTFILTER=Attitude
only run theAttitudeControl
test