Unit-testing in MORSE¶
Introduction¶
Unit-tests (using the standard Python unit-testing framework) can be added
to MORSE by creating a test class inheriting from
morse.testing.testing.MorseTestCase
.
When contributing code to MORSE, we recommend you create unit-tests for the new features in subdirectories of $MORSE_ROOT/testing.
Writing tests¶
The MorseTestCase¶
Compared to the standard TestCase
class, the morse.testing.testing.MorseTestCase
takes care of starting/closing
MORSE and initializing it with a specified environment.
This environment is defined by overridding the morse.testing.testing.MorseTestCase.setUpEnv()
with a description of the environment using the Builder API.
Moreover, you can override the
morse.testing.testing.MorseTestCase.setUpMw()
and
morse.testing.testing.MorseTestCase.tearDownMw()
methods if you want to
create some specific environment before launching the Morse simulator, and to
clean up afterwards.
Complete example¶
This example creates a new scenario with two robots in an indoor environment, and then checks that the MORSE list_robots control service actually returns both robots.
from morse.testing.testing import MorseTestCase
class BaseTest(MorseTestCase):
def setUpEnv(self):
""" Defines the test scenario, using the Builder API.
"""
# Adding 4 robots
# no name provided, use the name of the associated variable
jido = Jido()
# use explicitly name provided
robot2 = ATRV('mana')
# setup the name using explicitly robot3.name
robot3 = ATRV()
robot3.name = 'dala'
# no name provided, use variable name
atrv = ATRV()
env = Environment('empty', fastmode = True)
def test_list_robots(self):
""" Tests the simulator can return the list of robots
This test is guaranteed to be started only when the simulator
is ready.
"""
# Initialize a socket connection to the simulator
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 4000))
sockf = s.makefile()
# Queries for the list of robots
s.send(b"id1 simulation list_robots\n")
result = sockf.readline()
id, success, robots = result.strip().split(' ', 2)
self.assertEquals(success, "SUCCESS")
import ast
robotsset = set(ast.literal_eval(robots))
self.assertEquals(robotsset, {'jido', 'mana', 'dala', 'atrv'})
sockf.close()
s.close()
Compiling MORSE to allow testing¶
To be able to run the test suite, you must have compiled MORSE with the option
PYMORSE_SUPPORT
enabled. For example:
$ cmake -DPYMORSE_SUPPORT=ON [other options] ..
After doing the initial install, you’ll need to recompile. For example:
$ make install
$ make rebuild_cache
After the installation is complete, you will now be able to run:
$ make test
This will start launching MORSE with a series of unit tests, to check that the creation of scenes and some of the components is running properly on your system.
Windows users can run the winbuild.bat
file to build and run the tests
automatically.
Running tests¶
Running MORSE tests¶
The MORSE tests infrastructure is integrated with cmake, so you can run make test to check that all currently defined unit-tests for MORSE pass. Alternatively, you can use ctest –verbose to have a more verbose output.
If you want to run one specific test, you can do so directly using a Python 3
interpreter. For example, to run base_testing.py
, you can call:
$ python3 ${MORSE_SRC_ROOT}/testing/base/base_testing.py
Tests log¶
The complete log of a test is available in the ${TestName}.log file, created in the current directory, where TestName is the name of your class test (in the previous example, it will create the BaseTest.log file.
Running a test as a standalone application¶
We can run tests case by invoking:
MorseTestRunner().run(tests)
It is convenient to add the following lines at the end of a test-case:
if __name__ == "__main__":
import unittest
from morse.testing.testing import MorseTestRunner
suite = unittest.TestLoader().loadTestsFromTestCase(<Your test class>)
sys.exit(not MorseTestRunner().run(suite).wasSuccessful())
Thus, you can run your test by simply calling it with the Python VM.