Is there a way to replace socket communication functions for unit testing?
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:
Some of my classes have a very limited interface that depend a lot on subscriber callback methods.
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?
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.
(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 ..
.. 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:
in both cases that makes it easier to call those methods in proper ..
.. unit tests that don't depend on an entire ROS graph being present and functional.
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.
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...
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.
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.