[ROS in 5 mins] 054 – How to Unit Test loading a ROS Param

[ROS in 5 mins] 054 - How to Unit Test loading a ROS Param

Written by Ruben Alves

26/11/2018

Hello ROS Developers!

Welcome again to this “ROS In 5 Minutes” series.

It goes without saying that when we are developing, despite everything be seemingly working as expected, sometimes as soon as we put on production we see that the code doesn’t really work as expected.

One of the best ways to avoid problems like the aforementioned one is by having Unit Tests, therefore, in today’s videos we are going to learn how to run a Unit Test that ensures a parameter has been successfully loaded on the ROS Parameter Server. For that we are going to use Robot Ignite Academy, which is the best platform for those who want to Learn ROS Fast.

But before we start, if you are new to ROS, keep in mind that we offer the following ROS Basics courses:

Ok, let’s get started.

Let’s suppose in our scenario we load ROS Parameter files from different ROS Packages we want to make sure they load as expected. For that, we first need to create a package called tutorial on our ~/catkin_ws/src  folder, which can be accomplished with the following commands:

mkdir ~/catkin_ws/src/ -p
cd ~/catkin_ws/src/
catkin_create_pkg tutorial rospy

Now that our package was successfully created, let’s create a launch file called load_params.launch  inside the launch  folder by using the commands below:

cd ~/catkin_ws/src/tutorial/
mkdir launch
touch launch/load_params.launch

The file we just created will be used to load the ROS parameters. Since we don’t have parameter file, let’s try to find one on the ROS folders. For that let’s type:

find /opt/ros/kinetic/ -name *.yaml | head

After running the command above we may have ~10 lines in the output. We are only interested in a single file, so, let’s take the first line, which in my system was:

/opt/ros/kinetic/share/nodelet_tutorial_math/plus_default.yaml

By looking at that file we see that we have a parameter called value with the value 10:

value: 10

If we just try to get a variable called value from the ROS Parameter server we can see that the variable doesn’t exist, since we didn’t load that file yet. Let’s confirm with the command below:

rosparam get /value

we should have the following output:

ERROR: Parameter [/value] is not set

Ok, so far so good. Let’s now modify our load_params.launch  file in order to load that nodelet_tutorial_math/plus_default.yaml file. For that, let’s paste the following content on our launch file:

<launch>
    <rosparam command="load"file="$(find nodelet_tutorial_math)/plus_default.yaml"/>
</launch>

Now that our launch file is set, let’s launch it with the command below:

roslaunch tutorial load_params.launch

On the console, among other log messages we should have a message showing our ROS Parameter called value , something like the message below:

PARAMETERS
  * /rosdistro: kinetic
  * /rosversion: 1.12.14
  * /value: 10

If we now try to get that parameter from the ROS Parameter Server we should see the value 10. Let’s do it with the next command:

rosparam get /value

Ok, since we know everything is working when we manually run the commands, let’s now remove that parameter again from the server to test in an automated way. To remove it, use the following command:

rosparam delete /value

The reason why we might need a test is because our project starts increasing, we start loading parameters from different packages, loading different launch files, so on and so forth.

In order to create a our test, let’s create a test  folder inside our package with a file named test_params.py   inside. Let’s use the following commands for that:

cd ~/catkin_ws/src/tutorial/
mkdir test 
cd test
touch test_params.py
chmod +x test_params.py

Ok, now let’s create our Unit Test. For that, let’s paste the following content on the test_params.py  file:

#! /usr/bin/env python

import unittest
import rospy
import rostest


class MyTestCase(unittest.TestCase):
    def test_param_loaded(self):
        value = rospy.get_param('/value', None)
        self.assertIsNotNone(value)


if __name__ == '__main__':
    rostest.rosrun('tutorial', 'test_params', MyTestCase)

If we just run this test now we will see that it will fail because we don’t have the parameter loaded. Let’s run it to confirm that:

rosrun tutorial test_params.py

The test output should show a failure, something like the message below:

[ROSUNIT] Outputting test results to /home/user/.ros/test_results/tutorial/rosunit-test_params.xml
[Testcase: test_param_loaded] ... FAILURE!
FAILURE: unexpectedly None
  File "/usr/lib/python2.7/unittest/case.py", line 329, in run
    testMethod()
  File "/home/user/catkin_ws/src/tutorial/test/test_params.py", line 11, in test_param_loaded
    self.assertIsNotNone(value)
  File "/usr/lib/python2.7/unittest/case.py", line 960, in assertIsNotNone
    self.fail(self._formatMessage(msg, standardMsg))
  File "/usr/lib/python2.7/unittest/case.py", line 410, in fail
    raise self.failureException(msg)
--------------------------------------------------------------------------------
-------------------------------------------------------------
SUMMARY:
 * RESULT: FAIL
 * TESTS: 1
 * ERRORS: 0 []
 * FAILURES: 1 [test_param_loaded]

In order to load the parameters automatically during test, we need a launch file that launches both our test_params.py  and the load_params.launch  we created earlier. The launch file we will create will have the .test  extension but it is going to be a normal XML file, just as our .launch  files.

To create it, just use these commands:

cd ~/catkin_ws/src/tutorial/launch/
touch load_params.test

Let’s put the following content on the file we just created in order be able to launch our test properly:

<launch>
    <include file="$(find tutorial)/launch/load_params.launch" />
    <test test-name="test_params" pkg="tutorial" type="test_params.py" />
</launch>

If we run that file now, our test should pass because the load_params.launch  file will be included before running the test. Let’s test it:

rostest tutorial load_params.test

The log messages should show that the test has succeeded, something like:

[ROSUNIT] Outputting test results to /home/user/.ros/test_results/tutorial/rostest-launch_load_params.xml
[Testcase: testtest_params] ... ok

[ROSTEST]-----------------------------------------------------------------------

[tutorial.rosunit-test_params/test_param_loaded][passed]

SUMMARY
 * RESULT: SUCCESS
 * TESTS: 1
 * ERRORS: 0
 * FAILURES: 0

So, that is it for today, guys. I hope you liked the post.

Remember that below we also have the video that shows everything detailed in this post.

Also, feel free to post questions or suggestions on the comments section of the video on YouTube (https://www.youtube.com/watch?v=M_Vr0zJbih4) as well as share this content with your friends.

Keep pushing your ROS Learning.

 

Masterclass 2023 batch2 blog banner

Check Out These Related Posts

129. ros2ai

129. ros2ai

I would like to dedicate this episode to all the ROS Developers who believe that ChatGPT or...

read more

0 Comments

Submit a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Pin It on Pinterest

Share This