Files
lammps/doc/html/Developer_unittest.html
2025-01-13 14:55:48 +00:00

786 lines
62 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>4.12. Adding tests for unit testing &mdash; LAMMPS documentation</title>
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="_static/sphinx-design.min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/lammps.css" type="text/css" />
<link rel="shortcut icon" href="_static/lammps.ico"/>
<link rel="canonical" href="https://docs.lammps.org/Developer_unittest.html" />
<!--[if lt IE 9]>
<script src="_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=5929fcd5"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/design-tabs.js?v=f930bc37"></script>
<script async="async" src="_static/mathjax/es5/tex-mml-chtml.js?v=cadf963e"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="4.13. C++ base classes" href="Classes.html" />
<link rel="prev" title="4.11. Writing plugins" href="Developer_plugins.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="Manual.html">
<img src="_static/lammps-logo.png" class="logo" alt="Logo"/>
</a>
<div class="lammps_version">Version: <b>19 Nov 2024</b></div>
<div class="lammps_release">git info: </div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">User Guide</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Intro.html">1. Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="Install.html">2. Install LAMMPS</a></li>
<li class="toctree-l1"><a class="reference internal" href="Build.html">3. Build LAMMPS</a></li>
<li class="toctree-l1"><a class="reference internal" href="Run_head.html">4. Run LAMMPS</a></li>
<li class="toctree-l1"><a class="reference internal" href="Commands.html">5. Commands</a></li>
<li class="toctree-l1"><a class="reference internal" href="Packages.html">6. Optional packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="Speed.html">7. Accelerate performance</a></li>
<li class="toctree-l1"><a class="reference internal" href="Howto.html">8. Howto discussions</a></li>
<li class="toctree-l1"><a class="reference internal" href="Examples.html">9. Example scripts</a></li>
<li class="toctree-l1"><a class="reference internal" href="Tools.html">10. Auxiliary tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="Errors.html">11. Errors</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Programmer Guide</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Library.html">1. LAMMPS Library Interfaces</a></li>
<li class="toctree-l1"><a class="reference internal" href="Python_head.html">2. Use Python with LAMMPS</a></li>
<li class="toctree-l1"><a class="reference internal" href="Modify.html">3. Modifying &amp; extending LAMMPS</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="Developer.html">4. Information for Developers</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="Developer_org.html">4.1. Source files</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_org.html#class-topology">4.2. Class topology</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_code_design.html">4.3. Code design</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_parallel.html">4.4. Parallel algorithms</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_atom.html">4.5. Accessing per-atom data</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_comm_ops.html">4.6. Communication patterns</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_flow.html">4.7. How a timestep works</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_write.html">4.8. Writing new styles</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_notes.html">4.9. Notes for developers and code maintainers</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_updating.html">4.10. Notes for updating code written for older LAMMPS versions</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_plugins.html">4.11. Writing plugins</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">4.12. Adding tests for unit testing</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-utility-functions">4.12.1. Tests for utility functions</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-individual-lammps-commands">4.12.2. Tests for individual LAMMPS commands</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-the-c-style-library-interface">4.12.3. Tests for the C-style library interface</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-the-python-module-and-package">4.12.4. Tests for the Python module and package</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-the-fortran-interface">4.12.5. Tests for the Fortran interface</a></li>
<li class="toctree-l3"><a class="reference internal" href="#id1">4.12.6. Tests for the C++-style library interface</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-reading-and-writing-file-formats">4.12.7. Tests for reading and writing file formats</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-styles-computing-or-modifying-forces">4.12.8. Tests for styles computing or modifying forces</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tests-for-programs-in-the-tools-folder">4.12.9. Tests for programs in the tools folder</a></li>
<li class="toctree-l3"><a class="reference internal" href="#troubleshooting-failed-unit-tests">4.12.10. Troubleshooting failed unit tests</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="Classes.html">4.13. C++ base classes</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_platform.html">4.14. Platform abstraction functions</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html">4.15. Utility functions</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#special-math-functions">4.16. Special Math functions</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#tokenizer-classes">4.17. Tokenizer classes</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#argument-parsing-classes">4.18. Argument parsing classes</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#file-reader-classes">4.19. File reader classes</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#memory-pool-classes">4.20. Memory pool classes</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#eigensolver-functions">4.21. Eigensolver functions</a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_utils.html#communication-buffer-coding-with-ubuf">4.22. Communication buffer coding with <em>ubuf</em></a></li>
<li class="toctree-l2"><a class="reference internal" href="Developer_grid.html">4.23. Use of distributed grids within style classes</a></li>
</ul>
</li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Command Reference</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="commands_list.html">Commands</a></li>
<li class="toctree-l1"><a class="reference internal" href="fixes.html">Fix Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="computes.html">Compute Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="pairs.html">Pair Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="bonds.html">Bond Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="angles.html">Angle Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="dihedrals.html">Dihedral Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="impropers.html">Improper Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="dumps.html">Dump Styles</a></li>
<li class="toctree-l1"><a class="reference internal" href="fix_modify_atc_commands.html">fix_modify AtC commands</a></li>
<li class="toctree-l1"><a class="reference internal" href="Bibliography.html">Bibliography</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="Manual.html">LAMMPS</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content style-external-links">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="Manual.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="Developer.html"><span class="section-number">4. </span>Information for Developers</a></li>
<li class="breadcrumb-item active"><span class="section-number">4.12. </span>Adding tests for unit testing</li>
<li class="wy-breadcrumbs-aside">
<a href="https://www.lammps.org"><img src="_static/lammps-logo.png" width="64" height="16" alt="LAMMPS Homepage"></a> | <a href="Commands_all.html">Commands</a>
</li>
</ul><div class="rst-breadcrumbs-buttons" role="navigation" aria-label="Sequential page navigation">
<a href="Developer_plugins.html" class="btn btn-neutral float-left" title="4.11. Writing plugins" accesskey="p"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="Classes.html" class="btn btn-neutral float-right" title="4.13. C++ base classes" accesskey="n">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<p><span class="math notranslate nohighlight">\(\renewcommand{\AA}{\text{Å}}\)</span></p>
<section id="adding-tests-for-unit-testing">
<h1><span class="section-number">4.12. </span>Adding tests for unit testing<a class="headerlink" href="#adding-tests-for-unit-testing" title="Link to this heading"></a></h1>
<p>This section discusses adding or expanding tests for the unit test
infrastructure included into the LAMMPS source code distribution.
Unlike example inputs, unit tests focus on testing the “local” behavior
of individual features, tend to run fast, and should be set up to cover
as much of the added code as possible. When contributing code to the
distribution, the LAMMPS developers will appreciate if additions to the
integrated unit test facility are included.</p>
<p>Given the complex nature of MD simulations where many operations can
only be performed when suitable “real” simulation environment has been
set up, not all tests will be unit tests in the strict definition of
the term. They are rather executed on a more abstract level by issuing
LAMMPS script commands and then inspecting the changes to the internal
data. For some classes of tests, generic test programs have been
written that can be applied to parts of LAMMPS that use the same
interface (via polymorphism) and those are driven by input files, so
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.</p>
<p>When adding tests it is recommended to also <a class="reference internal" href="Build_development.html#testing"><span class="std std-ref">enable support for
code coverage reporting</span></a>, and study the coverage reports
so that it is possible to monitor which parts of the code of a given
file are executed during the tests and which tests would need to be
added to increase the coverage.</p>
<p>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.</p>
<section id="tests-for-utility-functions">
<h2><span class="section-number">4.12.1. </span>Tests for utility functions<a class="headerlink" href="#tests-for-utility-functions" title="Link to this heading"></a></h2>
<p>These tests are driven by programs in the <code class="docutils literal notranslate"><span class="pre">unittest/utils</span></code> 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 <code class="docutils literal notranslate"><span class="pre">test_</span></code>. The following sources and groups of tests are currently
available:</p>
<table class="docutils align-left">
<colgroup>
<col style="width: 32.0%" />
<col style="width: 18.0%" />
<col style="width: 50.0%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>File name:</p></th>
<th class="head"><p>Test name:</p></th>
<th class="head"><p>Description:</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">test_argutils.cpp</span></code></p></td>
<td><p>ArgInfo</p></td>
<td><p>Tests for <code class="docutils literal notranslate"><span class="pre">ArgInfo</span></code> class used by LAMMPS</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">test_fmtlib.cpp</span></code></p></td>
<td><p>FmtLib</p></td>
<td><p>Tests for <code class="docutils literal notranslate"><span class="pre">fmtlib::</span></code> functions used by LAMMPS</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">test_math_eigen_impl.cpp</span></code></p></td>
<td><p>MathEigen</p></td>
<td><p>Tests for <code class="docutils literal notranslate"><span class="pre">MathEigen::</span></code> classes and functions</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">test_mempool.cpp</span></code></p></td>
<td><p>MemPool</p></td>
<td><p>Tests for <a class="reference internal" href="Developer_utils.html#_CPPv4N9LAMMPS_NS6MyPageE" title="LAMMPS_NS::MyPage"><code class="xref cpp cpp-class docutils literal notranslate"><span class="pre">MyPage</span></code></a> and <a class="reference internal" href="Developer_utils.html#_CPPv4N9LAMMPS_NS11MyPoolChunkE" title="LAMMPS_NS::MyPoolChunk"><code class="xref cpp cpp-class docutils literal notranslate"><span class="pre">MyPoolChunk</span></code></a></p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">test_tokenizer.cpp</span></code></p></td>
<td><p>Tokenizer</p></td>
<td><p>Tests for <a class="reference internal" href="Developer_utils.html#_CPPv4N9LAMMPS_NS9TokenizerE" title="LAMMPS_NS::Tokenizer"><code class="xref cpp cpp-class docutils literal notranslate"><span class="pre">Tokenizer</span></code></a> and <a class="reference internal" href="Developer_utils.html#_CPPv4N9LAMMPS_NS14ValueTokenizerE" title="LAMMPS_NS::ValueTokenizer"><code class="xref cpp cpp-class docutils literal notranslate"><span class="pre">ValueTokenizer</span></code></a></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">test_utils.cpp</span></code></p></td>
<td><p>Utils</p></td>
<td><p>Tests for <code class="docutils literal notranslate"><span class="pre">utils::</span></code> <a class="reference internal" href="Developer_utils.html"><span class="doc">functions</span></a></p></td>
</tr>
</tbody>
</table>
<p>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 <code class="docutils literal notranslate"><span class="pre">CMakeLists.txt</span></code> file in the <code class="docutils literal notranslate"><span class="pre">unittest/utils</span></code> folder. Example:</p>
<div class="highlight-cmake notranslate"><div class="highlight"><pre><span></span><span class="nb">add_executable</span><span class="p">(</span><span class="s">test_tokenizer</span><span class="w"> </span><span class="s">test_tokenizer.cpp</span><span class="p">)</span>
<span class="nb">target_link_libraries</span><span class="p">(</span><span class="s">test_tokenizer</span><span class="w"> </span><span class="s">PRIVATE</span><span class="w"> </span><span class="s">lammps</span><span class="w"> </span><span class="s">GTest::GMockMain</span><span class="w"> </span><span class="s">GTest::GMock</span><span class="w"> </span><span class="s">GTest::GTest</span><span class="p">)</span>
<span class="nb">add_test</span><span class="p">(</span><span class="s">Tokenizer</span><span class="w"> </span><span class="s">test_tokenizer</span><span class="p">)</span>
</pre></div>
</div>
<p>This adds instructions to build the <code class="docutils literal notranslate"><span class="pre">test_tokenizer</span></code> executable from
<code class="docutils literal notranslate"><span class="pre">test_tokenizer.cpp</span></code> and links it with the GoogleTest libraries and the
LAMMPS library as well as it uses the <code class="docutils literal notranslate"><span class="pre">main()</span></code> function from the
GoogleMock library of GoogleTest. The third line registers the executable
as a test program to be run from <code class="docutils literal notranslate"><span class="pre">ctest</span></code> under the name <code class="docutils literal notranslate"><span class="pre">Tokenizer</span></code>.</p>
<p>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:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">TEST</span><span class="p">(</span><span class="n">Tokenizer</span><span class="p">,</span><span class="w"> </span><span class="n">empty_string</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">Tokenizer</span><span class="w"> </span><span class="n">t</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot; &quot;</span><span class="p">);</span>
<span class="w"> </span><span class="n">ASSERT_EQ</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">count</span><span class="p">(),</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">TEST</span><span class="p">(</span><span class="n">Tokenizer</span><span class="p">,</span><span class="w"> </span><span class="n">two_words</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">Tokenizer</span><span class="w"> </span><span class="n">t</span><span class="p">(</span><span class="s">&quot;test word&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot; &quot;</span><span class="p">);</span>
<span class="w"> </span><span class="n">ASSERT_EQ</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">count</span><span class="p">(),</span><span class="w"> </span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">TEST</span><span class="p">(</span><span class="n">Tokenizer</span><span class="p">,</span><span class="w"> </span><span class="n">default_separators</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">Tokenizer</span><span class="w"> </span><span class="n">t</span><span class="p">(</span><span class="s">&quot; </span><span class="se">\r\n</span><span class="s"> test </span><span class="se">\t</span><span class="s"> word </span><span class="se">\f</span><span class="s">&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="n">ASSERT_THAT</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">next</span><span class="p">(),</span><span class="w"> </span><span class="n">Eq</span><span class="p">(</span><span class="s">&quot;test&quot;</span><span class="p">));</span>
<span class="w"> </span><span class="n">ASSERT_THAT</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">next</span><span class="p">(),</span><span class="w"> </span><span class="n">Eq</span><span class="p">(</span><span class="s">&quot;word&quot;</span><span class="p">));</span>
<span class="w"> </span><span class="n">ASSERT_EQ</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">count</span><span class="p">(),</span><span class="w"> </span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Each of these TEST functions will become an individual
test run by the test program. When using the <code class="docutils literal notranslate"><span class="pre">ctest</span></code>
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:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">[...]</span>
<span class="go">1: [ RUN ] Tokenizer.empty_string</span>
<span class="go">1: [ OK ] Tokenizer.empty_string (0 ms)</span>
<span class="go">1: [ RUN ] Tokenizer.two_words</span>
<span class="go">1: [ OK ] Tokenizer.two_words (0 ms)</span>
<span class="go">1: [ RUN ] Tokenizer.default_separators</span>
<span class="go">1: [ OK ] Tokenizer.default_separators (0 ms)</span>
<span class="go">[...]</span>
</pre></div>
</div>
<p>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.</p>
</section>
<section id="tests-for-individual-lammps-commands">
<h2><span class="section-number">4.12.2. </span>Tests for individual LAMMPS commands<a class="headerlink" href="#tests-for-individual-lammps-commands" title="Link to this heading"></a></h2>
<p>The tests <code class="docutils literal notranslate"><span class="pre">unittest/commands</span></code> are a bit more complex as they require
to first create a <a class="reference internal" href="Classes_lammps.html#_CPPv4N9LAMMPS_NS6LAMMPSE" title="LAMMPS_NS::LAMMPS"><code class="xref cpp cpp-class docutils literal notranslate"><span class="pre">LAMMPS</span></code></a> class instance
and then use the <a class="reference internal" href="Cplusplus.html"><span class="doc">C++ API</span></a> to pass individual commands
to that LAMMPS instance. For that reason these tests use a GoogleTest
“test fixture”, i.e. a class derived from <code class="docutils literal notranslate"><span class="pre">testing::Test</span></code> that will
create (and delete) the required LAMMPS class instance for each set of
tests in a <code class="docutils literal notranslate"><span class="pre">TEST_F()</span></code> 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:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">TEST_F</span><span class="p">(</span><span class="n">SimpleCommandsTest</span><span class="p">,</span><span class="w"> </span><span class="n">ResetTimestep</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">ASSERT_EQ</span><span class="p">(</span><span class="n">lmp</span><span class="o">-&gt;</span><span class="n">update</span><span class="o">-&gt;</span><span class="n">ntimestep</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">BEGIN_HIDE_OUTPUT</span><span class="p">();</span>
<span class="w"> </span><span class="n">command</span><span class="p">(</span><span class="s">&quot;reset_timestep 10&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="n">END_HIDE_OUTPUT</span><span class="p">();</span>
<span class="w"> </span><span class="n">ASSERT_EQ</span><span class="p">(</span><span class="n">lmp</span><span class="o">-&gt;</span><span class="n">update</span><span class="o">-&gt;</span><span class="n">ntimestep</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="p">);</span>
<span class="w"> </span><span class="n">BEGIN_HIDE_OUTPUT</span><span class="p">();</span>
<span class="w"> </span><span class="n">command</span><span class="p">(</span><span class="s">&quot;reset_timestep 0&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="n">END_HIDE_OUTPUT</span><span class="p">();</span>
<span class="w"> </span><span class="n">ASSERT_EQ</span><span class="p">(</span><span class="n">lmp</span><span class="o">-&gt;</span><span class="n">update</span><span class="o">-&gt;</span><span class="n">ntimestep</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_FAILURE</span><span class="p">(</span><span class="s">&quot;.*ERROR: Timestep must be &gt;= 0.*&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">command</span><span class="p">(</span><span class="s">&quot;reset_timestep -10&quot;</span><span class="p">););</span>
<span class="w"> </span><span class="n">TEST_FAILURE</span><span class="p">(</span><span class="s">&quot;.*ERROR: Illegal reset_timestep .*&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">command</span><span class="p">(</span><span class="s">&quot;reset_timestep&quot;</span><span class="p">););</span>
<span class="w"> </span><span class="n">TEST_FAILURE</span><span class="p">(</span><span class="s">&quot;.*ERROR: Illegal reset_timestep .*&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">command</span><span class="p">(</span><span class="s">&quot;reset_timestep 10 10&quot;</span><span class="p">););</span>
<span class="w"> </span><span class="n">TEST_FAILURE</span><span class="p">(</span><span class="s">&quot;.*ERROR: Expected integer .*&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">command</span><span class="p">(</span><span class="s">&quot;reset_timestep xxx&quot;</span><span class="p">););</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Please note the use of the <code class="docutils literal notranslate"><span class="pre">BEGIN_HIDE_OUTPUT</span></code> and <code class="docutils literal notranslate"><span class="pre">END_HIDE_OUTPUT</span></code>
functions that will capture output from running LAMMPS. This is normally
discarded but by setting the verbose flag (via setting the <code class="docutils literal notranslate"><span class="pre">TEST_ARGS</span></code>
environment variable, <code class="docutils literal notranslate"><span class="pre">TEST_ARGS=-v</span></code>) it can be printed and used to
understand why tests fail unexpectedly.</p>
<p>The specifics of so-called “death tests”, i.e. conditions where LAMMPS
should fail and throw an exception, are implemented in the
<code class="docutils literal notranslate"><span class="pre">TEST_FAILURE()</span></code> 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:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">TEST_F</span><span class="p">(</span><span class="n">SimpleCommandsTest</span><span class="p">,</span><span class="w"> </span><span class="n">UnknownCommand</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">TEST_FAILURE</span><span class="p">(</span><span class="s">&quot;.*ERROR: Unknown command.*&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">lmp</span><span class="o">-&gt;</span><span class="n">input</span><span class="o">-&gt;</span><span class="n">one</span><span class="p">(</span><span class="s">&quot;XXX one two&quot;</span><span class="p">););</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The following test programs are currently available:</p>
<table class="docutils align-left">
<thead>
<tr class="row-odd"><th class="head"><p>File name:</p></th>
<th class="head"><p>Test name:</p></th>
<th class="head"><p>Description:</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">test_simple_commands.cpp</span></code></p></td>
<td><p>SimpleCommands</p></td>
<td><p>Tests for LAMMPS commands that do not require a box</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">test_lattice_region.cpp</span></code></p></td>
<td><p>LatticeRegion</p></td>
<td><p>Tests to validate the <a class="reference internal" href="lattice.html"><span class="doc">lattice</span></a> and <a class="reference internal" href="region.html"><span class="doc">region</span></a> commands</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">test_groups.cpp</span></code></p></td>
<td><p>GroupTest</p></td>
<td><p>Tests to validate the <a class="reference internal" href="group.html"><span class="doc">group</span></a> command</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">test_variables.cpp</span></code></p></td>
<td><p>VariableTest</p></td>
<td><p>Tests to validate the <a class="reference internal" href="variable.html"><span class="doc">variable</span></a> command</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">test_kim_commands.cpp</span></code></p></td>
<td><p>KimCommands</p></td>
<td><p>Tests for several commands from the <a class="reference internal" href="Packages_details.html#pkg-kim"><span class="std std-ref">KIM package</span></a></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">test_reset_atoms.cpp</span></code></p></td>
<td><p>ResetAtoms</p></td>
<td><p>Tests to validate the <a class="reference internal" href="reset_atoms.html"><span class="doc">reset_atoms</span></a> sub-commands</p></td>
</tr>
</tbody>
</table>
</section>
<section id="tests-for-the-c-style-library-interface">
<h2><span class="section-number">4.12.3. </span>Tests for the C-style library interface<a class="headerlink" href="#tests-for-the-c-style-library-interface" title="Link to this heading"></a></h2>
<p>Tests for validating the LAMMPS C-style library interface are in the
<code class="docutils literal notranslate"><span class="pre">unittest/c-library</span></code> folder. They are implemented either to be used
for utility functions or for LAMMPS commands, but use the functions
implemented in the <code class="docutils literal notranslate"><span class="pre">src/library.cpp</span></code> file as much as possible. There
may be some overlap with other tests, but only in as much as is required
to test the C-style library API. The tests are distributed over
multiple test programs which try to match the grouping of the
functions in the source code and <a class="reference internal" href="Library.html#lammps-c-api"><span class="std std-ref">in the manual</span></a>.</p>
<p>This group of tests also includes tests invoking LAMMPS in parallel
through the library interface, provided that LAMMPS was compiled with
MPI support. These include tests where LAMMPS is run in multi-partition
mode or only on a subset of the MPI world communicator. The CMake
script code for adding this kind of test looks like this:</p>
<div class="highlight-cmake notranslate"><div class="highlight"><pre><span></span><span class="nb">if</span><span class="w"> </span><span class="p">(</span><span class="s">BUILD_MPI</span><span class="p">)</span>
<span class="w"> </span><span class="nb">add_executable</span><span class="p">(</span><span class="s">test_library_mpi</span><span class="w"> </span><span class="s">test_library_mpi.cpp</span><span class="p">)</span>
<span class="w"> </span><span class="nb">target_link_libraries</span><span class="p">(</span><span class="s">test_library_mpi</span><span class="w"> </span><span class="s">PRIVATE</span><span class="w"> </span><span class="s">lammps</span><span class="w"> </span><span class="s">GTest::GTest</span><span class="w"> </span><span class="s">GTest::GMock</span><span class="p">)</span>
<span class="w"> </span><span class="nb">target_compile_definitions</span><span class="p">(</span><span class="s">test_library_mpi</span><span class="w"> </span><span class="s">PRIVATE</span><span class="w"> </span><span class="o">${</span><span class="nv">TEST_CONFIG_DEFS</span><span class="o">}</span><span class="p">)</span>
<span class="w"> </span><span class="nb">add_mpi_test</span><span class="p">(</span><span class="s">NAME</span><span class="w"> </span><span class="s">LibraryMPI</span><span class="w"> </span><span class="s">NUM_PROCS</span><span class="w"> </span><span class="s">4</span><span class="w"> </span><span class="s">COMMAND</span><span class="w"> </span><span class="o">$&lt;</span><span class="nv">TARGET_FILE:test_library_mpi</span><span class="o">&gt;</span><span class="p">)</span>
<span class="nb">endif</span><span class="p">()</span>
</pre></div>
</div>
<p>Note the custom function <code class="docutils literal notranslate"><span class="pre">add_mpi_test()</span></code> which adapts how <code class="docutils literal notranslate"><span class="pre">ctest</span></code>
will execute the test so it is launched in parallel (with 4 MPI ranks).</p>
</section>
<section id="tests-for-the-python-module-and-package">
<h2><span class="section-number">4.12.4. </span>Tests for the Python module and package<a class="headerlink" href="#tests-for-the-python-module-and-package" title="Link to this heading"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">unittest/python</span></code> folder contains primarily tests for classes and
functions in the LAMMPS python module but also for commands in the
PYTHON package. These tests are only enabled if the necessary
prerequisites are detected or enabled during configuration and
compilation of LAMMPS (shared library build enabled, Python interpreter
found, Python development files found).</p>
<p>The Python tests are implemented using the <code class="docutils literal notranslate"><span class="pre">unittest</span></code> standard Python
module and split into multiple files with similar categories as the
tests for the C-style library interface.</p>
</section>
<section id="tests-for-the-fortran-interface">
<h2><span class="section-number">4.12.5. </span>Tests for the Fortran interface<a class="headerlink" href="#tests-for-the-fortran-interface" title="Link to this heading"></a></h2>
<p>Tests for using the Fortran module are in the <code class="docutils literal notranslate"><span class="pre">unittest/fortran</span></code>
folder. Since they are also using the GoogleTest library, they require
implementing test wrappers in C++ that will call fortran functions
which provide a C function interface through ISO_C_BINDINGS that will in
turn call the functions in the LAMMPS Fortran module.</p>
</section>
<section id="id1">
<h2><span class="section-number">4.12.6. </span>Tests for the C++-style library interface<a class="headerlink" href="#id1" title="Link to this heading"></a></h2>
<p>The tests in the <code class="docutils literal notranslate"><span class="pre">unittest/cplusplus</span></code> folder are somewhat similar to
the tests for the C-style library interface, but do not need to test the
several convenience and utility functions that are only available through
the C-style interface. Instead it can focus on the more generic features
that are used internally. This part of the unit tests is currently still
mostly in the planning stage.</p>
</section>
<section id="tests-for-reading-and-writing-file-formats">
<h2><span class="section-number">4.12.7. </span>Tests for reading and writing file formats<a class="headerlink" href="#tests-for-reading-and-writing-file-formats" title="Link to this heading"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">unittest/formats</span></code> folder contains test programs for reading and
writing files like data files, restart files, potential files or dump files.
This covers simple things like the file i/o convenience functions in the
<code class="docutils literal notranslate"><span class="pre">utils::</span></code> namespace to complex tests of atom styles where creating and
deleting atoms with different properties is tested in different ways
and through script commands or reading and writing of data or restart files.</p>
</section>
<section id="tests-for-styles-computing-or-modifying-forces">
<h2><span class="section-number">4.12.8. </span>Tests for styles computing or modifying forces<a class="headerlink" href="#tests-for-styles-computing-or-modifying-forces" title="Link to this heading"></a></h2>
<p>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
<code class="docutils literal notranslate"><span class="pre">unittest/force-styles</span></code> folder and use LAMMPS input template and data
files as well as input files in YAML format from the
<code class="docutils literal notranslate"><span class="pre">unittest/force-styles/tests</span></code> 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 <code class="docutils literal notranslate"><span class="pre">ctest</span> <span class="pre">-N</span></code>. If you add a new YAML file,
you need to re-run CMake to update the corresponding list of tests.</p>
<p>A minimal YAML file for a (molecular) pair style test will looks
something like the following (see <code class="docutils literal notranslate"><span class="pre">mol-pair-zero.yaml</span></code>):</p>
<div class="highlight-yaml notranslate"><div class="highlight"><pre><span></span><span class="nn">---</span>
<span class="nt">lammps_version</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">24 Aug 2020</span>
<span class="nt">date_generated</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Tue Sep 15 09:44:21 202</span>
<span class="nt">epsilon</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1e-14</span>
<span class="nt">prerequisites</span><span class="p">:</span><span class="w"> </span><span class="kt">!</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w"> </span><span class="no">atom full</span>
<span class="w"> </span><span class="no">pair zero</span>
<span class="nt">pre_commands</span><span class="p">:</span><span class="w"> </span><span class="kt">!</span><span class="w"> </span><span class="s">&quot;&quot;</span>
<span class="nt">post_commands</span><span class="p">:</span><span class="w"> </span><span class="kt">!</span><span class="w"> </span><span class="s">&quot;&quot;</span>
<span class="nt">input_file</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">in.fourmol</span>
<span class="nt">pair_style</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">zero 8.0</span>
<span class="nt">pair_coeff</span><span class="p">:</span><span class="w"> </span><span class="kt">!</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w"> </span><span class="no">* *</span>
<span class="nt">extract</span><span class="p">:</span><span class="w"> </span><span class="kt">!</span><span class="w"> </span><span class="s">&quot;&quot;</span>
<span class="nt">natoms</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">29</span>
<span class="nt">init_vdwl</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0</span>
<span class="nt">init_coul</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0</span>
<span class="p p-Indicator">[</span><span class="nv">...</span><span class="p p-Indicator">]</span>
</pre></div>
</div>
<p>The following table describes the available keys and their purpose for
testing pair styles:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>Key:</p></th>
<th class="head"><p>Description:</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>lammps_version</p></td>
<td><p>LAMMPS version used to last update the reference data</p></td>
</tr>
<tr class="row-odd"><td><p>date_generated</p></td>
<td><p>date when the file was last updated</p></td>
</tr>
<tr class="row-even"><td><p>epsilon</p></td>
<td><p>base value for the relative precision required for tests to pass</p></td>
</tr>
<tr class="row-odd"><td><p>prerequisites</p></td>
<td><p>list of style kind / style name pairs required to run the test</p></td>
</tr>
<tr class="row-even"><td><p>pre_commands</p></td>
<td><p>LAMMPS commands to be executed before the input template file is read</p></td>
</tr>
<tr class="row-odd"><td><p>post_commands</p></td>
<td><p>LAMMPS commands to be executed right before the actual tests</p></td>
</tr>
<tr class="row-even"><td><p>input_file</p></td>
<td><p>LAMMPS input file template based on pair style zero</p></td>
</tr>
<tr class="row-odd"><td><p>pair_style</p></td>
<td><p>arguments to the pair_style command to be tested</p></td>
</tr>
<tr class="row-even"><td><p>pair_coeff</p></td>
<td><p>list of pair_coeff arguments to set parameters for the input template</p></td>
</tr>
<tr class="row-odd"><td><p>extract</p></td>
<td><p>list of keywords supported by <code class="docutils literal notranslate"><span class="pre">Pair::extract()</span></code> and their dimension</p></td>
</tr>
<tr class="row-even"><td><p>natoms</p></td>
<td><p>number of atoms in the input file template</p></td>
</tr>
<tr class="row-odd"><td><p>init_vdwl</p></td>
<td><p>non-Coulomb pair energy after “run 0”</p></td>
</tr>
<tr class="row-even"><td><p>init_coul</p></td>
<td><p>Coulomb pair energy after “run 0”</p></td>
</tr>
<tr class="row-odd"><td><p>init_stress</p></td>
<td><p>stress tensor after “run 0”</p></td>
</tr>
<tr class="row-even"><td><p>init_forces</p></td>
<td><p>forces on atoms after “run 0”</p></td>
</tr>
<tr class="row-odd"><td><p>run_vdwl</p></td>
<td><p>non-Coulomb pair energy after “run 4”</p></td>
</tr>
<tr class="row-even"><td><p>run_coul</p></td>
<td><p>Coulomb pair energy after “run 4”</p></td>
</tr>
<tr class="row-odd"><td><p>run_stress</p></td>
<td><p>stress tensor after “run 4”</p></td>
</tr>
<tr class="row-even"><td><p>run_forces</p></td>
<td><p>forces on atoms after “run 4”</p></td>
</tr>
</tbody>
</table>
<p>The test program will read all this data from the YAML file and then
create a LAMMPS instance, apply the settings/commands from the YAML file
as needed and then issue a “run 0” command, write out a restart file, a
data file and a coeff file. The actual test will then compare computed
energies, stresses, and forces with the reference data, issue a “run 4”
command and compare to the second set of reference data. This will be
run with both the newton_pair setting enabled and disabled and is
expected to generate the same results (allowing for some numerical
noise). Then it will restart from the previously generated restart and
compare with the reference and also start from the data file. A final
check will use multi-cutoff r-RESPA (if supported by the pair style) at
a 1:1 split and compare to the Verlet results. These sets of tests are
run with multiple test fixtures for accelerated styles (OPT, OPENMP,
INTEL, KOKKOS (OpenMP only)) and for the latter three with 4 OpenMP
threads enabled. For these tests the relative error (epsilon) is lowered
by a common factor due to the additional numerical noise, but the tests
are still comparing to the same reference data.</p>
<p>Additional tests will check whether all listed extract keywords are
supported and have the correct dimensionality and the final set of tests
will set up a few pairs of atoms explicitly and in such a fashion that
the forces on the atoms computed from <code class="docutils literal notranslate"><span class="pre">Pair::compute()</span></code> will match
individually with the results from <code class="docutils literal notranslate"><span class="pre">Pair::single()</span></code>, if the pair style
does support that functionality.</p>
<p>With this scheme a large fraction of the code of any tested pair style
will be executed and consistent results are required for different
settings and between different accelerated pair style variants and the
base class, as well as for computing individual pairs through the
<code class="docutils literal notranslate"><span class="pre">Pair::single()</span></code> method where supported.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">test_pair_style</span></code> tester is used with 4 categories of test inputs:</p>
<ul class="simple">
<li><p>pair styles compatible with molecular systems using bonded
interactions and exclusions. For pair styles requiring a KSpace style
the KSpace computations are disabled. The YAML files match the
pattern “mol-pair-*.yaml” and the tests are correspondingly labeled
with “MolPairStyle:*”</p></li>
<li><p>pair styles not compatible with the previous input template.
The YAML files match the pattern “atomic-pair-*.yaml” and the tests are
correspondingly labeled with “AtomicPairStyle:*”</p></li>
<li><p>manybody pair styles.
The YAML files match the pattern “atomic-pair-*.yaml” and the tests are
correspondingly labeled with “AtomicPairStyle:*”</p></li>
<li><p>kspace styles.
The YAML files match the pattern “kspace-*.yaml” and the tests are
correspondingly labeled with “KSpaceStyle:*”. In these cases a compatible
pair style is defined, but the computation of the pair style contributions
is disabled.</p></li>
</ul>
<p>The <code class="docutils literal notranslate"><span class="pre">test_bond_style</span></code>, <code class="docutils literal notranslate"><span class="pre">test_angle_style</span></code>, <code class="docutils literal notranslate"><span class="pre">test_dihedral_style</span></code>, and
<code class="docutils literal notranslate"><span class="pre">test_improper_style</span></code> tester programs are set up in a similar fashion and
share support functions with the pair style tester. The final group of
tests in this section is for fix styles that add/manipulate forces and
velocities, e.g. for time integration, thermostats and more.</p>
<p>Adding a new test is easiest done by copying and modifying an existing YAML
file for a style that is similar to one to be tested. The file name should
follow the naming conventions described above and after copying the file,
the first step is to replace the style names where needed. The coefficient
values do not have to be meaningful, just in a reasonable range for the
given system. It does not matter if some forces are large, as long as
they do not diverge.</p>
<p>The template input files define a large number of index variables at the top
that can be modified inside the YAML file to control the behavior. For example,
if a pair style requires a “newton on” setting, the following can be used in
as the “pre_commands” section:</p>
<div class="highlight-yaml notranslate"><div class="highlight"><pre><span></span><span class="nt">pre_commands</span><span class="p">:</span><span class="w"> </span><span class="kt">!</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w"> </span><span class="no">variable newton_pair delete</span>
<span class="w"> </span><span class="no">variable newton_pair index on</span>
</pre></div>
</div>
<p>And for a pair style requiring a kspace solver the following would be used as
the “post_commands” section:</p>
<div class="highlight-yaml notranslate"><div class="highlight"><pre><span></span><span class="nt">post_commands</span><span class="p">:</span><span class="w"> </span><span class="kt">!</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w"> </span><span class="no">pair_modify table 0</span>
<span class="w"> </span><span class="no">kspace_style pppm/tip4p 1.0e-6</span>
<span class="w"> </span><span class="no">kspace_modify gewald 0.3</span>
<span class="w"> </span><span class="no">kspace_modify compute no</span>
</pre></div>
</div>
<p>Note that this disables computing the kspace contribution, but still will run
the setup. The “gewald” parameter should be set explicitly to speed up the run.
For styles with long-range electrostatics, typically two tests are added one using
the (slower) analytic approximation of the erfc() function and the other using
the tabulated coulomb, to test both code paths. The reference results in the YAML
files then should be compared manually, if they agree well enough within the limits
of those two approximations.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">test_pair_style</span></code> and equivalent programs have special command-line options
to update the YAML files. Running a command like</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_pair_style<span class="w"> </span>mol-pair-lennard_mdf.yaml<span class="w"> </span>-g<span class="w"> </span>new.yaml
</pre></div>
</div>
<p>will read the settings from the <code class="docutils literal notranslate"><span class="pre">mol-pair-lennard_mdf.yaml</span></code> file and then compute
the reference data and write a new file with to <code class="docutils literal notranslate"><span class="pre">new.yaml</span></code>. If this step fails,
there are likely some (LAMMPS or YAML) syntax issues in the YAML file that need to
be resolved and then one can compare the two files to see if the output is as expected.</p>
<p>It is also possible to do an update in place with:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_pair_style<span class="w"> </span>mol-pair-lennard_mdf.yaml<span class="w"> </span>-u
</pre></div>
</div>
<p>And one can finally run the full set of tests with:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_pair_style<span class="w"> </span>mol-pair-lennard_mdf.yaml
</pre></div>
</div>
<p>This will just print a summary of the groups of tests. When using the “-v” flag
the test will also keep any LAMMPS output and when using the “-s” flag, there
will be some statistics reported on the relative errors for the individual checks
which can help to figure out what would be a good choice of the epsilon parameter.
It should be as small as possible to catch any unintended side effects from changes
elsewhere, but large enough to accommodate the numerical noise due to the implementation
of the potentials and differences in compilers.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>These kinds of tests can be very sensitive to compiler optimization and
thus the expectation is that they pass with compiler optimization turned
off. When compiler optimization is enabled, there may be some failures, but
one has to carefully check whether those are acceptable due to the enhanced
numerical noise from reordering floating-point math operations or due to
the compiler mis-compiling the code. That is not always obvious.</p>
</div>
</section>
<section id="tests-for-programs-in-the-tools-folder">
<h2><span class="section-number">4.12.9. </span>Tests for programs in the tools folder<a class="headerlink" href="#tests-for-programs-in-the-tools-folder" title="Link to this heading"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">unittest/tools</span></code> folder contains tests for programs in the
<code class="docutils literal notranslate"><span class="pre">tools</span></code> folder. This currently only contains tests for the LAMMPS
shell, which are implemented as a python scripts using the <code class="docutils literal notranslate"><span class="pre">unittest</span></code>
Python module and launching the tool commands through the <code class="docutils literal notranslate"><span class="pre">subprocess</span></code>
Python module.</p>
</section>
<section id="troubleshooting-failed-unit-tests">
<h2><span class="section-number">4.12.10. </span>Troubleshooting failed unit tests<a class="headerlink" href="#troubleshooting-failed-unit-tests" title="Link to this heading"></a></h2>
<p>The are by default no unit tests for newly added features (e.g. pair, fix,
or compute styles) unless your pull request also includes tests for the
added features. If you are modifying some features, you may see failures
for existing tests, if your modifications have some unexpected side effects
or your changes render the existing test invalid. If you are adding an
accelerated version of an existing style, then only tests for INTEL,
KOKKOS (with OpenMP only), OPENMP, and OPT will be run automatically.
Tests for the GPU package are time consuming and thus are only run
<em>after</em> a merge, or when a special label, <code class="docutils literal notranslate"><span class="pre">gpu_unit_tests</span></code> is added
to the pull request. After the test has started, it is often best to
remove the label since every PR activity will re-trigger the test (that
is a limitation of triggering a test with a label). Support for unit
tests when using KOKKOS with GPU acceleration is currently not supported.</p>
<p>When you see a failed build on GitHub, click on <code class="docutils literal notranslate"><span class="pre">Details</span></code> to be taken
to the corresponding LAMMPS Jenkins CI web page. Click on the “Exit”
symbol near the <code class="docutils literal notranslate"><span class="pre">Logout</span></code> button on the top right of that page to go to
the “classic view”. In the classic view, there is a list of the
individual runs that make up this test run (they are shown but cannot be
inspected in the default view). You can click on any of those.
Clicking on <code class="docutils literal notranslate"><span class="pre">Test</span> <span class="pre">Result</span></code> will display the list of failed tests. Click
on the “Status” column to sort the tests based on their Failed or Passed
status. Then click on the failed test to expand its output.</p>
<p>For example, the following output snippet shows the failed unit test</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">[ RUN ] PairStyle.gpu</span>
<span class="go">/home/builder/workspace/dev/pull_requests/ubuntu_gpu/unit_tests/cmake_gpu_opencl_mixed_smallbig_clang_static/unittest/force-styles/test_main.cpp:63: Failure</span>
<span class="go">Expected: (err) &lt;= (epsilon)</span>
<span class="go">Actual: 0.00018957912910606503 vs 0.0001</span>
<span class="go">Google Test trace:</span>
<span class="go">/home/builder/workspace/dev/pull_requests/ubuntu_gpu/unit_tests/cmake_gpu_opencl_mixed_smallbig_clang_static/unittest/force-styles/test_main.cpp:56: EXPECT_FORCES: init_forces (newton off)</span>
<span class="go">/home/builder/workspace/dev/pull_requests/ubuntu_gpu/unit_tests/cmake_gpu_opencl_mixed_smallbig_clang_static/unittest/force-styles/test_main.cpp:64: Failure</span>
<span class="go">Expected: (err) &lt;= (epsilon)</span>
<span class="go">Actual: 0.00022892713393549854 vs 0.0001</span>
</pre></div>
</div>
<p>The failed assertions provide line numbers in the test source
(e.g. <code class="docutils literal notranslate"><span class="pre">test_main.cpp:56</span></code>), from which one can understand what
specific assertion failed.</p>
<p>Note that the force style engine runs one of a small number of systems
in a rather off-equilibrium configuration with a few atoms for a few
steps, writes data and restart files, uses <a class="reference internal" href="clear.html"><span class="doc">the clear command</span></a> to reset LAMMPS, and then runs from those files with different
settings (e.g. newton on/off) and integrators (e.g. verlet vs. respa).
Beyond potential issues/bugs in the source code, the mismatch between
the expected and actual values could be that force arrays are not
properly cleared between multiple run commands or that class members are
not correctly initialized or written to or read from a data or restart
file.</p>
<p>While the epsilon (relative precision) for a single, <a class="reference external" href="https://en.wikipedia.org/wiki/IEEE_754">IEEE 754 compliant</a>, double precision floating
point operation is at about 2.2e-16, the achievable precision for the
tests is lower due to most numbers being sums over intermediate results
and the non-associativity of floating point math leading to larger
errors. As a rule of thumb, the test epsilon can often be in the range
5.0e-14 to 1.0e-13. But for “noisy” force kernels, e.g. those a larger
amount of arithmetic operations involving <cite>exp()</cite>, <cite>log()</cite> or <cite>sin()</cite>
functions, and also due to the effect of compiler optimization or differences
between compilers or platforms, epsilon may need to be further relaxed,
sometimes epsilon can be relaxed to 1.0e-12. If interpolation or lookup
tables are used, epsilon may need to be set to 1.0e-10 or even higher.
For tests of accelerated styles, the per-test epsilon is multiplied
by empirical factors that take into account the differences in the order
of floating point operations or that some or most intermediate operations
may be done using approximations or with single precision floating point
math.</p>
<p>To rerun the failed unit test individually, change to the <code class="docutils literal notranslate"><span class="pre">build</span></code> directory
and run the test with verbose output. For example,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>env<span class="w"> </span><span class="nv">TEST_ARGS</span><span class="o">=</span>-v<span class="w"> </span>ctest<span class="w"> </span>-R<span class="w"> </span>^MolPairStyle:lj_cut_coul_long<span class="w"> </span>-V
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">ctest</span></code> with the <code class="docutils literal notranslate"><span class="pre">-V</span></code> flag also shows the exact command
of the test. One can then use <code class="docutils literal notranslate"><span class="pre">gdb</span> <span class="pre">--args</span></code> to further debug and
catch exceptions with the test command, for example,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>gdb<span class="w"> </span>--args<span class="w"> </span>/path/to/lammps/build/test_pair_style<span class="w"> </span>/path/to/lammps/unittest/force-styles/tests/mol-pair-lj_cut_coul_long.yaml
</pre></div>
</div>
<p>It is recommended to configure the build with <code class="docutils literal notranslate"><span class="pre">-D</span>
<span class="pre">BUILD_SHARED_LIBS=on</span></code> and use a custom linker to shorten the build time
during recompilation. Installing <cite>ccache</cite> in your development
environment helps speed up recompilation by caching previous
compilations and detecting when the same compilation is being done
again. Please see <a class="reference internal" href="Build_development.html"><span class="doc">Development build options</span></a> for further details.</p>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="Developer_plugins.html" class="btn btn-neutral float-left" title="4.11. Writing plugins" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="Classes.html" class="btn btn-neutral float-right" title="4.13. C++ base classes" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2003-2025 Sandia Corporation.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(false);
});
</script>
</body>
</html>