Generalize constraints on MPI rank counts for tests
[alexxy/gromacs.git] / docs / dev-manual / testutils.rst
1 Unit testing
2 ============
3
4 The main goal of unit tests in |Gromacs| is to help developers while developing
5 the code.  They focus on testing functionality of a certain module or a group
6 of closely related modules.  They are designed for quick execution, such that
7 they are easy to run after every change to check that nothing has been broken.
8
9 Finding, building and running
10 -----------------------------
11
12 As described in :ref:`dev-source-layout`, ``src/gromacs/`` is divided into modules,
13 each corresponding to a subdirectory.  If available, unit tests for that module
14 can be found in a ``tests/`` subdirectory under the top-level module directory.
15 Typically, tests for code in :file:`{file}.h` in the module is in a corresponding
16 :file:`tests/{file}.cpp`.  Not all files have corresponding tests, as it may not
17 make sense to test that individual file in isolation.  Focus of the tests is on
18 functionality exposed outside the module.  Some of the tests, in particular for
19 higher-level modules, are more like integration tests, and test the
20 functionality of multiple modules.
21 Shared code used to implement the tests is in ``src/external/googletest/`` and
22 ``src/testutils/`` (see below).
23
24 The tests are built if ``BUILD_TESTING=ON`` (the default) and
25 ``GMX_BUILD_UNITTESTS=ON`` (the default) in CMake. Each module
26 produces at least one separate unit test binary
27 (:file:`{module}-test`) under ``bin/``, which can execute tests for
28 that module.
29
30 The tests can be executed in a few different ways:
31
32 - Build the ``test`` target (e.g., ``make test``):
33   This runs all the tests using CTest.  This includes also the regression
34   tests if CMake has been told where to find them (regression tests are not
35   discussed further on this page).
36   If some of the tests fail, this only prints basic summary information (only
37   a pass/fail status for each test binary or regression test class).
38   You can execute the failing test binaries individually to get more
39   information on the failure.
40   Note that ``make test`` does not rebuild the test binaries if you have changed
41   the source code, so you need to separately run ``make`` or ``make tests``.
42   The latter only builds the test binaries and their dependencies.
43 - Build the ``check`` target (e.g., ``make check``):
44   This behaves the same as the ``test`` target, with a few extensions:
45
46   1. Test binaries are rebuilt if they are outdated before the tests are run.
47   2. If a test fails, the output of the test binary is shown.
48   3. If unit tests and/or regression tests are not available, a message is
49      printed.
50
51 - The implementation of ``make check`` calls CTest via the ``ctest`` binary
52   to run all the individual test binaries. More fine-grained control is available
53   there, e.g. filtering by test name or label, or increasing verbosity.
54 - Directly executing a test binary.  This provides the most useful
55   output for diagnosing failures, and allows debugging test failures.
56   The output identifies the individual test(s) that fail, and shows
57   the results of all failing assertions.  Some tests also add extra
58   information to failing assertions to make it easier to identify the
59   reason. Some tests are skipped because they cannot run with the
60   number of MPI ranks or GPU devices detected.  Explicit information
61   about such cases can be obtained by using the ``-echo-reasons`` flag
62   to the test binary.  It is possible to control which tests are run
63   using command line options.  Execute the binary with ``--help`` to
64   get additional information.
65
66 When executed using CTest, the tests produce XML output in
67 ``Testing/Temporary/``, containing the result of each test as well as failure
68 messages.  This XML is used by GitLab CI for reporting the test status for
69 individual tests.  Note that if a test crashes or fails because of an assert or
70 a gmx_fatal() call, no XML is produced for the binary, and CI does not
71 report anything for the test binary.  The actual error is only visible in the
72 console output.
73
74 Unit testing framework
75 ----------------------
76
77 The tests are written using `Google Test`_, which provides a framework for
78 writing unit tests and compiling them into a test binary.  Most of the command
79 line options provided by the test binaries are implemented by Google Test.  See
80 the `Google Test Primer`_ for an introduction.
81 Some tests also use `Google Mock`_, which provides a framework for creating
82 mock implementations of C++ classes.  Both components are included in the
83 source tree under ``src/external/googletest/``, and are compiled as part of the
84 unit test build.
85
86 ``src/testutils/`` contains |Gromacs|-specific shared test code.  This includes
87 a few parts:
88
89 - CMake macros for declaring test binaries.  These take care of providing the
90   ``main()`` method for the test executables and initializing the other parts of
91   the framework, so that the test code in modules can focus on the actual
92   tests.  This is the only part of the framework that you need to know to be
93   able to write simple tests: you can use ``gmx_add_unit_test()`` in CMake to
94   create your test binary and start writing the actual tests right away.
95   See ``src/testutils/TestMacros.cmake`` and existing CMake code for examples
96   how to use them.
97
98 - Generic test fixtures and helper classes.  The C++ API is documented on
99   `Doxygen page for testutils`__.  Functionality here includes
100   locating test input files from the source directory and constructing
101   temporary files, adding custom command line
102   options to the test binary, some custom test assertions
103   for better exception and floating-point handling, utilities
104   for constructing command line argument arrays, and
105   test fixtures for tests that need to test long strings for correctness
106   and for tests that execute legacy code where
107   ``stdin`` reading etc. cannot be easily mocked.
108
109   __ doxygen-module-testutils_
110
111 - Some classes and functions to support the above.  This code is for internal
112   use of the CMake machinery to build and set up the test binaries, and to
113   customize Google Test to suit our environment.
114
115 - Simple framework for building tests that check the results against reference
116   data that is generated by the same test code.  This can be used if it is not
117   easy to verify the results of the code with C/C++ code alone, but manual
118   inspection of the results is manageable.  The general approach is
119   documented on the `Doxygen page on using the reference data`__.
120
121   __ doxygen-page-refdata_
122
123 In addition to ``src/testutils/``, some of the module test directories may
124 provide reusable test code that is used in higher-level tests.  For example,
125 the ``src/gromacs/analysisdata/tests/`` provides test fixtures, a mock
126 implementation for gmx::IAnalysisDataModule, and some helper classes
127 that are also used in ``src/gromacs/trajectoryanalysis/tests/``.
128 These cases are handled using CMake object libraries that are linked to all the
129 test binaries that need them.
130
131 .. _gmx-make-new-tests:
132
133 Getting started with new tests
134 ------------------------------
135
136 To start working with new tests, you should first read the `Google Test`_
137 documentation to get a basic understanding of the testing framework, and read
138 the above description to understand how the tests are organized in |Gromacs|.
139 It is not necessary to understand all the details, but an overall understanding
140 helps to get started.
141
142 Writing a basic test is straightforward, and you can look at existing tests for
143 examples.  The existing tests have a varying level of complexity, so here are
144 some pointers to find tests that use certain functionality:
145
146 - ``src/gromacs/utility/tests/stringutil.cpp`` contains very simple tests for
147   functions.  These do
148   not use any fancy functionality, only plain Google Test assertions.
149   The only thing required for these tests is the ``TEST()`` macro and the block
150   following it, plus headers required to make them compile.
151 - The same file contains also simple tests using the reference framework to
152   check line wrapping (the tests for ``gmx::TextLineWrapper``).  The test fixture
153   for these tests is in ``src/testutils/include/testutils/stringtest.h``/``.cpp``.  The string test
154   fixture also demonstrates how to add a custom command line option to the
155   test binary to influence the test execution.
156 - ``src/gromacs/selection/tests/`` contains more complex use of the
157   reference framework.  This is the code the reference framework was
158   originally written for.
159   ``src/gromacs/selection/tests/selectioncollection.cpp`` is the main file to
160   look at.
161 - For more complex tests that do not use the reference framework, but instead
162   do more complex verification in code, you can look at
163   ``src/gromacs/selection/tests/nbsearch.cpp``.
164 - For complex tests with mock-up classes and the reference framework, you can
165   look at ``src/gromacs/analysisdata/tests/``.
166
167 Here are some things to keep in mind when working with the unit tests:
168
169 - Try to keep the execution time for the tests as short as possible, while
170   covering the most important paths in the code under test.  Generally, tests
171   should take seconds instead of minutes to run, so that no one needs to
172   hesitate before running the tests after they have done some changes.
173   Long-running tests should go somewhere else than in the unit test set.
174   Note that CI will run the tests in several build configuration and
175   slow tests will significantly slow down the pipelines and can even cause
176   them to timeout.
177 - Try to produce useful messages when a test assertion fails.  The assertion
178   message should tell what went wrong, with no need to run the *test itself*
179   under a debugger (e.g., if the assertion is within a loop, and the loop
180   index is relevant for understanding why the assertion fails, it should be
181   included in the message).  Even better if even a user can understand what
182   goes wrong, but the main audience for the messages is the developer who
183   caused the test to fail.
184
185 .. _Google Test: http://code.google.com/p/googletest/
186 .. _Google Test Primer: http://code.google.com/p/googletest/wiki/V1_7_Primer
187 .. _Google Mock: http://code.google.com/p/googlemock/
188
189 .. include:: /fragments/doxygen-links.rst
190
191 MPI tests
192 ---------
193
194 If your test makes specific requirements on the number of MPI ranks,
195 or needs a communicator as part of its implementation, then there are
196 GROMACS-specific extensions that make normal-looking GoogleTests work
197 well in these cases. Use ``GMX_TEST_MPI(RankRequirement)`` and declare
198 the test with ``gmx_add_mpi_unit_test`` to teach ``CTest`` how to run
199 the test regardless of whether the build is with thread-MPI or real
200 MPI. See ``src/testutils/include/mpitest.h`` for details.