Is there a way to replace socket communication functions for unit testing?

asked 2017-03-27 15:42:53 -0500

cpagravel gravatar image

updated 2017-03-27 15:54:40 -0500

I have a large source base with multiple contributors that runs a lot of unit tests on the server every time a PR is issued. I want to have more code coverage without creating a special interface for my nodes and classes and I've run into two problems:

  1. Some of my classes have a very limited interface that depend a lot on subscriber callback methods.

  2. Some of my classes publish its output directly to a topic.

The obvious solution is to use publishers and subscribers in a unit test to check this functionality. However, this will really slow down the testing process by incorporating socket communication in our unit tests.

Therefore, I would really like to find a way to replace the ROS subscribe and publish functions with my own, only for the purpose of testing. Is there an implementation for this or an easy way to do this? Has anybody already thought about this and determined its usefulness?

edit retag flag offensive close merge delete

Comments

I don't think this is possible without some serious research into how those functions are used in the middleware layers.

I've seen some projects where "nodelet everything" was (ab)used for this: for testing, start everything as nodelets. Normal production system, load them as standalone nodes.

gvdhoorn gravatar image gvdhoorn  ( 2017-03-29 12:11:41 -0500 )edit

slow down the testing process by incorporating socket communication in our unit tests

(without trying to be pedantic here): wouldn't including socket comms immediately make these tests integration tests? Sockets are typically used to cross component barriers, implying multiple components are ..

gvdhoorn gravatar image gvdhoorn  ( 2017-03-29 12:13:12 -0500 )edit

.. involved in the test. To me that sounds like integration tests.

What I've seen done is to refactor things in such a way that either:

  • callbacks actually only dispatch to other (member) functions
  • callbacks are idempotent

in both cases that makes it easier to call those methods in proper ..

gvdhoorn gravatar image gvdhoorn  ( 2017-03-29 12:14:41 -0500 )edit

.. unit tests that don't depend on an entire ROS graph being present and functional.

gvdhoorn gravatar image gvdhoorn  ( 2017-03-29 12:15:32 -0500 )edit

Finally: you're probably aware of it, but rostest explicitly supports starting up (parts of a) ROS node graph to facilitate testing of components that 'need' it.

gvdhoorn gravatar image gvdhoorn  ( 2017-03-29 12:16:18 -0500 )edit

Thanks for the comments. I wasn't notified that someone had commented on this post. Can you define what an idempotent callback is? I'm only aware of the definition of idempotent as it relates to linear algebra :P. What I ended up doing was making the callbacks as protected functions and...

cpagravel gravatar image cpagravel  ( 2017-04-03 12:28:49 -0500 )edit

In my test case, I had a class that inherits the node class so I can call those callbacks directly (as if a message was passed to it). It is not ideal and it limited behaviour when spinOnce was called. For those cases I ended up using publishers as one would in the actual implementation.

cpagravel gravatar image cpagravel  ( 2017-04-03 12:31:30 -0500 )edit

I see that idempotence in computer science is very similar to the linear algebra definition. Anyway, my primary concern was about the speed of my unit tests, but it seems that, because this unit test was intended to recreate a race condition, I could not simplify it further.

cpagravel gravatar image cpagravel  ( 2017-04-03 12:38:13 -0500 )edit