Package: ros2-easy-test
ROS2 easy-testA Python test framework forROS2allowing for:simple and expressive assertions based on message and service interactions (black box testing)easy integration of existing nodes and launch filestesting of nodes implemented in any programming language (C++, Python, ...)works with and without tools likecolcon testandpytestis minimalistic and hasvery few dependenciesis typed anddocumentedis tested, used in practice, and maintainedInstallationJust run:pipinstallros2-easy-testExamplesThe following two examples show off the usage of the Python decorators@with_single_nodeand@with_launch_file, which provide the core functionality of this package.
To get a better grasp of their inner workings, have a look at their implementationhere.
Besides the simple examples here, you can embed everything inunittest.TestCaseas well.
To check out how, have a look at the providedtests/for some advanced examples.Testing a NodeSimple settings where a single node shall be tested can make use of the decorator@with_single_nodeas in the following example.fromros2_easy_testimportROS2TestEnvironment,with_launch_file,with_single_nodefrommy_nodesimportTalkerfromstd_msgs.msgimportString@with_single_node(Talker,watch_topics={"/chatter":String})deftest_simple_publisher(env:ROS2TestEnvironment)->None:response:String=env.assert_message_published("/chatter",timeout=5)assertresponse.data=="Hello World: 0"You can optionally provide more parameters to the test setting, i.e., additionally passparameters={"some.thing": 30.2}to the decorator.
The argument of the test function receiving theROS2TestEnvironmentmustbe namedenv.Testing a Launch FileFor more complex scenarios involving multiple nodes using a launch file (both nodes and launch file being implemented inany language supported by ROS2), the@with_launch_filedecorator can be used.@with_launch_file("example_launch_file.yaml",watch_topics={"/some/interesting/response":ColorRGBA},)deftest_simple_update_launch_file(env:ROS2TestEnvironment)->None:env.publish("/topic/for/node_input",ColorRGBA(r=0.5,g=0.2,b=0.9,a=1.0))response_color=env.assert_message_published("/some/interesting/response")assertresponse_color.r==0.5You can also pass the literal launch file contents as astrinstead of a path like"example_launch_file.yaml".
The argument of the test function receiving theROS2TestEnvironmentmustbe namedenv.Note that, however, this method is much slower than the one above.
One reason for this is the requirement of a fixed warm-up time for the nodes to be started.
This is because the test environment has to wait for the nodes to be ready before it can start listening for messages.UsageHow you can interact with the node(s)UsingROS2TestEnvironment, you can call:publish(topic: str, message: RosMessage) -> Nonelisten_for_messages(topic: str, time_span: float) -> List[RosMessage]clear_messages(topic: str) -> Noneto forget all messages that have been received so far.call_service(name: str, request: Request, timeout_availability: Optional[float], timeout_call: Optional[float]) -> ResponseNote thatROS2TestEnvironmentis arclpy.node.Nodeand thus has all the methods of a ROS2 node.
In addition, nothing stops you from using any other means of interacting with ROS2 that would work otherwise.What you can test (recommended way of obtaining messages)UsingROS2TestEnvironment, you can assert:assert_message_published(topic: str, timeout: Optional[float]) -> RosMessageassert_no_message_published(topic: str, timeout: Optional[float]) -> Noneassert_messages_published(topic: str, number: int, ...) -> List[RosMessage]Generally, you can always test that no exceptions are thrown, e.g., when nodes are initialized (see limitations below).Combining with other toolsSome hints:If you want to usepytest markerslike@pytest.mark.skipif(...), add that above (=before) the@with_single_node(...)/@with_launch_file(...)decorator and it will work just fine.Similarly, you can seamlessly use other tools which annotate test functions, likehypothesisorpytest fixtures.
Generally, you have to be mindful of the order of the decorators here.
TheROS2TestEnvironmentis always added as a keyword argument calledenvto the test function.
Seetests/demo/for a few examples.Limitations, Design, and Other ProjectsSeethe documentation on that.ContributingYou can install the development dependencies withpip install -e ".[dev]". After this, you will have access to the configured formattersblack .andruff check ..You can run the test with simplypytest. Coverage reports and timings will be printed on the command line, and a fresh line-by-line coverage report is inhtmlcov/index.html.Building the documentation is simple too:# Install the required dependenciespipinstall-e".[doc]"# Build the documentationcddoc
makehtml# open build/html/index.html in you browser# You can also run a small webserver to serve the static files withcdbuild/html
python-mhttp.serverChangelogSeeReleases.LicenseSeeLICENSE.Initially developed byFelix DivoatSailing Team Darmstadt e. V., a student group devoted to robotic sailing based in Darmstadt, Germany.
Thanks toSimon Kohautfor his kind and nuanced feedback.