Create a new folder in the directory
/src/python/moduleswith the name equals to adding module name (let's suppose it is<ModuleName>).Create an empty
__init__.pyfile in your folder. This has to be done because/src/pythonfolder is designed as a package.For each objective create a class implementing abstract class
ITest(it is defined in the file/src/python/shared/ITest.py). Your class name must have the form<ModuleName><Objective>, where<Objective>is the type of objective this class is created for (BA,GMMetc.). The class file must have the same name as the class itself (i.e.<ModuleName><Objective>.py). As far as the/src/pythondesigned as a package, imports in your class files must be relative tosrc/pythondirectory. E.g.fromshared.ITestimportITest
You need to implement the following methods:
prepare(self, input)
Performs some preliminary work, e.g. converts input data into the format that tested AD framework needs.
inputparameter is a variable of type<Objective>Input. Such classes are defined in the files<Objective>Data.pyin the folder/src/python/shared.calculate_objective(self, times)
Repeatedly calculates objective function given number of times.
calculate_jacobian(self, times)
Repeatedly calculates objective function jacobian given number of times.
output(self)
Returns an object of the class
<Objective>Outputcontains calculated values. Such classes are defined in the files<Objective>Data.py.
Configure python requirements for a new module:
Add the following line to
/src/python/modules/CMakeLists.txt:add_subdirectory ("<ModuleName>")
In
/src/python/modules/<ModuleName>/create following files:requirements.txtwith python requirements. E.g.scipy>=1.3.1 numpy>=1.11CMakeLists.txtwith the following content:This command installs required pip packages on configure stage of CMake.project(<ModuleName>) execute_process( COMMAND${Python3_EXECUTABLE}"-m""pip""install""-r""${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt" )
Do not forget to add your module to the global runner script.
For module testing unittest framework is used.
All modules have common tests defined in the folder /test/python/modules/common. The file for the specified objective type has the name <objective>_tests.py, where <objective> is the objective type in the lowercase (e.g. ba). If you want to add your module to the module common test list then follow these steps:
- Open respected common test file.
- Find a
test_paramsvariable definition. It looks like this:# Parameters for different modules. They have the following form:# {# "path": <module path relative to src/python/modules directory>,# "tolerance": <tolerance for module output results># }test_params= [ { "path": os.path.join("PyTorch", "PyTorchHand.py"), "tolerance": 1e-8 }, # other class information ]
- Add information of your objective class to this definition.
If you want to add a new test to common tests, add a new test method to the respected common test class. Method name must start with the test prefix and it must not take any parameters except self:
deftestSomeFeature(self):
# method bodyNote, that before any test method running unittest framework calls setUp method of the test class. In the common test classes this method has the following form:
defsetUp(self):
module_path=os.path.join(MODULES_ROOT, self.params["path"])
self.test=module_load(module_path)
self.assertIsNotNone(self.test)So, self.test variable holds an instance of your objective benchmark class.
You can use standard unittest assertion methods or additional assertion methods from the class TestClassWithAdditionalAsserts, defined in the file /test/python/modules/common/utils.py. This class is extended by common test classes.
If you want to add common tests for a new type of objective follow these steps:
Add a new python file in the folder
/test/python/modules/common. It could have any name but suggesting name is<objective>_tests.pywhere<objective>is a name of a new objective type in the lower case.Do any import you need for a new file and also import
unittestmodule andutils.pyfile from the folder/test/python/modules/common:importunittestimportutils
Create a test class inherited form
utils.BaseTestClass. This base class has additional assertions and also provides parametrization, so you are able to create common tests for several modules using its.If you don't need parametrization, then just add the following code to the end of the file:
if__name__=="__main__": unittest.main()
If you need parametrization, then you should add something like this:
test_params= [ # array of test parameters ] if__name__=="__main__": suite=unittest.TestSuite() forparam_setintest_params: suite.addTest(utils.ParametrizedTestClass.parametrize( PythonModuleCommonGMMTests, params=param_set )) res=unittest.TextTestRunner(verbosity=2).run(suite) ifres.wasSuccessful(): sys.exit(0) else: sys.exit(1)
If such a code is added, then
self.paramsvariable of the test class object will store current test class parameters (respected element of yourtest_paramsarray).You can make a new test file visible for GTest runner. Add the following lines to the file
/test/python/modules/common/CMakeList.txt:add_test(NAME<TestsName>COMMAND${Python3_EXECUTABLE}"${CMAKE_SOURCE_DIR}/test/python/modules/common/<test_file_name>")
Here
<TestsName>is the displaying name of your tests for GTest,<test_file_name>is a name of the new common test file.
You can run test file by a Python3 interpreter installed on your machine, e.g.:
python3 ba_tests.py
All test files that are made visible for GTest can be run using any GTest runner.