From dd9575cf4ffda095c374b8f7cca79b923384a189 Mon Sep 17 00:00:00 2001 From: pawelirh Date: Fri, 6 Sep 2024 09:40:22 +0000 Subject: [PATCH 1/8] Change License in system monitor integration test --- .../test/integration/system_monitor_node.test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panther_diagnostics/test/integration/system_monitor_node.test.py b/panther_diagnostics/test/integration/system_monitor_node.test.py index 6307e972..dc895713 100644 --- a/panther_diagnostics/test/integration/system_monitor_node.test.py +++ b/panther_diagnostics/test/integration/system_monitor_node.test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2022 TIER IV, Inc. +# Copyright 2024 Husarion sp. z o.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From 728c1dda15da89f8d28ebf851ff0a56a3751ea24 Mon Sep 17 00:00:00 2001 From: pawelirh Date: Mon, 9 Sep 2024 13:34:19 +0000 Subject: [PATCH 2/8] Implement panther_lights integration tests --- panther_lights/CMakeLists.txt | 34 +++-- .../test/integration/panther_lights.test.py | 143 ++++++++++++++++++ .../{ => unit}/animation/test_animation.cpp | 0 .../animation/test_charging_animation.cpp | 0 .../animation/test_image_animation.cpp | 0 .../led_components/test_led_animation.cpp | 0 .../test_led_animations_queue.cpp | 0 .../led_components/test_led_panel.cpp | 0 .../led_components/test_led_segment.cpp | 0 .../led_components/test_segment_converter.cpp | 0 .../test/{ => unit}/test_apa102.cpp | 0 .../test_lights_controller_node.cpp | 0 .../{ => unit}/test_lights_driver_node.cpp | 0 13 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 panther_lights/test/integration/panther_lights.test.py rename panther_lights/test/{ => unit}/animation/test_animation.cpp (100%) rename panther_lights/test/{ => unit}/animation/test_charging_animation.cpp (100%) rename panther_lights/test/{ => unit}/animation/test_image_animation.cpp (100%) rename panther_lights/test/{ => unit}/led_components/test_led_animation.cpp (100%) rename panther_lights/test/{ => unit}/led_components/test_led_animations_queue.cpp (100%) rename panther_lights/test/{ => unit}/led_components/test_led_panel.cpp (100%) rename panther_lights/test/{ => unit}/led_components/test_led_segment.cpp (100%) rename panther_lights/test/{ => unit}/led_components/test_segment_converter.cpp (100%) rename panther_lights/test/{ => unit}/test_apa102.cpp (100%) rename panther_lights/test/{ => unit}/test_lights_controller_node.cpp (100%) rename panther_lights/test/{ => unit}/test_lights_driver_node.cpp (100%) diff --git a/panther_lights/CMakeLists.txt b/panther_lights/CMakeLists.txt index a86796f7..070bd8c1 100644 --- a/panther_lights/CMakeLists.txt +++ b/panther_lights/CMakeLists.txt @@ -92,8 +92,9 @@ if(BUILD_TESTING) find_package(ament_cmake_gmock REQUIRED) find_package(ros_testing REQUIRED) + # Unit tests ament_add_gtest(${PROJECT_NAME}_test_animation - test/animation/test_animation.cpp) + test/unit/animation/test_animation.cpp) target_include_directories( ${PROJECT_NAME}_test_animation PUBLIC $ @@ -103,7 +104,7 @@ if(BUILD_TESTING) ament_add_gtest( ${PROJECT_NAME}_test_charging_animation - test/animation/test_charging_animation.cpp + test/unit/animation/test_charging_animation.cpp src/animation/charging_animation.cpp) target_include_directories( ${PROJECT_NAME}_test_charging_animation @@ -115,7 +116,8 @@ if(BUILD_TESTING) ament_add_gtest( ${PROJECT_NAME}_test_image_animation - test/animation/test_image_animation.cpp src/animation/image_animation.cpp) + test/unit/animation/test_image_animation.cpp + src/animation/image_animation.cpp) target_include_directories( ${PROJECT_NAME}_test_image_animation PUBLIC $ @@ -125,7 +127,7 @@ if(BUILD_TESTING) target_link_libraries(${PROJECT_NAME}_test_image_animation png yaml-cpp) ament_add_gtest( - ${PROJECT_NAME}_test_led_panel test/led_components/test_led_panel.cpp + ${PROJECT_NAME}_test_led_panel test/unit/led_components/test_led_panel.cpp src/led_components/led_panel.cpp) target_include_directories( ${PROJECT_NAME}_test_led_panel @@ -133,7 +135,8 @@ if(BUILD_TESTING) $) ament_add_gtest( - ${PROJECT_NAME}_test_led_segment test/led_components/test_led_segment.cpp + ${PROJECT_NAME}_test_led_segment + test/unit/led_components/test_led_segment.cpp src/led_components/led_segment.cpp) target_include_directories( ${PROJECT_NAME}_test_led_segment @@ -145,7 +148,7 @@ if(BUILD_TESTING) ament_add_gtest( ${PROJECT_NAME}_test_segment_converter - test/led_components/test_segment_converter.cpp + test/unit/led_components/test_segment_converter.cpp src/led_components/segment_converter.cpp src/led_components/led_panel.cpp src/led_components/led_segment.cpp) @@ -159,7 +162,7 @@ if(BUILD_TESTING) ament_add_gtest( ${PROJECT_NAME}_test_led_animation - test/led_components/test_led_animation.cpp + test/unit/led_components/test_led_animation.cpp src/led_components/led_panel.cpp src/led_components/led_segment.cpp src/led_components/led_animations_queue.cpp) @@ -173,7 +176,7 @@ if(BUILD_TESTING) ament_add_gtest( ${PROJECT_NAME}_test_led_animations_queue - test/led_components/test_led_animations_queue.cpp + test/unit/led_components/test_led_animations_queue.cpp src/led_components/led_panel.cpp src/led_components/led_segment.cpp src/led_components/led_animations_queue.cpp) @@ -185,7 +188,7 @@ if(BUILD_TESTING) panther_utils rclcpp) target_link_libraries(${PROJECT_NAME}_test_led_animations_queue yaml-cpp) - ament_add_gmock(${PROJECT_NAME}_test_apa102 test/test_apa102.cpp + ament_add_gmock(${PROJECT_NAME}_test_apa102 test/unit/test_apa102.cpp src/apa102.cpp) target_include_directories( ${PROJECT_NAME}_test_apa102 @@ -193,8 +196,9 @@ if(BUILD_TESTING) $) ament_add_gmock( - ${PROJECT_NAME}_test_lights_driver_node test/test_lights_driver_node.cpp - src/apa102.cpp src/lights_driver_node.cpp) + ${PROJECT_NAME}_test_lights_driver_node + test/unit/test_lights_driver_node.cpp src/apa102.cpp + src/lights_driver_node.cpp) target_include_directories( ${PROJECT_NAME}_test_lights_driver_node PUBLIC $ @@ -206,7 +210,7 @@ if(BUILD_TESTING) ament_add_gtest( ${PROJECT_NAME}_test_lights_controller_node - test/test_lights_controller_node.cpp + test/unit/test_lights_controller_node.cpp src/lights_controller_node.cpp src/led_components/led_segment.cpp src/led_components/led_panel.cpp @@ -221,6 +225,12 @@ if(BUILD_TESTING) target_link_libraries(${PROJECT_NAME}_test_lights_controller_node lights_controller_node_component yaml-cpp) + # Integration tests + option(TEST_INTEGRATION "Run integration tests" OFF) + if(TEST_INTEGRATION) + add_ros_test(test/integration/panther_lights.test.py) + endif() + endif() ament_export_include_directories(include) diff --git a/panther_lights/test/integration/panther_lights.test.py b/panther_lights/test/integration/panther_lights.test.py new file mode 100644 index 00000000..89491041 --- /dev/null +++ b/panther_lights/test/integration/panther_lights.test.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +# Copyright 2024 Husarion sp. z o.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import unittest + +import launch +import launch_testing +import rclpy +import rclpy.qos +from diagnostic_msgs.msg import DiagnosticArray +from launch import LaunchDescription +from launch.substitutions import PathJoinSubstitution +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare +from launch_testing_ros import WaitForTopics +from panther_msgs.msg import LEDAnimation +from panther_msgs.srv import SetLEDAnimation +from sensor_msgs.msg import Image +from std_srvs.srv import SetBool + + +def generate_test_description(): + + led_config_file = ( + PathJoinSubstitution([FindPackageShare("panther_lights"), "config", "led_config.yaml"]), + ) + + lights_controller_node = Node( + package="panther_lights", + executable="lights_controller_node", + parameters=[{"led_config_file": led_config_file}], + ) + + lights_driver_node = Node( + package="panther_lights", + executable="lights_driver_node", + ) + + # Start test after 1s + delay_timer = launch.actions.TimerAction( + period=1.0, actions=[launch_testing.actions.ReadyToTest()] + ) + + actions = [lights_controller_node, lights_driver_node, delay_timer] + + context = {} + + return ( + LaunchDescription(actions), + context, + ) + + +class TestNode(unittest.TestCase): + + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() + + def setUp(self): + self.test_node = rclpy.create_node("test_node") + self.led_control_requested = None + + self.led_control_enable_srv = self.test_node.create_service( + srv_type=SetBool, + srv_name="hardware/led_control_enable", + callback=self.led_control_enable_cb, + qos_profile=rclpy.qos.qos_profile_services_default, + ) + + self.set_led_animation_client = self.test_node.create_client( + srv_type=SetLEDAnimation, + srv_name="lights/set_animation", + qos_profile=rclpy.qos.qos_profile_services_default, + ) + + def tearDown(self): + self.test_node.destroy_node() + + def led_control_enable_cb(self, request, response): + self.led_control_requested = request.data + response.success = True + response.message = "LED control enabled" + return response + + def test_initialization(self, proc_output): + rclpy.spin_until_future_complete(self.test_node, rclpy.task.Future(), timeout_sec=2.0) + + self.assertTrue(self.led_control_requested) + + ## Controller initialization + proc_output.assertWaitFor("[lights_controller]: Loaded default animations.") + proc_output.assertWaitFor("[lights_controller]: Initialized successfully.") + ## Driver initialization + proc_output.assertWaitFor("[lights_driver]: Node constructed successfully.") + proc_output.assertWaitFor("[lights_driver]: LED control granted.") + + def request_error_animation(self): + request = SetLEDAnimation.Request() + request.animation = LEDAnimation(id=LEDAnimation.ERROR) + request.repeating = False + + self.set_led_animation_client.wait_for_service(timeout_sec=1.0) + self.set_led_animation_client.call_async(request) + + def test_msg_publishers(self): + self.request_error_animation() + + topic_list = [ + ("lights/channel_1_frame", Image), + ("lights/channel_2_frame", Image), + ("diagnostics", DiagnosticArray), + ] + + with WaitForTopics(topic_list, timeout=5.0) as wait_for_topics: + received_topics_str = ", ".join(wait_for_topics.topics_received()) + print("Received messages from the following topics: [" + received_topics_str + "]") + + +@launch_testing.post_shutdown_test() +class TestProcessOutput(unittest.TestCase): + + def test_exit_code(self, proc_info): + # Check that process exits with code 0: no error + launch_testing.asserts.assertExitCodes(proc_info) diff --git a/panther_lights/test/animation/test_animation.cpp b/panther_lights/test/unit/animation/test_animation.cpp similarity index 100% rename from panther_lights/test/animation/test_animation.cpp rename to panther_lights/test/unit/animation/test_animation.cpp diff --git a/panther_lights/test/animation/test_charging_animation.cpp b/panther_lights/test/unit/animation/test_charging_animation.cpp similarity index 100% rename from panther_lights/test/animation/test_charging_animation.cpp rename to panther_lights/test/unit/animation/test_charging_animation.cpp diff --git a/panther_lights/test/animation/test_image_animation.cpp b/panther_lights/test/unit/animation/test_image_animation.cpp similarity index 100% rename from panther_lights/test/animation/test_image_animation.cpp rename to panther_lights/test/unit/animation/test_image_animation.cpp diff --git a/panther_lights/test/led_components/test_led_animation.cpp b/panther_lights/test/unit/led_components/test_led_animation.cpp similarity index 100% rename from panther_lights/test/led_components/test_led_animation.cpp rename to panther_lights/test/unit/led_components/test_led_animation.cpp diff --git a/panther_lights/test/led_components/test_led_animations_queue.cpp b/panther_lights/test/unit/led_components/test_led_animations_queue.cpp similarity index 100% rename from panther_lights/test/led_components/test_led_animations_queue.cpp rename to panther_lights/test/unit/led_components/test_led_animations_queue.cpp diff --git a/panther_lights/test/led_components/test_led_panel.cpp b/panther_lights/test/unit/led_components/test_led_panel.cpp similarity index 100% rename from panther_lights/test/led_components/test_led_panel.cpp rename to panther_lights/test/unit/led_components/test_led_panel.cpp diff --git a/panther_lights/test/led_components/test_led_segment.cpp b/panther_lights/test/unit/led_components/test_led_segment.cpp similarity index 100% rename from panther_lights/test/led_components/test_led_segment.cpp rename to panther_lights/test/unit/led_components/test_led_segment.cpp diff --git a/panther_lights/test/led_components/test_segment_converter.cpp b/panther_lights/test/unit/led_components/test_segment_converter.cpp similarity index 100% rename from panther_lights/test/led_components/test_segment_converter.cpp rename to panther_lights/test/unit/led_components/test_segment_converter.cpp diff --git a/panther_lights/test/test_apa102.cpp b/panther_lights/test/unit/test_apa102.cpp similarity index 100% rename from panther_lights/test/test_apa102.cpp rename to panther_lights/test/unit/test_apa102.cpp diff --git a/panther_lights/test/test_lights_controller_node.cpp b/panther_lights/test/unit/test_lights_controller_node.cpp similarity index 100% rename from panther_lights/test/test_lights_controller_node.cpp rename to panther_lights/test/unit/test_lights_controller_node.cpp diff --git a/panther_lights/test/test_lights_driver_node.cpp b/panther_lights/test/unit/test_lights_driver_node.cpp similarity index 100% rename from panther_lights/test/test_lights_driver_node.cpp rename to panther_lights/test/unit/test_lights_driver_node.cpp From 4d16480f22bc5a26b91fea3953f4582f5303b259 Mon Sep 17 00:00:00 2001 From: pawelirh Date: Mon, 9 Sep 2024 13:43:59 +0000 Subject: [PATCH 3/8] Fix comments --- panther_lights/test/integration/panther_lights.test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/panther_lights/test/integration/panther_lights.test.py b/panther_lights/test/integration/panther_lights.test.py index 89491041..5575e45f 100644 --- a/panther_lights/test/integration/panther_lights.test.py +++ b/panther_lights/test/integration/panther_lights.test.py @@ -106,10 +106,10 @@ def test_initialization(self, proc_output): self.assertTrue(self.led_control_requested) - ## Controller initialization + # Controller initialization proc_output.assertWaitFor("[lights_controller]: Loaded default animations.") proc_output.assertWaitFor("[lights_controller]: Initialized successfully.") - ## Driver initialization + # Driver initialization proc_output.assertWaitFor("[lights_driver]: Node constructed successfully.") proc_output.assertWaitFor("[lights_driver]: LED control granted.") From 6a9e94582bedae26790c110eb10c4262ed9ada59 Mon Sep 17 00:00:00 2001 From: pawelirh Date: Thu, 12 Sep 2024 06:36:33 +0000 Subject: [PATCH 4/8] Rename test fixture --- panther_lights/test/integration/panther_lights.test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panther_lights/test/integration/panther_lights.test.py b/panther_lights/test/integration/panther_lights.test.py index 5575e45f..98d8e2b7 100644 --- a/panther_lights/test/integration/panther_lights.test.py +++ b/panther_lights/test/integration/panther_lights.test.py @@ -65,7 +65,7 @@ def generate_test_description(): ) -class TestNode(unittest.TestCase): +class TestNodesIntegration(unittest.TestCase): @classmethod def setUpClass(cls): From 3f9d608291d16b6ff27a55b2355d687ef90a6e54 Mon Sep 17 00:00:00 2001 From: pawelirh Date: Fri, 13 Sep 2024 06:12:42 +0000 Subject: [PATCH 5/8] Add underscore prefix to private members --- .../test/integration/panther_lights.test.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/panther_lights/test/integration/panther_lights.test.py b/panther_lights/test/integration/panther_lights.test.py index 98d8e2b7..a9700abd 100644 --- a/panther_lights/test/integration/panther_lights.test.py +++ b/panther_lights/test/integration/panther_lights.test.py @@ -76,35 +76,35 @@ def tearDownClass(cls): rclpy.shutdown() def setUp(self): - self.test_node = rclpy.create_node("test_node") - self.led_control_requested = None + self._test_node = rclpy.create_node("test_node") + self._led_control_requested = None - self.led_control_enable_srv = self.test_node.create_service( + self._led_control_enable_srv = self._test_node.create_service( srv_type=SetBool, srv_name="hardware/led_control_enable", - callback=self.led_control_enable_cb, + callback=self._led_control_enable_cb, qos_profile=rclpy.qos.qos_profile_services_default, ) - self.set_led_animation_client = self.test_node.create_client( + self._set_led_animation_client = self._test_node.create_client( srv_type=SetLEDAnimation, srv_name="lights/set_animation", qos_profile=rclpy.qos.qos_profile_services_default, ) def tearDown(self): - self.test_node.destroy_node() + self._test_node.destroy_node() - def led_control_enable_cb(self, request, response): - self.led_control_requested = request.data + def _led_control_enable_cb(self, request, response): + self._led_control_requested = request.data response.success = True response.message = "LED control enabled" return response def test_initialization(self, proc_output): - rclpy.spin_until_future_complete(self.test_node, rclpy.task.Future(), timeout_sec=2.0) + rclpy.spin_until_future_complete(self._test_node, rclpy.task.Future(), timeout_sec=2.0) - self.assertTrue(self.led_control_requested) + self.assertTrue(self._led_control_requested) # Controller initialization proc_output.assertWaitFor("[lights_controller]: Loaded default animations.") @@ -113,16 +113,16 @@ def test_initialization(self, proc_output): proc_output.assertWaitFor("[lights_driver]: Node constructed successfully.") proc_output.assertWaitFor("[lights_driver]: LED control granted.") - def request_error_animation(self): + def _request_error_animation(self): request = SetLEDAnimation.Request() request.animation = LEDAnimation(id=LEDAnimation.ERROR) request.repeating = False - self.set_led_animation_client.wait_for_service(timeout_sec=1.0) - self.set_led_animation_client.call_async(request) + self._set_led_animation_client.wait_for_service(timeout_sec=1.0) + self._set_led_animation_client.call_async(request) def test_msg_publishers(self): - self.request_error_animation() + self._request_error_animation() topic_list = [ ("lights/channel_1_frame", Image), From 9eb271c8dbd6eacd1018fcd78df717aab25ec9cd Mon Sep 17 00:00:00 2001 From: pawelirh Date: Fri, 13 Sep 2024 07:29:31 +0000 Subject: [PATCH 6/8] Add subscription verification --- .../test/integration/panther_lights.test.py | 7 ++ .../panther_utils/integration_test_utils.py | 79 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 panther_utils/panther_utils/integration_test_utils.py diff --git a/panther_lights/test/integration/panther_lights.test.py b/panther_lights/test/integration/panther_lights.test.py index a9700abd..046bab91 100644 --- a/panther_lights/test/integration/panther_lights.test.py +++ b/panther_lights/test/integration/panther_lights.test.py @@ -19,6 +19,7 @@ import launch import launch_testing +import panther_utils.integration_test_utils as test_utils import rclpy import rclpy.qos from diagnostic_msgs.msg import DiagnosticArray @@ -134,6 +135,12 @@ def test_msg_publishers(self): received_topics_str = ", ".join(wait_for_topics.topics_received()) print("Received messages from the following topics: [" + received_topics_str + "]") + def test_msg_subscribers(self): + node_info = test_utils.get_node_info("/lights_driver") + + self.assertIn("/lights/channel_1_frame", node_info.subscribers) + self.assertIn("/lights/channel_2_frame", node_info.subscribers) + @launch_testing.post_shutdown_test() class TestProcessOutput(unittest.TestCase): diff --git a/panther_utils/panther_utils/integration_test_utils.py b/panther_utils/panther_utils/integration_test_utils.py new file mode 100644 index 00000000..47dd4739 --- /dev/null +++ b/panther_utils/panther_utils/integration_test_utils.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +# Copyright 2024 Husarion sp. z o.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +from typing import List + + +class ROSNodeInfo: + """ + Class representing the ROS node info. + """ + + def __init__(self): + self.subscribers: List[str] = [] + self.publishers: List[str] = [] + self.service_servers: List[str] = [] + self.service_clients: List[str] = [] + self.action_servers: List[str] = [] + self.action_clients: List[str] = [] + + +def get_node_info(node_name: str) -> ROSNodeInfo: + """ + Executes the command 'ros2 node info ' and returns the ROSNodeInfo object. + + Args: + node_name (str): The name of the ROS 2 node to get information about. + + Returns: + ROSNodeInfo: An object representing a complete node info. + """ + node_info = ROSNodeInfo() + + section_map = { + "Subscribers:": node_info.subscribers, + "Publishers:": node_info.publishers, + "Service Servers:": node_info.service_servers, + "Service Clients:": node_info.service_clients, + "Action Servers:": node_info.action_servers, + "Action Clients:": node_info.action_clients, + } + + try: + # Execute the `ros2 node info` command + result = subprocess.run( + ["ros2", "node", "info", node_name], capture_output=True, text=True, check=True + ) + + # Parse the output + lines = result.stdout.splitlines() + current_section = None + + for line in lines: + line = line.strip() + if line in section_map: + current_section = section_map[line] + elif line and current_section is not None: + current_section.append(line.split(":")[0].strip()) + else: + current_section = None + + except subprocess.CalledProcessError as e: + print(f"Error executing command: {e}") + print(f"stderr: {e.stderr}") + + return node_info From ffc4fe6ce423ecaee1ab557203b69dc506c808bc Mon Sep 17 00:00:00 2001 From: pawelirh Date: Fri, 13 Sep 2024 07:59:20 +0000 Subject: [PATCH 7/8] Avoid pre-commit complains --- panther_lights/test/integration/panther_lights.test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/panther_lights/test/integration/panther_lights.test.py b/panther_lights/test/integration/panther_lights.test.py index 046bab91..fafd6bf1 100644 --- a/panther_lights/test/integration/panther_lights.test.py +++ b/panther_lights/test/integration/panther_lights.test.py @@ -138,8 +138,8 @@ def test_msg_publishers(self): def test_msg_subscribers(self): node_info = test_utils.get_node_info("/lights_driver") - self.assertIn("/lights/channel_1_frame", node_info.subscribers) - self.assertIn("/lights/channel_2_frame", node_info.subscribers) + self.assertTrue("/lights/channel_1_frame" in node_info.subscribers) + self.assertTrue("/lights/channel_2_frame" in node_info.subscribers) @launch_testing.post_shutdown_test() From 962719bb6eb7c50de8978a3b3267cf7102164c37 Mon Sep 17 00:00:00 2001 From: pawelirh Date: Fri, 13 Sep 2024 08:12:15 +0000 Subject: [PATCH 8/8] Add error handling in get_node_info() method --- panther_utils/panther_utils/integration_test_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/panther_utils/panther_utils/integration_test_utils.py b/panther_utils/panther_utils/integration_test_utils.py index 47dd4739..621f906c 100644 --- a/panther_utils/panther_utils/integration_test_utils.py +++ b/panther_utils/panther_utils/integration_test_utils.py @@ -41,6 +41,9 @@ def get_node_info(node_name: str) -> ROSNodeInfo: Returns: ROSNodeInfo: An object representing a complete node info. + + Raises: + RuntimeError: If the command execution fails. """ node_info = ROSNodeInfo() @@ -73,7 +76,6 @@ def get_node_info(node_name: str) -> ROSNodeInfo: current_section = None except subprocess.CalledProcessError as e: - print(f"Error executing command: {e}") - print(f"stderr: {e.stderr}") + raise RuntimeError(f"Error executing command: {e}. stderr: {e.stderr}") from e return node_info