Testing ------- Before you open a merge request, your change must be tested — by the unit tests where they apply, by hand across the axes below, and it must pass CI. This chapter covers all three. Unit tests ========== Siril's unit tests live in :file:`src/tests/` and use the `Criterion `_ framework. They are built only when Criterion is available, so you enable them explicitly at configure time: .. code-block:: bash meson setup _build -Dcriterion=true ninja -C _build meson test -C _build -v --no-suite perfs Each test is a small executable registered with ``test()`` in :file:`src/tests/meson.build` (for example ``sorting``, ``stacking_blocks_test``, ``siril_date_test``, ``siril_world_cs_test``, and the ``arithmetic`` suite ``imoper_test`` / ``soper_test``). They link ``siril_dep``, so they exercise the real core code. The ``perfs`` suite is a set of performance benchmarks excluded in CI with ``--no-suite perfs`` — run it locally when you care about timing, skip it otherwise. If you add a testable piece of core logic, add a Criterion test next to the others and register it in :file:`src/tests/meson.build` (put it in a named ``suite`` if it belongs to a family). :file:`src/tests/` also holds diagnostic harnesses written during the GTK4 port audits — small programs that reproduce a specific GUI or processing scenario; use them as templates when a bug needs a dedicated reproducer. Headless testing with siril-cli =============================== Most features are quickest to test through a script run headless: .. code-block:: bash siril-cli -s myscript.ssf # run a Siril script file printf 'requires 1.0.0\n' | siril-cli -s - # read the script from stdin ``siril-cli`` links no GTK, so a script that exercises your command is also a smoke test that your code does not reach into the GUI (see :ref:`gui:the separation rules`). A reproducible test script that loads a known input, runs your command and saves the output is the best regression artifact you can attach to a ticket. The feature test checklist ========================== As noted in :ref:`writingfeature:writing a feature`, a feature must work across several axes. Test **every** applicable combination: - **By command and through the GUI** — both front-ends drive the same worker, but the wiring differs (idle dispatch, undo, preview). - **Mono and colour** — ``fit->naxes[2]`` is 1 or 3; a loop that assumes three channels will crash on mono, and vice-versa. - **16-bit and 32-bit** — ``DATA_USHORT`` vs ``DATA_FLOAT``; honour ``com.pref.force_16bit`` (see :ref:`writingfeature:process a single image`). - **Single image and sequence** — the sequence path adds filtering, parallelism and output plumbing (see :ref:`genericworkers:generic_sequence_worker`). - **Cancellation** — a long operation must stop promptly when cancelled (:ref:`threading:threading`). The continuous integration matrix ================================= CI is defined in :file:`.gitlab-ci.yml` and enumerated in :ref:`cibuilds:continuous integration jobs`. Two jobs are your first line of defence against the invariants this documentation stresses: - **siril-headless-build** (``-Dgtk=false``) — fails to link if any core code calls the GUI directly, and runs the unit tests with coverage. - **siril-lint-gtk-includes** — runs :file:`scripts/lint-gtk-includes.sh` to catch GTK / :file:`src/gui-gtk4` includes that leaked outside :file:`src/gui-gtk4`. Before pushing, reproduce these locally: a headless build (``meson setup _build -Dgtk=false && ninja -C _build``) and the test run above.