Testing & Quality

Run PHPUnit, add fixtures, and write reliable unit/integration tests for VelvetCMS.

Category: Development

Test harness #

  • PHPUnit 12 configuration lives in phpunit.xml and points to tests/bootstrap.php.
  • The bootstrap script loads Composer autoloading, forces APP_ENV=testing, defaults cache/content drivers to file, and ensures fixture directories exist under tests/fixtures.
  • Two suites are declared:
    • tests/Unit for isolated components (CacheTagManager, Router pipeline, Exception handler, etc.).
    • tests/Integration for end-to-end behaviors (content drivers, ModuleManager, Diagnose command, request lifecycle).

Running tests #

./vendor/bin/phpunit              # run everything
./vendor/bin/phpunit --testsuite Unit
./vendor/bin/phpunit tests/Unit/PageTest.php --filter "::testPublish"  

Prefer the vendor binary; if you expose a Composer script (composer test), wire it to the same command.

Writing tests #

  1. Pick the right suite: unit tests should stub dependencies, integration tests can bootstrap the container and hit real drivers.
  2. Use fixtures: drop Markdown files or cached JSON under tests/fixtures and point drivers to them via helper methods in your test class.
  3. Leverage helpers: content_path() and storage_path() work in tests too because the bootstrap defines VELVET_BASE_PATH.
  4. Isolation: clean up temp files (e.g., delete storage/cache/*.php) inside tearDown() to avoid cross-test pollution.
  5. Events & modules: when testing modules, you can instantiate ModuleManager, call discover() against tests/fixtures/modules, and assert on the compiled state without touching real modules.

Mocking the container #

  • For highly isolated tests, instantiate services manually (e.g., new PageService($driver, $events, $cache, $tags) with mocked dependencies).
  • For integration tests, bootstrap the app via require base_path('bootstrap/app.php'), but remember to clean up global state when done.

Continuous integration tips #

  • Enable failOnWarning and failOnRisky (already set in phpunit.xml) to catch incomplete tests early.
  • Cache Composer dependencies but not storage/cache/*; tests rely on a clean slate.
  • Pair PHPUnit with ./velvet diagnose --json to assert runtime health post-build.

With this guide you can confidently extend VelvetCMS while keeping regressions at bay—add tests alongside every new module or bugfix for maximum safety.