ADR-001: DRY and SPOT using Test::WriteVariants

Status

Accepted

Context

Params::Util ships both a Pure-Perl (PP) and an XS implementation. Both must be tested with the same test logic; the only difference is which backend is active, controlled via $ENV{PERL_PARAMS_UTIL_PP}.

Historically the test suite maintained two parallel directory trees (t/pp/ and t/xs/) with near-identical content. The sole difference was a single line in each file's BEGIN block setting the environment variable to 1 or 0.

This violated both DRY (Don't Repeat Yourself) and SPOT (Single Point of Truth): every test change had to be applied twice, and divergence between the two trees was a recurring source of subtle bugs and wasted review effort.

Hash-Merge (a sibling distribution maintained by the same author) already solved this problem using Test::WriteVariants.

Decision

Adopt the Test::WriteVariants pattern established in Hash-Merge:

  • Canonical tests live in t/inline/ as the single source of truth.

  • Sandbox/Tumble.pm defines two variants (pp and xs) that only differ in the PERL_PARAMS_UTIL_PP environment variable.

  • Running perl Makefile.PL in a developer checkout (where Sandbox/ is present) regenerates t/pp/ and t/xs/ from the inline tests.

  • Generated files are excluded from version control (.gitignore) but included in the distribution tarball (MANIFEST), so CPAN consumers do not need Test::WriteVariants installed.

  • xt/perltidy.t excludes the generated directories since their formatting is determined by Test::WriteVariants, not the project's .perltidyrc.

Consequences

  • Test logic is maintained in exactly one place; changes automatically propagate to both backend variants.

  • Adding a new variant (e.g. a future optional backend) requires only a new entry in Sandbox/Tumble.pm, not duplicating every test file.

  • Developer tooling requires Test::WriteVariants ≥ 0.014 (declared as a develop prerequisite).

  • make realclean removes the generated directories so that a fresh perl Makefile.PL regenerates them from current inline sources.