[ROS2] Get rid of unnecessary info with launch_test
Hi, I am performing integration testing of a service. Below is the output of launch_test
command:
$ launch_test src/minimal_service/test/test_service_member_function.py
[INFO] [launch]: All log files can be found below /home/ravi/.ros/log/2022-07-27-18-02-53-325657-dell-60021
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [service_member_function-1]: process started with pid [60024]
test_add_two_ints (test_service_member_function.TestMinimalService) ... [service_member_function-1] [INFO] [1658912573.644021537] [minimal_service]: Incoming request
[service_member_function-1] a: 10 b: 20
ok
----------------------------------------------------------------------
Ran 1 test in 0.320s
OK
[INFO] [service_member_function-1]: sending signal 'SIGINT' to process[service_member_function-1]
[service_member_function-1] Traceback (most recent call last):
[service_member_function-1] File "/home/ravi/ros_ws/install/examples_rclpy_minimal_service/lib/examples_rclpy_minimal_service/service_member_function", line 33, in <module>
[service_member_function-1] sys.exit(load_entry_point('examples-rclpy-minimal-service==0.9.4', 'console_scripts', 'service_member_function')())
[service_member_function-1] File "/home/ravi/ros_ws/install/examples_rclpy_minimal_service/lib/python3.8/site-packages/examples_rclpy_minimal_service/service_member_function.py", line 39, in main
[service_member_function-1] rclpy.spin(minimal_service)
[service_member_function-1] File "/opt/ros/foxy/lib/python3.8/site-packages/rclpy/__init__.py", line 191, in spin
[service_member_function-1] executor.spin_once()
[service_member_function-1] File "/opt/ros/foxy/lib/python3.8/site-packages/rclpy/executors.py", line 706, in spin_once
[service_member_function-1] handler, entity, node = self.wait_for_ready_callbacks(timeout_sec=timeout_sec)
[service_member_function-1] File "/opt/ros/foxy/lib/python3.8/site-packages/rclpy/executors.py", line 692, in wait_for_ready_callbacks
[service_member_function-1] return next(self._cb_iter)
[service_member_function-1] File "/opt/ros/foxy/lib/python3.8/site-packages/rclpy/executors.py", line 589, in _wait_for_ready_callbacks
[service_member_function-1] _rclpy.rclpy_wait(wait_set, timeout_nsec)
[service_member_function-1] KeyboardInterrupt
[ERROR] [service_member_function-1]: process has died [pid 60024, exit code -2, cmd '/home/ravi/ros_ws/install/examples_rclpy_minimal_service/lib/examples_rclpy_minimal_service/service_member_function --ros-args -r __ns:=/'].
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Question
The unnecessary info from "sending signal 'SIGINT'" to "process has died" is confusing. It made me think that my service node died in between while testing. How to get rid of this information? Instead, I would like to have a summary report on test cases that passed/failed.
Additional Info
Below is the workspace structure:
.
├── build
├── install
├── log
└── src
└── minimal_service
├── CHANGELOG.rst
├── examples_rclpy_minimal_service
│ ├── __init__.py
│ └── service_member_function.py
├── package.xml
├── README.md
├── resource
│ └── examples_rclpy_minimal_service
├── setup.cfg
├── setup.py
└── test
├── test_copyright.py
├── test_flake8.py
├── test_pep257.py
└── test_service_member_function.py <- This is the newly added file
The package is taken from ros2/examples. Below is the content of test_service_member_function.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from threading import Thread
import unittest
from example_interfaces.srv import AddTwoInts
import launch
import launch_ros
import launch_ros.actions
import launch_testing.actions
import pytest
import rclpy
@pytest.mark.rostest
def generate_test_description():
node = launch_ros.actions.Node(
package='examples_rclpy_minimal_service',
namespace='',
executable='service_member_function',
)
return (
launch.LaunchDescription(
[
node,
launch_testing.actions.ReadyToTest(),
]
),
{
'minimal_service': node,
},
)
class TestMinimalService(unittest.TestCase):
@classmethod
def setUpClass(cls):
rclpy.init()
@classmethod
def tearDownClass(cls):
rclpy.shutdown()
def setUp(self):
self.node = rclpy.create_node('test_minimal_service')
self.client_add_two_ints = self.node.create_client(AddTwoInts, '/add_two_ints')
self.assertTrue(self.client_add_two_ints.wait_for_service(timeout_sec=10.0))
self.spin_thread = Thread(target=rclpy.spin, args=(self.node,))
self.spin_thread.start()
def tearDown(self):
self.node.destroy_node()
def test_add_two_ints(self):
req = AddTwoInts.Request(a=10, b=20)
res = self.client_add_two_ints.call(req)
self.assertEqual(res.sum, 30)