-
Create a new folder in the directory
/src/python/modules
with the name equals to adding module name (let's suppose it is<ModuleName>
). -
Create an empty
__init__.py
file in your folder. This has to be done because/src/python
folder 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
,GMM
etc.). The class file must have the same name as the class itself (i.e.<ModuleName><Objective>.py
). As far as the/src/python
designed as a package, imports in your class files must be relative tosrc/python
directory. E.g.from shared.ITest import ITest
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.
input
parameter is a variable of type<Objective>Input
. Such classes are defined in the files<Objective>Data.py
in 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>Output
contains 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.txt
with python requirements. E.g.scipy>=1.3.1 numpy>=1.11
CMakeLists.txt
with 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_params
variable 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
:
def testSomeFeature(self):
# method body
Note, 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:
def setUp(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.py
where<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
unittest
module andutils.py
file from the folder/test/python/modules/common
:import unittest import utils
-
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() for param_set in test_params: suite.addTest(utils.ParametrizedTestClass.parametrize( PythonModuleCommonGMMTests, params = param_set )) res = unittest.TextTestRunner(verbosity = 2).run(suite) if res.wasSuccessful(): sys.exit(0) else: sys.exit(1)
If such a code is added, then
self.params
variable of the test class object will store current test class parameters (respected element of yourtest_params
array). -
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.