Testing 

Test infrastructure overview 

The extension uses a layered test approach:

Layer Tool Runner
Unit tests PHPUnit ddev composer ci:tests:unit or runTests.sh -s unit
Functional tests PHPUnit + TYPO3 testing framework ddev composer ci:tests (requires database)
Architecture tests PHPAt (via PHPStan extension) ddev composer ci:phpstan (runs automatically with PHPStan)
Static analysis PHPStan ddev composer ci:phpstan
Code style PHP-CS-Fixer ddev composer ci:cgl
Mutation testing Infection ddev composer ci:mutation

Running tests with DDEV 

# Unit tests
ddev composer ci:tests:unit

# Unit + functional tests
ddev composer ci:tests

# Static analysis (includes architecture tests)
ddev composer ci:phpstan

# Mutation testing
ddev composer ci:mutation
Copied!

Running tests with Docker (runTests.sh) 

Build/Scripts/runTests.sh provides a Docker-based test runner that mirrors the CI environment exactly. It does not require DDEV.

# Show all options
./Build/Scripts/runTests.sh -h

# Unit tests
./Build/Scripts/runTests.sh -s unit

# Unit tests with a specific PHP version
./Build/Scripts/runTests.sh -s unit -p 8.3

# PHPStan
./Build/Scripts/runTests.sh -s phpstan

# Code style check
./Build/Scripts/runTests.sh -s cgl

# Fix code style
./Build/Scripts/runTests.sh -s cgl -n

# Mutation testing
./Build/Scripts/runTests.sh -s mutation
Copied!

Supported -s values: unit, unitCoverage, cgl, phpstan, rector, mutation, lint, composer, composerUpdate, clean, update.

Architecture tests 

Architecture tests enforce dependency rules between the extension's layers. They are implemented using PHPAt and registered as a PHPStan extension — they run automatically as part of ci:phpstan, not as a separate PHPUnit testsuite.

The rules are defined in Tests/Architecture/LayerDependencyTest.php. They ensure, for example, that Domain classes do not depend on Controller classes.

Mutation testing 

Infection is used to verify the quality of unit tests by introducing code mutations and checking whether tests catch them.

The minimum thresholds are defined in infection.json.dist:

  • minMsi: 60 % (Mutation Score Indicator)
  • minCoveredMsi: 70 % (Covered Code MSI)

Run locally:

ddev composer ci:mutation
Copied!

Some mutations are intentionally ignored (see infection.json.dist):

  • CastArray on GeneralUtility::makeInstance calls -- untestable in unit tests without TYPO3 boot.
  • Logical conditions on PHP_SAPI -- compile-time constant, always 'cli' in unit test context.