Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Unit Test for Republisher Node on Noetic Branch #39

Open
wants to merge 20 commits into
base: noetic-devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9a2f422
added a .gitignore file
IrinaTerebiznik Dec 17, 2024
4941500
added a .gitignore file
IrinaTerebiznik Dec 17, 2024
ae89291
test files added to the package
IrinaTerebiznik Dec 20, 2024
1e91c64
Created a unit test to test the republisher's behavior when launching.
IrinaTerebiznik Dec 23, 2024
4adba3c
Added a README.md file to folder
IrinaTerebiznik Dec 23, 2024
973e75c
Rename UnitTests folder to adhere to PEP8 style guide
IrinaTerebiznik Dec 26, 2024
2059bc1
Updated .gitignore to deprecate unnecessary instructions
IrinaTerebiznik Dec 26, 2024
6b3988c
Updated example.yaml file
IrinaTerebiznik Dec 26, 2024
1293ddf
Added a new config file specific for the unit test and modified test_…
IrinaTerebiznik Dec 26, 2024
0a3bcaf
Updated the README file to correct a shell instruction.
IrinaTerebiznik Dec 26, 2024
a608a1a
Improved readme's readability
IrinaTerebiznik Dec 26, 2024
95c3ae1
Removed unnecessary test
IrinaTerebiznik Dec 26, 2024
8bf54d7
Updated READMEs, i added a first step to build a docker before runnin…
IrinaTerebiznik Dec 26, 2024
2b654e0
Changed rospy.sleep() to rospy.wait_for_message() on test_message_rep…
IrinaTerebiznik Dec 26, 2024
9ad039b
Changed timeout trigger to prevent slower connections to fail test
IrinaTerebiznik Dec 26, 2024
0149d29
Changed READMEs catkin_build command to catkin build
IrinaTerebiznik Dec 27, 2024
a24e6b8
Changed rospy.sleep() function for rospy.rostime.wallsleep() to preve…
IrinaTerebiznik Dec 27, 2024
1318e80
Changed rospy.rostime.wallsleep() for rate.sleep() to avoid using an …
IrinaTerebiznik Dec 27, 2024
7e349b5
Moved an import to the top for better organization
IrinaTerebiznik Dec 27, 2024
34a5566
Merge branch 'noetic-devel' into irina_noetic_unitest
IrinaTerebiznik Dec 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
__pycache__/

29 changes: 29 additions & 0 deletions inorbit_republisher/config/example_unit_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
republishers:
- topic: "/input_topic"
msg_type: "std_msgs/String"
mappings:
- field: "data"
mapping_type: "single_field"
out:
topic: "/output_topic"
key: "input_to_output"
static_publishers:
- value_from:
package_version: "rospy"
out:
topic: "/inorbit/custom_data/0"
key: "rospy_version"
- value_from:
package_version: "inorbit_republisher"
out:
topic: "/inorbit/custom_data/0"
key: "inorbit_republisher_version"
- value_from:
environment_variable: "PYTHONPATH"
out:
topic: "/inorbit/custom_data/0"
key: "python_path"
- value: "let's republish in orbit"
out:
topic: "/inorbit/custom_data/0"
key: "greeting"
32 changes: 24 additions & 8 deletions inorbit_republisher/test/sample_data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,30 @@ topics: /my_magnetic_field 10 msgs : sensor_msgs/MagneticField
```

To validate the node works launch the sample by using the ``sample_data.launch`` launch file and look at ``out`` topic: ``rostopic echo /inorbit/custom_data/0``.

```bash
. ~/catkin_ws/devel/setup.zsh
cd ~/catkin_ws/src/inorbit_republisher/test/sample_data
roslaunch sample_data.launch
1. **Start ROS2 docker container (optional)**:
You can run the commands below for building and running the republisher inside a docker container.
```bash
docker run -ti --rm \
--workdir /root/catkin_ws/ \
-v .:/root/catkin_ws/src/inorbit_republisher \
osrf/ros:noetic-desktop
# Install catkin
apt update && apt install python3-catkin-tools python3-osrf-pycommon -y
```
2. **Build the Workspace**:
Ensure the workspace is built and the environment is sourced:
```bash
cd ~/catkin_ws
rosdep install --from-paths ~/catkin_ws/src --ignore-src --rosdistro=noetic
catkin clean
catkin build inorbit_republisher --verbose
```
3. **Source and Run the Workspace**:
```bash
. ~/catkin_ws/install/setup.zsh
roslaunch sample_data.launch
# On a different terminal windows
source /opt/ros/noetic/setup.bash
$ rostopic echo my_temperature
$ rostopic echo /inorbit/custom_data/0
data: "my_temperature=41.0"
---
data: "my_magnetic_field_x=1.4"
Expand All @@ -37,4 +53,4 @@ data: "my_magnetic_field_z=0.6"
---
data: "my_temperature=41.0"
...
```
```
41 changes: 41 additions & 0 deletions inorbit_republisher/test/unit_test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Unit Test for ROS Republisher Node

This repository contains a unit test for a ROS node that republishes messages from `/input_topic` to `/output_topic`. The test ensures the republisher node processes and republishes messages correctly.

## Test Description

The unit test is implemented in `test_republisher.py` and uses the `unittest` framework along with `rostest`. It includes the following test cases:

- **`test_message_republishing`**:
- Publishes a test message (`key=value`) to `/input_topic`.
- Verifies that the republisher node republishes the message with the correct prefix (`input_to_output=`) to `/output_topic`.

- **`test_no_message`**:
- Ensures that no messages are received on `/output_topic` at the start of the test.

The test subscribes to `/output_topic` and collects received messages for validation.

## Running the Unit Test
1. **Start ROS2 docker container (optional)**:
You can run the commands below for building and running the republisher inside a docker container.
```bash
docker run -ti --rm \
--workdir /root/catkin_ws/ \
-v .:/root/catkin_ws/src/inorbit_republisher \
osrf/ros:noetic-desktop
# Install catkin
apt update && apt install python3-catkin-tools python3-osrf-pycommon -y
```
2. **Build the Workspace**:
Ensure the workspace is built and the environment is sourced:
```bash
cd ~/catkin_ws
rosdep install --from-paths ~/catkin_ws/src --ignore-src --rosdistro=noetic
catkin clean
catkin build inorbit_republisher --verbose
```
3. **Source and Run the Workspace**:
```bash
. ~/catkin_ws/devel/setup.bash
rostest inorbit_republisher test_republisher.test
```
46 changes: 46 additions & 0 deletions inorbit_republisher/test/unit_test/test_republisher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python
# Unit test for a ROS node that republishes messages from /input_topic to /output_topic.
# It uses the unittest framework and rostest for testing.

import unittest
import rospy
import rostest
from std_msgs.msg import String

class TestRepublisher(unittest.TestCase):
def setUp(self):
# Initialize the ROS node for testing
rospy.init_node('test_republisher', anonymous=True)
self.test_pub = rospy.Publisher('/input_topic', String, queue_size=10)
self.received_messages = []
rospy.Subscriber('/output_topic', String, self.callback)

# Safe way to Wait for publisher connections to be established
timeout = rospy.get_time() + 5.0 # Timeout limited to 5 seconds
rate = rospy.Rate(5) # ROS Rate at 5Hz
while self.test_pub.get_num_connections() == 0:
IrinaTerebiznik marked this conversation as resolved.
Show resolved Hide resolved
if rospy.get_time() > timeout:
self.fail("Test setup failed: Publisher connection timeout.")
rate.sleep()

def callback(self, msg):
# Method to save messages received on /output_topic.
self.received_messages.append(msg.data)

def test_message_republishing(self):
# Method to send a message (key=value) to /input_topic and
# check if the republisher correctly adds the prefix (input_to_output=) and sends it to /output_topic.
test_message = "key=value"
expected_message = f"input_to_output={test_message}"
rospy.loginfo(f"Publishing: {test_message} to /input_topic")
self.test_pub.publish(String(data=test_message))
try:
msg = rospy.wait_for_message('/output_topic', String, timeout=35)
print(f"Received message: {msg.data}")
except rospy.ROSException:
print("Timeout exceeded while waiting for a message.")
rospy.loginfo(f"Messages received: {self.received_messages}")
self.assertIn(expected_message, self.received_messages)

if __name__ == '__main__':
IrinaTerebiznik marked this conversation as resolved.
Show resolved Hide resolved
rostest.rosrun('my_ros_package', 'test_republisher', TestRepublisher)
9 changes: 9 additions & 0 deletions inorbit_republisher/test/unit_test/test_republisher.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<launch>
<!-- Launch republisher node -->
<node name="inorbit_republisher" pkg="inorbit_republisher" type="republisher.py">
<param name="config" textfile="$(find inorbit_republisher)/config/example_unit_test.yaml" />
</node>

<!-- Launch unit test -->
<test test-name="test_republisher" pkg="inorbit_republisher" type="test_republisher.py" />
</launch>