more documentation for adding unittest
This commit is contained in:
committed by
Richard Berger
parent
2a8cc331e7
commit
bbe50ab5c1
@ -21,16 +21,202 @@ tests can be added by simply adding more of those input files. Those
|
|||||||
tests should be seen more as a hybrid between unit and regression tests.
|
tests should be seen more as a hybrid between unit and regression tests.
|
||||||
|
|
||||||
When adding tests it is recommended to also :ref:`enable support for
|
When adding tests it is recommended to also :ref:`enable support for
|
||||||
code coverage reporting <testing>`, so that it is possible to monitor
|
code coverage reporting <testing>`, and study the coverage reports
|
||||||
how large a fraction of the code of a given file is executed during
|
so that it is possible to monitor which parts of the code of a given
|
||||||
the tests.
|
file are executed during the tests and which tests would need to be
|
||||||
|
added to increase the coverage.
|
||||||
|
|
||||||
|
The tests are grouped into categories and corresponding folders.
|
||||||
|
The following sections describe how the tests are implemented and
|
||||||
|
executed in those categories with increasing complexity of tests
|
||||||
|
and implementation.
|
||||||
|
|
||||||
|
|
||||||
Adding tests for styles computing forces
|
Tests for utility functions
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These tests are driven by programs in the ``unittest/utils`` folder
|
||||||
|
and most closely resemble conventional unit tests. There is one test
|
||||||
|
program for each namespace or group of classes or file. The naming
|
||||||
|
convention for the sources and executables is that they start with
|
||||||
|
with ``test_``. The following sources and groups of tests are currently
|
||||||
|
available:
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
:widths: auto
|
||||||
|
:align: left
|
||||||
|
|
||||||
|
* - File name:
|
||||||
|
- Test name:
|
||||||
|
- Description:
|
||||||
|
* - ``test_fmtlib.cpp``
|
||||||
|
- FmtLib
|
||||||
|
- Tests for ``fmtlib::`` functions used by LAMMPS
|
||||||
|
* - ``test_math_eigen_impl.cpp``
|
||||||
|
- MathEigen
|
||||||
|
- Tests for ``MathEigen::`` classes and functions
|
||||||
|
* - ``test_mempool.cpp``
|
||||||
|
- MemPool
|
||||||
|
- Tests for :cpp:class:`MyPage <LAMMPS_NS::MyPage>` and :cpp:class:`MyPoolChunk <LAMMPS_NS::MyPoolChunk>`
|
||||||
|
* - ``test_tokenizer.cpp``
|
||||||
|
- Tokenizer
|
||||||
|
- Tests for :cpp:class:`Tokenizer <LAMMPS_NS::Tokenizer>` and :cpp:class:`ValueTokenizer <LAMMPS_NS::ValueTokenizer>`
|
||||||
|
* - ``test_utils.cpp``
|
||||||
|
- Utils
|
||||||
|
- Tests for ``utils::`` :doc:`functions <Developer_utils>`
|
||||||
|
|
||||||
|
To add tests either an existing source file needs to be modified or a
|
||||||
|
new source file needs to be added to the distribution and enabled for
|
||||||
|
testing. To add a new file suitable CMake script code needs to be added
|
||||||
|
to the ``CMakeLists.txt`` file in the ``unittest/utils`` folder. Example:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
add_executable(test_tokenizer test_tokenizer.cpp)
|
||||||
|
target_link_libraries(test_tokenizer PRIVATE lammps GTest::GMockMain GTest::GMock GTest::GTest)
|
||||||
|
add_test(Tokenizer test_tokenizer)
|
||||||
|
|
||||||
|
This adds instructions to build the ``test_tokenizer`` executable from
|
||||||
|
``test_tokenizer.cpp`` and links it with the googletest libraries and the
|
||||||
|
LAMMPS library as well as it uses the ``main()`` function from the
|
||||||
|
GMock library of googletest. The third line registers the executable
|
||||||
|
as a test program to be run from ``ctest`` under the name ``Tokenizer``.
|
||||||
|
|
||||||
|
The test executable itself will execute multiple individual tests
|
||||||
|
through the googletest framework. In this case each test consists of
|
||||||
|
creating a tokenizer class instance with a given string and explicit or
|
||||||
|
default separator choice, and then executing member functions of the
|
||||||
|
class and comparing their results with expected values. A few examples:
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
TEST(Tokenizer, empty_string)
|
||||||
|
{
|
||||||
|
Tokenizer t("", " ");
|
||||||
|
ASSERT_EQ(t.count(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Tokenizer, two_words)
|
||||||
|
{
|
||||||
|
Tokenizer t("test word", " ");
|
||||||
|
ASSERT_EQ(t.count(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Tokenizer, default_separators)
|
||||||
|
{
|
||||||
|
Tokenizer t(" \r\n test \t word \f");
|
||||||
|
ASSERT_THAT(t.next(), Eq("test"));
|
||||||
|
ASSERT_THAT(t.next(), Eq("word"));
|
||||||
|
ASSERT_EQ(t.count(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Each of these TEST functions will become an individual
|
||||||
|
test run by the test program. When using the ``ctest``
|
||||||
|
command as a front end to run the tests, their output
|
||||||
|
will be suppressed and only a summary printed, but adding
|
||||||
|
the '-V' option will then produce output from the tests
|
||||||
|
above like the following:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
[...]
|
||||||
|
1: [ RUN ] Tokenizer.empty_string
|
||||||
|
1: [ OK ] Tokenizer.empty_string (0 ms)
|
||||||
|
1: [ RUN ] Tokenizer.two_words
|
||||||
|
1: [ OK ] Tokenizer.two_words (0 ms)
|
||||||
|
1: [ RUN ] Tokenizer.default_separators
|
||||||
|
1: [ OK ] Tokenizer.default_separators (0 ms)
|
||||||
|
[...]
|
||||||
|
|
||||||
|
The MathEigen test collection has been adapted from a standalone test
|
||||||
|
and does not use the googletest framework and thus not representative.
|
||||||
|
The other test sources, however, can serve as guiding examples for
|
||||||
|
additional tests.
|
||||||
|
|
||||||
|
Tests for individual LAMMPS commands
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These tests are a bit more complex as they require to first create a
|
||||||
|
:cpp:class:`LAMMPS <LAMMPS_NS::LAMMPS>` class instance and then use the
|
||||||
|
:doc:`C++ API <Cplusplus>` to pass individual commands to that LAMMPS
|
||||||
|
instance. For that reason these tests use a googletest "test fixture",
|
||||||
|
i.e. a class derived from ``testing::Test`` that will create (and
|
||||||
|
delete) the required LAMMPS class instance for each set of tests in a
|
||||||
|
TEST_F() function. Please see the individual source files for different
|
||||||
|
examples of setting up suitable test fixtures. Here is an example for
|
||||||
|
implementing a test using a fixture by first checking the default
|
||||||
|
value and then issuing LAMMPS commands and checking whether they
|
||||||
|
have the desired effect:
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
TEST_F(SimpleCommandsTest, ResetTimestep)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(lmp->update->ntimestep, 0);
|
||||||
|
|
||||||
|
if (!verbose) ::testing::internal::CaptureStdout();
|
||||||
|
lmp->input->one("reset_timestep 10");
|
||||||
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
ASSERT_EQ(lmp->update->ntimestep, 10);
|
||||||
|
|
||||||
|
if (!verbose) ::testing::internal::CaptureStdout();
|
||||||
|
lmp->input->one("reset_timestep 0");
|
||||||
|
if (!verbose) ::testing::internal::GetCapturedStdout();
|
||||||
|
ASSERT_EQ(lmp->update->ntimestep, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Please note the use of the (global) verbose variable to control whether
|
||||||
|
the LAMMPS command will be silent by capturing the output or not. In
|
||||||
|
the default case, verbose == false, the test output will be compact and
|
||||||
|
not mixed with LAMMPS output. However setting the verbose flag (via
|
||||||
|
setting the TEST_ARGS environment variable, ``TEST_ARGS=-v``) can be
|
||||||
|
helpful to understand why tests fail unexpectedly.
|
||||||
|
|
||||||
|
Another complexity of these tests stems from the need to capture
|
||||||
|
situations where LAMMPS will stop with an error, i.e. handle so-called
|
||||||
|
"death tests". Here the LAMMPS code will operate differently depending
|
||||||
|
on whether it was configured to throw C++ exceptions on errors or call
|
||||||
|
either ``exit()`` or ``MPI_Abort()``. In the latter case, the test code
|
||||||
|
also needs to detect whether LAMMPS was compiled with the OpenMPI
|
||||||
|
library, as OpenMPI is **only** compatible the death test options of the
|
||||||
|
googletest library when C++ exceptions are enabled; otherwise those
|
||||||
|
"death tests" must be skipped to avoid reporting bogus failures. The
|
||||||
|
specifics of this step are implemented in the TEST_FAILURE()
|
||||||
|
macro. These tests operate by capturing the screen output when executing
|
||||||
|
the failing command and then comparing that with a provided regular
|
||||||
|
expression string pattern. Example:
|
||||||
|
|
||||||
|
.. code-block:: C++
|
||||||
|
|
||||||
|
TEST_F(SimpleCommandsTest, UnknownCommand)
|
||||||
|
{
|
||||||
|
TEST_FAILURE(".*ERROR: Unknown command.*", lmp->input->one("XXX one two"););
|
||||||
|
}
|
||||||
|
|
||||||
|
The following test programs are currently available:
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
:widths: auto
|
||||||
|
:align: left
|
||||||
|
|
||||||
|
* - File name:
|
||||||
|
- Test name:
|
||||||
|
- Description:
|
||||||
|
* - ``test_simple_commands.cpp``
|
||||||
|
- SimpleCommands
|
||||||
|
- Tests for LAMMPS commands that do not require a box
|
||||||
|
* - ``test_lattice_region.cpp``
|
||||||
|
- LatticeRegion
|
||||||
|
- Tests to validate the :doc:`lattice <lattice>` and :doc:`region <region>` commands
|
||||||
|
* - ``test_kim_commands.cpp``
|
||||||
|
- KimCommands
|
||||||
|
- Tests for several commands from the :ref:`KIM package <PKG-KIM>`
|
||||||
|
* - ``test_reset_ids.cpp``
|
||||||
|
- ResetIDs
|
||||||
|
- Tests to validate the :doc:`reset_atom_ids <reset_atom_ids>` and :doc:`reset_mol_ids <reset_mol_ids>` commands
|
||||||
|
|
||||||
Adding tests for individual LAMMPS commands
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Adding tests for the C-style library interface
|
Adding tests for the C-style library interface
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -44,8 +230,45 @@ Adding tests for the Fortran interface
|
|||||||
Adding tests for the C++-style library interface
|
Adding tests for the C++-style library interface
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Adding tests for utility functions
|
Adding tests for styles computing or modifying forces
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These are tests common configurations for pair styles, bond styles,
|
||||||
|
angle styles, kspace styles and certain fix styles. Those are tests
|
||||||
|
driven by some test executables build from sources in the
|
||||||
|
``unittest/force-styles`` folder and use LAMMPS input template and data
|
||||||
|
files as well as input files in YAML format from the
|
||||||
|
``unittest/force-styles/tests`` folder. The YAML file names have to
|
||||||
|
follow some naming conventions so they get associated with the test
|
||||||
|
programs and categorized and listed with canonical names in the list
|
||||||
|
of tests as displayed by ``ctest -N``. If you add a new YAML file,
|
||||||
|
you need to re-run CMake to update the corresponding list of tests.
|
||||||
|
|
||||||
|
A minimal YAML file for a (molecular) pair style test will looks
|
||||||
|
something like the following (see ``mol-pair-zero.yaml``):
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
---
|
||||||
|
lammps_version: 24 Aug 2020
|
||||||
|
date_generated: Tue Sep 15 09:44:21 202
|
||||||
|
epsilon: 1e-14
|
||||||
|
prerequisites: ! |
|
||||||
|
atom full
|
||||||
|
pair zero
|
||||||
|
pre_commands: ! ""
|
||||||
|
post_commands: ! ""
|
||||||
|
input_file: in.fourmol
|
||||||
|
pair_style: zero 8.0
|
||||||
|
pair_coeff: ! |
|
||||||
|
* *
|
||||||
|
extract: ! ""
|
||||||
|
natoms: 29
|
||||||
|
init_vdwl: 0
|
||||||
|
init_coul: 0
|
||||||
|
|
||||||
|
[...]
|
||||||
|
|
||||||
|
|
||||||
Adding tests for programs in the tools folder
|
Adding tests for programs in the tools folder
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|||||||
@ -1119,11 +1119,13 @@ gmail
|
|||||||
gmake
|
gmake
|
||||||
gmask
|
gmask
|
||||||
Gmask
|
Gmask
|
||||||
|
GMock
|
||||||
gneb
|
gneb
|
||||||
GNEB
|
GNEB
|
||||||
Goldfarb
|
Goldfarb
|
||||||
Gonzalez-Melchor
|
Gonzalez-Melchor
|
||||||
googlemail
|
googlemail
|
||||||
|
googletest
|
||||||
Gordan
|
Gordan
|
||||||
GPa
|
GPa
|
||||||
gpu
|
gpu
|
||||||
|
|||||||
Reference in New Issue
Block a user