How to verify publications using rostest?
I have several pieces of software in ROS, all of which are pretty thoroughly unit and integration tested. However, there's one aspect of testing within ROS that I have yet to accomplish with much success: Verifying publications.
Note that I'm still stuck in the dark ages of Fuerte, but I believe my question is relevant to more recent releases as well.
I currently have several tests within rostest, which looks like this in my CMakeLists.txt:
rosbuild_add_executable(my_tests EXCLUDE_FROM_ALL ${MY_TESTS})
rosbuild_add_gtest_build_flags(my_tests)
rosbuild_add_rostest(${PROJECT_SOURCE_DIR}/test/node/node.test)
Running this with make test
also runs a roscore (since node.test is a launch file), so these tests can make use of classes that require a connection to roscore. I'd like to use this to verify publications, but it's not working reliably, which makes me think I'm doing something wrong. As an example:
class TestSubscriber
{
public:
TestSubscriber() : receivedMessage(false) {}
void callback(const std_msgs::Int32ConstPtr &newMessage)
{
receivedMessage = true;
message = newMessage;
}
bool receivedMessage;
std_msgs::Int32ConstPtr message;
}
TEST(MyTest, TestPublication)
{
// This class will publish on the "output" topic. It will create a node handle
// and advertise in its constructor.
MyPublishingClass publishingClass;
ros::NodeHandle nodeHandle;
TestSubscriber subscriber;
ros::Subscriber rosSubscriber = nodeHandle.subscribe("output",
1,
&TestSubscriber::callback,
&subscriber);
ASSERT_EQ(1, rosSubscriber.getNumPublishers()); // This passes
publishingClass.publishMessage();
ros::spinOnce(); // Spin so that publication can get to subscription
EXPECT_TRUE(subscriber.receivedMessage); // This may or may not be true
}
Depending on how the MyPublishingClass is written, this test may pass or fail due to that last line. To give a specific example, I have a class that reads through a bagfile and publishes specific topics. If that class publishes topics with:
publisher.publish(rosBagViewIterator->instantiate<std_msgs::Int32>());
the test passes. If instead the class publishes with:
publisher.publish(*rosBagViewIterator);
the test fails (even though the node still runs normally outside of the test, so I know that publication is actually happening). I have more examples of similar weirdness, but I'm hoping this is enough to describe my problem.
So, down to my questions:
- Why is this so finicky? I realize that it's basically a node subscribing to its own publication, but that shouldn't be a problem. Should it?
- Am I doing this wrong? Is there a better way to test ROS publications? Note that the class in question is not a complete ROS node, and cannot be tested as such.
Thanks for the link Dirk! That is indeed exactly what I'm doing-- hopefully I'll be able to narrow it down a bit more.
Hi Kyle, did you manage to find out why the callback was inconsistent? I am having exactly the same problem. Let me know if you found something