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