How do I test a service caller in python?
I have a python class that has a method that calls a ROS service. I'd like to test that class's method. My going in approach is to create a mock service, call it, and validate the calls are working.
# my_package/src/my_package/foo.py
class Foo(object):
def bar(self, req):
rospy.wait_for_service('service_name')
try:
send_request = rospy.ServiceProxy('service_name', MyService)
resp = send_request(req)
return resp
except rospy.ServiceException, e:
logging.error('[service_name] service call failed: %s' % e)
I've set up a test file that creates a Foo object in a unittest fixture, starts creates a node and service in the main and calls the unit testing framework.
# my_package/test/my_test.py
class FooTest(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_bar(self):
f = Foo()
req = MyServiceRequest()
self.assertTrue(f.bar(req))
def mock_baz_callback(req):
res = MyServiceResponse()
res.ok = True
return res
if __name__ == "__main__":
rospy.init_node('my_service')
s = rospy.Service('my_service', MyService, mock_baz_callback)
# unittest.main() doesn't start roscore
import rostest
rostest.rosrun('my_package', 'my_test', FooTest)
Using unittest.main() doesn't work, because roscore isn't started automatically. I assumed rostest would work better, but I'm unable to get it working. It appears to hang waiting for wait_for_service() to complete, which tells me either the Service in the main isn't starting or the test roscore isn't starting.
<launch>
<test test-name="my_test" pkg="my_package" type="my_test.py" />
</launch>
Do I need to make the mock service a stand-alone node that the launch file starts? I'd rather not have to...
Edit: If I manually start roscore and rosrun the test file directly, the test passes.