Testing ======= Test categories --------------- Tests are organised into three directories by purpose: .. list-table:: :header-rows: 1 :widths: 20 25 55 * - Category - Directory - When to use * - Unit - ``tests/unit/`` - Fast checks of a single module (allocator, reordering, statistics) * - Verification - ``tests/verification/`` - Comparing numerical results against analytical solutions * - Performance - ``tests/performance/`` - Benchmarking throughput — large problems, many iterations, no correctness checks Each test is registered with a CTest label matching its category (``unit``, ``verification``, or ``performance``) and its backend (``omp`` or ``cuda``). Writing a test -------------- Create a Fortran source file in the appropriate directory. Use ``#ifdef CUDA`` guards so the same file compiles for both backends. **Unit test example** (``tests/unit/test_example.f90``): .. code-block:: fortran program test_example use MPI use m_common, only: dp implicit none integer :: ierr logical :: allpass call MPI_Init(ierr) allpass = .true. ! --- your checks here --- if (1 + 1 /= 2) then print *, 'FAIL: arithmetic' allpass = .false. end if call MPI_Finalize(ierr) if (.not. allpass) error stop 1 end program test_example **Verification test** — use ``check_norm`` from ``m_test_utils``: .. code-block:: fortran use m_test_utils, only: check_norm ... call check_norm(error_norm, 1e-8_dp, 'my_operator_periodic', allpass) ``check_norm`` prints a standardised ``PASSED``/``FAILED`` line with the norm value and tolerance. **Performance test** — use ``report_perf`` from ``m_test_utils``: .. code-block:: fortran use m_test_utils, only: report_perf ... call report_perf('my_kernel', elapsed_time, n_iters, ndof, bytes_per_dof) This emits machine-parseable output: ``PERF_METRIC: