Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A Python test framework for ROS2 allowing simple and expressive assertions based on message interactions.

License

NotificationsYou must be signed in to change notification settings

felixdivo/ros2-easy-test

Repository files navigation

licenseros2 versionros2 versionPython versionROS Package Index

CI statusdocumentation statusRuffstatic type checker

A Python test framework forROS2 allowing for:

  • simple and expressive assertions based on message and service interactions (black box testing)
  • easy integration of existing nodes and launch files
  • testing of nodes implemented in any programming language (C++, Python, etc.)
  • works with and without tools likecolcon test andpytest
  • is minimalistic and hasvery few dependencies
  • is typed anddocumented
  • is tested, used in practice,indexed, and maintained

Installation

Note:The formerPyPI packageros2-easy-test is now deprecated and will not be updated anymore. Thus, only usepip install ros2-easy-test for ROS versions prior to Kilted.

Just run (ROS2Rolling andKilted+):

rosdep install ros2_easy_test

Or add it to yourpackage.xml (see theROS2 docs):

<test_depend>ros2_easy_test</test_depend>

Examples

The following two examples demonstrate the usage of the Python decorators@with_single_node and@with_launch_file, which provide this package's core functionality.To get a better understanding of their inner workings, please have a look at their implementationhere.Besides the simple examples here, you can embed everything inunittest.TestCase as well.To check out how, have a look at the provided test intests/demo/ for some advanced examples.

Testing a Node

In simple settings, where a single node is to be tested, the decorator@with_single_node can be used:

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"

It is also possible to specify custom QoSProfiles for theROS2TestEnvironment to use when subscribing or publishing on the specified topics. Seetests/demo/latching_topic_test.py for an example. If no profile is specified, the defaultQoSProfile(history=QoSHistoryPolicy.KEEP_ALL) is used.

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 theROS2TestEnvironmentmust be namedenv.

Testing a Launch File

For 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_file decorator 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.5

You can also pass the literal launch file contents as astr instead of a path like"example_launch_file.yaml".The argument of the test function receiving theROS2TestEnvironmentmust be 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.

Usage

How you can interact with the node(s)

UsingROS2TestEnvironment, you can call:

  • publish(topic: str, message: RosMessage) -> None
  • listen_for_messages(topic: str, time_span: float) -> List[RosMessage]
  • clear_messages(topic: str) -> None to forget all messages that have been received so far.
  • call_service(name: str, request: Request, ...) -> Response
  • send_action_goal(name: str, goal: Any, ...) -> Tuple[ClientGoalHandle, List[FeedbackMsg]]
  • send_action_goal_and_wait_for_result(name: str, goal: Any, ...) -> Tuple[List[FeedbackMsg], ResultMsg]

Note that aROS2TestEnvironment is a normalrclpy.node.Node and thus has all the methods of any other ROS2 node.So feel free to offer a service withenv.create_service() and cover more specific use cases.Extend as you please!

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]) -> RosMessage
  • assert_no_message_published(topic: str, timeout: Optional[float]) -> None
  • assert_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 tools

Some hints:

  • If you want to usepytest markers like@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, likehypothesis orpytest fixtures.Generally, you have to be mindful of the order of the decorators here.TheROS2TestEnvironment is always added as a keyword argument calledenv to the test function.Seetests/demo/ for a few examples.

Limitations, Design, and Other Projects

Seethe documentation on that.Please read it before suggesting major features or changes.

Contributing

Basic installation is easiest with the providedDockerfile.For the last piece of setup, either open it in the providedDevcontainer or maunally runrosdep install --from-paths ros2_easy_test && colcon build --symlink-install && pip install -e './ros2_easy_test[dev]' afterward.

After this, you will have access to the configured formatter (ruff format) and linter (ruff 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 dependenciespip install -e'ros2_easy_test[doc]'# Build the documentationcd docmake html# open build/html/index.html in your browser# You can also run a small webserver to serve the static files withcd build/htmlpython -m http.server

A new version can be released by pusing a new tag starting withv to the repository.This will trigger the CI to draft a release in GitHub that can then be filled with the changelog.Make sure to update the version number inpackage.xml andros2_easy_test/ros2_easy_test/__init__.py before tagging.Then, a release via rosdep can be made.

Changelog

SeeReleases.

License

SeeLICENSE.

Initially developed byFelix Divo atSailing Team Darmstadt e. V., a student group devoted to robotic sailing based in Darmstadt, Germany.Thanks toSimon Kohaut for his kind and nuanced feedback, and allthe other awesome contributors for their help and support!

About

A Python test framework for ROS2 allowing simple and expressive assertions based on message interactions.

Topics

Resources

License

Stars

Watchers

Forks


[8]ページ先頭

©2009-2025 Movatter.jp