MEPP2 Project
|
A unit test is a program (contains the main function) which permits to detect code regressions and is a measure of code quality. Unit tests are used in MEPP2 to prevent either compilation or running time issues. A unit test must have a short execution time (generally less than 1 s), and it must validate only one thing (e.g. only one processing filter for a particular data structure). A failed test must return a value different from 0. It can also have an assertion check (assert call) which fails (but assertion failure is only detected in Debug mode). A successful test always returns 0 and has all its assertions (assert calls) which pass. A unit test generally produces an output file (e.g. a mesh or a point cloud file) and then compares this file with the expected result file (which is called reference file when the expected result is different from the input file).
For mesh and point cloud data structures (the most relevant use case), unit tests permit to ensure the proper functioning of some functionalities. For instance, you can ensure the proper file loading, the proper file writing, or the proper execution of a processing filter (processing onto a mesh or a point cloud is called a filter in MEPP2). You can also ensure that some concepts are implemented.
For external libraries, there might be a specific library usage test (it is always the case if the library was compiled by the MEPP team). It ensures that the library includes are found and that the library link edition operates normally under the 3 OS (Windows, Linux, and Mac OS X).
If MEPP2 is your local repository folder, then MEPP2/Testing
is the folder that contains the source code of the unit tests and their input and output reference files.
More specifically, the MEPP2/Testing hierarchy is the following:
AIF
, CGAL/LCC
, CGAL/Polyhedron
, CGAL/Surfae_mesh
, OpenMesh
;CGAL/Point_set
, PCL
;boost
, Cimg
, Draco
.Generic
. Note that generic filters for both meshes and point clouds are specified in this folder, while generic filters specific to 2-manifold meshes (resp. point clouds) are specified in the Manifold
(resp. PointCloud
) subfolder;Concepts
.Utils
.The Utils
folder contains functions to help for the elaboration of unit tests. It contains:
retrieve the vertex_descriptor
(resp. halfedge_descriptor
, edge_descriptor
, and face_descriptor
) from 1 index (resp. 2 indices, 2 indices, and 1 index).Functions to compare 2 files (duplicate vertices are not properly managed yet): bool identical_text_based_files(std::string filename_a, std::string filename_b, bool skip_mtllib = false)
and bool are_meshes_equal(std::string filename_a, std::string filename_b, bool verbose, FloatT threshold, bool relative_threshold)
. The first function searches for a line difference in the two input text files. The second function uses face descriptions based on vertex indices and searches for either a point coordinate difference or a face description difference. This function does not work with vertex duplicates and only supports OFF files.
There are 2 use cases:
RefOutput
folder (usual case), you can use it at the end of your applied processing to check if the result is stable (are_meshes_equal(result_mesh_file.off, ref_mesh_file.off, verbose, geom_threshold, attr_threshold, relative_thresholds));RefOutput
folder: you will apply filter1 and then filter2, you will thus use the input data file (e.g. from the Data folder) as a reference file. For instance, this kind of test is used to test a decompression filter once we have validated its associated compression filter.Testing a processing filter with a data structure (either a mesh or a point cloud data structure) consists in writing a program (containing the main function) inside a mesh/point cloud data structure folder (in the MEPP2/Testing
folder). As mentioned at the beginning of this page, it is important that the main function returns 0 when the test passes, while two approaches can be used to make the test fails: returning a value different from 0 (which works in Debug and Release) or asserting with an assert function that something is true of false in your code (which works in Debug).
A non-generic unit test permits to test both a data-structure-specific filter and a generic filter with a specific data structure (see next section for the generic case).
For instance, the CGAL specific filter boolean_operations.hpp
is tested for the Polyhedron data structure in the CGAL/Polyhedron
folder. See test_boolean_operations_polyhedron.cpp
.
The last step is to add your unit test to the MEPP2 project in the CMakeLists.txt file present in the data structure folder. For instance, to add a unit test associated with the test_boolean_operations_polyhedron.cpp in the CGAL/Polyhedron
you edit this CMakeLists.txt
file and add:
Note that ${TESTING_DATA_DIR} (resp. ${TESTING_REFOUTPUT_DIR}) refers to the Data
(resp. RefOutput
) folder.
Note that unit tests can be run in parallel and therefore it is highly recommended that each output file produced by a unit test in the temporary testing directory has a unique name. For instance, the first test (union case) will produce an output file that is named "test_boolean_operations_polyhedron_UNION.off". Some unit tests specify the output file name directly as an argument of the add_test cmake function.
A generic test is used to test a generic filter.
The example below is given for a 2-manifold generic test. A generic test for point cloud data structures can be implemented in the same way.
MEPP2/Testing/Generic/Manifold
folder: test_xxxx.inl (see for instance test_curvature_filter.inl
). It is important not to include data structure specific headers in this file.in the MEPP2/Testing/CGAL/Surface_mesh/test_curvature_filter_surfacemesh.cpp
file. Note that this file includes the data structure headers and then includes the generic test file.