Lancer les tests de ROS2 et les analyser
Avec les commandes bash enregistrées dans :votre fichier .bashrc , vous pouvez lancer les tests de ROS2 avec les commandes décrites ci-dessous. N’oubliez pas que pour que cela fonctionne, il faut avoir initialisé l’environnement ros2 et que toutes les paquets aient été compilés avec succès.
ros2_humble
ros2_build
Lancer les tests sur tous les paquets du répertoire de travail
ros2_test
Exemple d’exécution sans erreur
[1] 140979
Starting >>> scara_description
Starting >>> scara_bringup
Starting >>> scara_joint_velocity_controller
Starting >>> scara_nodes
Finished <<< scara_joint_velocity_controller [0.03s]
Finished <<< scara_description [0.60s]
Starting >>> scara_hardware
Finished <<< scara_hardware [0.01s]
Finished <<< scara_nodes [0.96s]
Finished <<< scara_bringup [1.17s]
Summary: 5 packages finished [1.38s]
[1]+ Done source install/setup.bash
Exemple d’exécution avec erreurs
1[1] 129806
2Starting >>> scara_description
3Starting >>> scara_bringup
4Starting >>> scara_joint_velocity_controller
5Starting >>> scara_nodes
6Finished <<< scara_joint_velocity_controller [0.09s]
7Finished <<< scara_description [0.66s]
8Starting >>> scara_hardware
9Finished <<< scara_hardware [0.08s]
10--- stderr: scara_bringup
11Errors while running CTest
12Output from these tests are in: /home/pi/info_indus/ros2_ws/build/scara_bringup/Testing/Temporary/LastTest.log
13Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
14---
15Finished <<< scara_bringup [1.04s] [ with test failures ]
16--- stderr: scara_nodes
17Errors while running CTest
18Output from these tests are in: /home/pi/info_indus/ros2_ws/build/scara_nodes/Testing/Temporary/LastTest.log
19Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
20---
21Finished <<< scara_nodes [1.06s] [ with test failures ]
22
23Summary: 5 packages finished [1.46s]
24 2 packages had stderr output: scara_bringup scara_nodes
25 2 packages had test failures: scara_bringup scara_nodes
26[1]+ Done source install/setup.bash
Lancer les tests pour un paquet spécifique
La commande est:
ros2_test_only <nom_du_paquet>
Par exemple:
ros2_test_only scara_velocity_supervision
Analyser les résultats des tests
S’il y a une erreur, la sortie des tests telle qu’indiquée dans la sortie de la commande ros2_test ou ros2_test_only est bien souvent vide et donc inutile pour comprendre l’erreur.
Pour faire une analyse des tests, il faut utiliser la commande:
ros2_view_tests
Celle-ci donne des informations uniquement pour les tests qui contiennent des erreurs. Par exemple:
build/scara_bringup/Testing/20241121-1426/Test.xml: 5 tests, 0 errors, 1 failure, 0 skipped
build/scara_bringup/test_results/scara_bringup/flake8.xunit.xml: 21 tests, 0 errors, 21 failures, 0 skipped
build/scara_nodes/Testing/20241121-1426/Test.xml: 4 tests, 0 errors, 1 failure, 0 skipped
build/scara_nodes/test_results/scara_nodes/flake8.xunit.xml: 5 tests, 0 errors, 5 failures, 0 skipped
Summary: 50 tests, 0 errors, 28 failures, 0 skipped
En exécutant ces commandes dans un terminal de vscode,
Il suffit de faire un click gauche avec la souris sur le lien en maintenant appuyée la touche Ctrl du clavier pour ouvrir le fichier de log des tests et voir les erreurs.
Note
Nous avons défini une fonction ros2_view_tests_all qui permet de voir tous les tests, même ceux qui n’ont pas d’erreur.
Les cas d’usage sont très rares: principalement pour débuguer les CMakeLists.txt impliquant des tests et vérifier quels tests sont executés.
En ajoutant les lignes suivantes dans le fichier de configuration de vscode, vous pouvez ouvrir les fichiers de log des tests avec la coloration syntaxique adaptée:
"files.associations": {
"Test.xml": "log",
"*.xunit.xml": "log",
"*.gtest.xml": "log"
},
Note
Si vous avez déjà une variable files.associations définie dans votre fichier de configuration, il suffit d’ajouter les lignes ci-dessus dans la définition de cette variable.
D’autres options de configuration de vscode sont disponibles dans le fichier de configuration de vscode de ce cours, qui est très inspiré du projet git: vscode_ros2_workspace d’athackst (Allison Thackston)
Votre fichier de configuration de vscode peut ressembler à ceci:
settings.json
{
"editor.formatOnSave": true,
"editor.detectIndentation": true,
"editor.formatOnPaste": true,
"editor.wordWrap": "on",
"C_Cpp.clang_format_sortIncludes": false,
"terminal.integrated.scrollback": 100000,
"workbench.editor.enablePreview": false,
"[restructuredtext]": {
"editor.tabSize": 3
},
"files.associations": {
"Test.xml": "log",
"*.xunit.xml": "log",
"*.gtest.xml": "log",
"*.repos": "yaml",
"*.world": "xml",
"*.xacro": "xml"
},
"editor.tabSize": 8,
"editor.rulers": [
100
],
"python.analysis.extraPaths": [
"/opt/ros/humble/lib/python3.10/site-packages/"
],
// Autocomplete from ros python packages
"python.autoComplete.extraPaths": [
"/opt/ros/humble/lib/python3.10/site-packages/"
],
// Environment file lets vscode find python files within workspace
"python.envFile": "${workspaceFolder}/.env",
// Use the system installed version of autopep8
"python.formatting.autopep8Path": "/usr/bin/autopep8",
"python.formatting.autopep8Args": [
"--max-line-length=100"
],
"C_Cpp.default.intelliSenseMode": "linux-gcc-x86",
"C_Cpp.formatting": "disabled",
"uncrustify.configPath.linux": "/opt/ros/humble/lib/python3.10/site-packages/ament_uncrustify/configuration/ament_code_style.cfg",
"[cpp]": {
"editor.defaultFormatter": "zachflower.uncrustify"
},
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true,
"**/build": true,
"**/install": true,
"**/log": true
},
"cSpell.words": [
"RTPS",
"athackst",
"autopep",
"cmake",
"cppcheck",
"cpplint",
"DCMAKE",
"deque",
"devcontainer",
"ints",
"noqa",
"pytest",
"rclcpp",
"rclpy",
"repos",
"rosdep",
"rosdistro",
"rosidl",
"RTPS",
"uncrustify",
"Wextra",
"Wpedantic",
"xmllint"
],
"cSpell.allowCompoundWords": true,
"cSpell.ignorePaths": [
"**/package-lock.json",
"**/node_modules/**",
"**/vscode-extension/**",
"**/.git/objects/**",
".vscode",
".vscode-insiders",
".devcontainer/devcontainer.json"
]
}
{
"editor.formatOnSave": true,
"editor.detectIndentation": true,
"editor.formatOnPaste": true,
"editor.wordWrap": "on",
"C_Cpp.clang_format_sortIncludes": false,
"terminal.integrated.scrollback": 100000,
"workbench.editor.enablePreview": false,
"[restructuredtext]": {
"editor.tabSize": 3
},
"files.associations": {
"Test.xml": "log",
"*.xunit.xml": "log",
"*.gtest.xml": "log",
"*.repos": "yaml",
"*.world": "xml",
"*.xacro": "xml"
},
"editor.tabSize": 8,
"editor.rulers": [
100
],
"python.analysis.extraPaths": [
"/opt/ros/jazzy/lib/python3.10/site-packages/"
],
// Autocomplete from ros python packages
"python.autoComplete.extraPaths": [
"/opt/ros/jazzy/lib/python3.10/site-packages/"
],
// Environment file lets vscode find python files within workspace
"python.envFile": "${workspaceFolder}/.env",
// Use the system installed version of autopep8
"python.formatting.autopep8Path": "/usr/bin/autopep8",
"python.formatting.autopep8Args": [
"--max-line-length=100"
],
"C_Cpp.default.intelliSenseMode": "linux-gcc-x86",
"C_Cpp.formatting": "disabled",
"uncrustify.configPath.linux": "/opt/ros/jazzy/lib/python3.10/site-packages/ament_uncrustify/configuration/ament_code_style.cfg",
"[cpp]": {
"editor.defaultFormatter": "zachflower.uncrustify"
},
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true,
"**/build": true,
"**/install": true,
"**/log": true
},
"cSpell.words": [
"RTPS",
"athackst",
"autopep",
"cmake",
"cppcheck",
"cpplint",
"DCMAKE",
"deque",
"devcontainer",
"ints",
"noqa",
"pytest",
"rclcpp",
"rclpy",
"repos",
"rosdep",
"rosdistro",
"rosidl",
"RTPS",
"uncrustify",
"Wextra",
"Wpedantic",
"xmllint"
],
"cSpell.allowCompoundWords": true,
"cSpell.ignorePaths": [
"**/package-lock.json",
"**/node_modules/**",
"**/vscode-extension/**",
"**/.git/objects/**",
".vscode",
".vscode-insiders",
".devcontainer/devcontainer.json"
]
}
Dans le rapport de tests ci-dessous:
1build/scara_bringup/Testing/20241121-1426/Test.xml: 5 tests, 0 errors, 1 failure, 0 skipped
2build/scara_bringup/test_results/scara_bringup/flake8.xunit.xml: 21 tests, 0 errors, 21 failures, 0 skipped
3build/scara_nodes/Testing/20241121-1426/Test.xml: 4 tests, 0 errors, 1 failure, 0 skipped
4build/scara_nodes/test_results/scara_nodes/flake8.xunit.xml: 5 tests, 0 errors, 5 failures, 0 skipped
5
6Summary: 50 tests, 0 errors, 28 failures, 0 skipped
Les lignes surlignées en jaune sont des fichiers qui rassemblent les erreurs pour chaque package.
Les lignes 2 et 4 explicitent les tests qui ont échoués, dans ce cas, les tests sont des tests flake8 de type formatage de code python.
Ces tests sont les moins critiques car ce ne sont pas des erreurs de tests unitaires.
Ils devront néanmoins être corrigés pour que le code soit conforme aux standards de qualité et puisse être intégré dans une branche officielle du projet.
Afin de corriger ces tests rapidement, il est possible d’utiliser une fonctionnalité de vscode qui permet d’exécuter les tests directement dans l’éditeur.
Il faut configurer des tâches dans le fichier .vscode/tasks.json du répertoire du package pour exécuter les tests.
tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
// Build tasks
{
"label": "build",
"detail": "Build workspace (default)",
"type": "shell",
"command": "./build.sh",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": "$gcc"
},
{
"label": "debug",
"detail": "Build workspace (debug)",
"type": "shell",
"command": "./build.sh",
"options": {
"env": {
"BUILD_TYPE": "Debug"
}
},
"group": "build",
"problemMatcher": "$gcc"
},
// Test tasks
{
"label": "test",
"detail": "Run all unit tests and show results.",
"type": "shell",
"command": "./test.sh",
"group": {
"kind": "test",
"isDefault": true
}
},
// Clean
{
"label": "clean",
"detail": "Run the clean target",
"type": "shell",
"command": "colcon build --cmake-target clean",
"problemMatcher": "$gcc"
},
{
"label": "purge",
"detail": "Purge workspace by deleting all generated files.",
"type": "shell",
"command": "sudo rm -fr build install log; sudo py3clean .",
"problemMatcher": []
},
// Linting and static code analysis tasks
{
"label": "fix",
"detail": "Reformat files with uncrustify.",
"type": "shell",
"command": "ament_uncrustify --reformat src/",
"problemMatcher": []
},
{
"label": "uncrustify",
"detail": "Lint files with uncrustify.",
"type": "shell",
"command": "ament_uncrustify src/",
"presentation": {
"panel": "dedicated",
"reveal": "silent",
"clear": true
},
"problemMatcher": [
{
"owner": "uncrustify",
"source": "uncrustify",
"fileLocation": "relative",
"pattern": [
// just the file name message
{
"regexp": "^(.*)'(.*)':",
"kind": "file",
"file": 2,
"message": 1
}
]
}
]
},
{
"label": "cpplint",
"detail": "Lint files with cpplint.",
"type": "ament",
"task": "cpplint",
"path": "src/",
"problemMatcher": "$ament_cpplint",
"presentation": {
"panel": "dedicated",
"reveal": "silent",
"clear": true
},
},
{
"label": "cppcheck",
"detail": "Run static code checker cppcheck.",
"type": "ament",
"task": "cppcheck",
"path": "src/",
"problemMatcher": "$ament_cppcheck",
"presentation": {
"panel": "dedicated",
"reveal": "silent",
"clear": true
},
"options": {
"env": {
"AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS": "1"
}
}
},
{
"label": "lint_cmake",
"detail": "Run lint on cmake files.",
"type": "ament",
"task": "lint_cmake",
"path": "src/",
"problemMatcher": "$ament_lint_cmake",
"presentation": {
"panel": "dedicated",
"reveal": "silent",
"clear": true
}
},
{
"label": "flake8",
"detail": "Run flake8 on python files.",
"type": "ament",
"task": "flake8",
"path": "src/",
"problemMatcher": "$ament_flake8",
"presentation": {
"panel": "dedicated",
"reveal": "silent",
"clear": true
}
},
{
"label": "pep257",
"detail": "Run pep257 on python files.",
"type": "ament",
"task": "pep257",
"path": "src/",
"problemMatcher": "$ament_pep257",
"presentation": {
"panel": "dedicated",
"reveal": "silent",
"clear": true
}
},
{
"label": "xmllint",
"detail": "Run xmllint on xml files.",
"type": "ament",
"task": "xmllint",
"path": "src/",
"problemMatcher": "$ament_xmllint",
"presentation": {
"panel": "dedicated",
"reveal": "silent",
"clear": true
}
},
{
"label": "lint all",
"detail": "Run all linters.",
"dependsOn": [
"cppcheck",
"cpplint",
"flake8",
"lint_cmake",
"pep257",
"xmllint",
"uncrustify"
],
"problemMatcher": []
},
// Workspace editing tasks
{
"label": "new ament_cmake package",
"detail": "Create a new ROS cpp package from a template.",
"type": "shell",
"command": "ros2 pkg create --destination-directory src --build-type ament_cmake ${input:package}",
"problemMatcher": []
},
{
"label": "new ament_python package",
"detail": "Create a new ROS python package from a template.",
"type": "shell",
"command": "ros2 pkg create --destination-directory src --build-type ament_python ${input:package}",
"problemMatcher": []
},
{
"label": "import from workspace file",
"detail": "Use vcs to import modules specified by a workspace/rosinstall file.",
"type": "shell",
"command": "vcs import < src/ros2.repos src",
"problemMatcher": []
},
{
"label": "update workspace file",
"detail": "Use vcs to update repositories in src to workspace file.",
"type": "shell",
"command": "vcs export src > src/ros2.repos",
"problemMatcher": []
},
{
"label": "install dependencies",
"detail": "Install all dependencies specified in the workspaces package.xml files.",
"type": "shell",
"command": "sudo apt-get update && rosdep update && rosdep install --from-paths src --ignore-src -y",
"problemMatcher": []
},
{
"label": "setup",
"detail": "Set up the workspace",
"type": "shell",
"command": "./setup.sh",
"problemMatcher": []
},
{
"label": "add submodules from .repos",
"detail": "Create a git submodule for all repositories in your .repos file",
"type": "shell",
"command": "python3 .devcontainer/repos_to_submodules.py",
"problemMatcher": []
}
],
"inputs": [
{
"id": "package",
"type": "promptString",
"description": "Package name"
}
]
}
Ce fichier est intégralement repris du projet git: vscode_ros2_workspace d’athackst (Allison Thackston)
Pour exécuter une tache de linter, il suffit de taper Ctrl+Shift+P puis de taper Run Task et de sélectionner la tâche voulue.
Dans notre cas, il faut sélectionner la tâche flake8 pour exécuter les tests de formatage de code python.
De manière plus générale, pour les problèmes de linter, il est possible d’exécuter la tâche lint all qui exécute tous les tests de linter.