VOOZH about

URL: https://deepwiki.com/calevans/staticforge/10.1-testing-strategy

⇱ Testing Strategy | calevans/staticforge | DeepWiki


Loading...
Last indexed: 11 February 2026 (5f6a2a)
Menu

Testing Strategy

This document describes the testing approach, infrastructure, and patterns used in StaticForge development. It covers the test organization, execution, and best practices for writing tests that validate both individual components and full system behavior.

For information about extending core classes, see Extending the Core. For migration patterns when testing version upgrades, see Migration Patterns.


Testing Philosophy

StaticForge employs a dual-layer testing strategy that validates both component isolation and system integration:

  1. Unit Tests: Validate individual features, services, and core components in isolation using mocked dependencies
  2. Integration Tests: Validate complete workflows by executing the full application stack with real filesystem operations

This approach ensures components work correctly both independently and as part of the complete generation pipeline.

Sources: composer.json28-36 tests/Unit/Features/HtmlRenderer/FeatureTest.php1-332 tests/Integration/Commands/RenderSiteCommandTest.php1-387


Test Organization

Test Directory Structure

tests/
├── .env.testing # Unit test environment config
├── .env.integration # Integration test environment config
├── Unit/ # Component-level tests
│ ├── UnitTestCase.php # Base class for unit tests
│ └── Features/
│ ├── HtmlRenderer/
│ │ └── FeatureTest.php
│ └── CacheBusterFeatureTest.php
└── Integration/ # Full-stack workflow tests
 ├── IntegrationTestCase.php
 ├── Commands/
 │ └── RenderSiteCommandTest.php
 ├── Features/
 │ └── RobotsTxtIntegrationTest.php
 └── RssFeedIntegrationTest.php

Unit Tests (tests/Unit/):

  • Test individual classes and methods in isolation
  • Use virtual filesystems (vfsStream) where possible
  • Mock external dependencies
  • Fast execution (<1s per test)
  • Focus on logic validation and edge cases

Integration Tests (tests/Integration/):

  • Test complete workflows from content to output
  • Use real temporary directories
  • Execute full event pipeline
  • Slower execution (2-5s per test)
  • Focus on feature interactions and system behavior

Sources: tests/Unit/Features/HtmlRenderer/FeatureTest.php1-15 tests/Integration/Commands/RenderSiteCommandTest.php1-14 tests/.env.integration1-14


Test Infrastructure

Base Test Classes Hierarchy


UnitTestCase provides:

  • Bootstrapped container via createContainer()
  • Helper methods: setContainerVariable(), addToContainer()
  • Virtual filesystem setup for isolated testing
  • Automatic cleanup in tearDown()

IntegrationTestCase provides:

  • Container creation with custom .env files
  • Temporary directory management
  • removeDirectory() helper for cleanup
  • Real filesystem operations for end-to-end testing

Sources: tests/Unit/Features/HtmlRenderer/FeatureTest.php15-68 tests/Integration/Commands/RenderSiteCommandTest.php14-77


Test Fixture Patterns

Unit Test Fixture Setup


Key Pattern: Unit tests use vfsStream for source/output directories but real temp directories for Twig templates because Twig's filesystem loader cannot read from virtual streams.

Sources: tests/Unit/Features/HtmlRenderer/FeatureTest.php25-68

Integration Test Fixture Setup


Key Pattern: Integration tests create real temporary directories with process-specific names to support parallel test execution, and override $_ENV before loading the bootstrap to ensure the container uses test paths.

Sources: tests/Integration/Commands/RenderSiteCommandTest.php21-67 tests/Integration/RssFeedIntegrationTest.php19-41


Running Tests

PHPUnit Execution


The test suite is configured via phpunit.xml in the project root.

Sources: README.md72-84 composer.json34


Writing Unit Tests

Unit Test Structure


Unit Test Checklist

RequirementPurpose
Extend UnitTestCaseAccess bootstrapped container and helpers
Call parent::setUp()Load dependencies and initialize container
Test single responsibilityEach test validates one behavior
Use descriptive test namestestMethodNameBehaviorExpectedResult()
Mock external dependenciesIsolate component under test
Clean up in tearDown()Remove temp directories, reset state

Common Unit Test Assertions


Sources: tests/Unit/Features/CacheBusterFeatureTest.php1-53 tests/Unit/Features/HtmlRenderer/FeatureTest.php70-114


Writing Integration Tests

Integration Test Structure


Integration Test Checklist

RequirementPurpose
Create unique temp directoriesSupport parallel test execution
Use uniqid() + getmypid()Prevent directory collisions
Override $_ENV before bootstrapEnsure test paths are used
Call createContainer('.env.testing')Load test environment
Execute Application::generate()Run full generation pipeline
Verify file existence and contentValidate complete workflow
Clean up all temp directoriesPrevent disk space leaks

Parallel-Safe Directory Naming


Sources: tests/Integration/RssFeedIntegrationTest.php1-267 tests/Integration/Features/RobotsTxtIntegrationTest.php1-277


Test Environment Configuration

Environment File Hierarchy


Test Environment Variables

.env.testing (Unit Tests):


.env.integration (Integration Tests):


Override Pattern in Tests:


Sources: tests/.env.integration1-14 tests/Integration/Commands/RenderSiteCommandTest.php35-40


Testing Tools Ecosystem


Running Quality Tools


PHPStan Configuration

PHPStan is configured via phpstan.neon to validate:

  • Type correctness
  • Method call validity
  • Null safety
  • Array access safety
  • Unused parameters and variables

PHP_CodeSniffer Standards

Code style follows PSR-12 with custom rules for:

  • Indentation (4 spaces)
  • Line length (120 characters)
  • Namespace declarations
  • Import statements

Sources: composer.json33-36 README.md76-80


Command Testing Patterns

Testing CLI Commands


Testing Command Options


Command Testing Checklist

AspectValidation
Success caseExit code 0, success message
Failure caseExit code 1, error message
Verbose outputAdditional information displayed
Option handlingOverrides applied correctly
Error messagesHelpful and specific
Directory creationOutput directories exist after run

Sources: tests/Integration/Commands/RenderSiteCommandTest.php82-239


Feature Testing Patterns

Testing Feature Registration


Testing Event Handlers


Testing Feature Services


Sources: tests/Unit/Features/CacheBusterFeatureTest.php23-52 tests/Unit/Features/HtmlRenderer/FeatureTest.php116-156


XML Validation Patterns

Testing RSS Feed Validity


Testing XML Content


Sources: tests/Integration/RssFeedIntegrationTest.php236-267


Template Testing Patterns

Creating Test Templates


Testing Template Variable Substitution


Sources: tests/Unit/Features/HtmlRenderer/FeatureTest.php302-328 tests/Integration/Commands/RenderSiteCommandTest.php48-56


Continuous Integration Patterns

Test Suite Organization for CI


Typical CI Pipeline Structure


CI Environment Configuration

For GitHub Actions, GitLab CI, or similar:


Sources: composer.json28-36 README.md72-84


Test Data Management

Content Fixtures



Heredoc vs NOWDOC

  • Use heredoc (<<<HTML) when variable substitution is needed
  • Use nowdoc (<<<'HTML') for static test fixtures to prevent accidental variable expansion

Sources: tests/Integration/RssFeedIntegrationTest.php102-128 tests/Integration/Features/RobotsTxtIntegrationTest.php202-225


Common Testing Pitfalls

PitfallSolution
Tests fail when run in parallelUse uniqid() + getmypid() for temp directories
Twig cannot find templatesUse real temp directories, not vfsStream, for templates
Container has stale valuesCall updateVariable() instead of setVariable()
Environment not loadedOverride $_ENV BEFORE calling createContainer()
Directory not cleanedAlways call removeDirectory() in tearDown()
XML validation failsUse DOMDocument with validateOnParse = true
Test order dependencyEach test should be independent, reset state in setUp()

Sources: tests/Unit/Features/HtmlRenderer/FeatureTest.php34-36 tests/Integration/RssFeedIntegrationTest.php24-26


Test Coverage Goals

Coverage Targets

ComponentTarget CoveragePriority
Core classes90%+Critical
Features80%+High
Commands75%+High
Services85%+High
Utilities70%+Medium

Coverage Commands


Uncovered Code Analysis

Use PHPUnit's coverage reports to identify:

  • Critical paths without tests
  • Dead code (covered by dead-code-detector)
  • Edge cases missing validation
  • Error handling paths

Sources: composer.json34


Summary

StaticForge's testing strategy provides comprehensive validation through:

  1. Dual-layer testing: Unit tests for component isolation, integration tests for workflow validation
  2. Robust infrastructure: Base classes provide bootstrapped containers, fixture helpers, and cleanup
  3. Environment isolation: Test-specific .env files and temporary directories prevent cross-contamination
  4. Quality tooling: PHPStan, PHP_CodeSniffer, and dead code detection ensure code quality
  5. Parallel-safe execution: Unique directory naming supports concurrent test execution

This approach ensures both individual components and the complete system work correctly, enabling confident refactoring and feature development.

Sources: composer.json1-60 tests/Unit/Features/HtmlRenderer/FeatureTest.php1-332 tests/Integration/Commands/RenderSiteCommandTest.php1-387 tests/Integration/RssFeedIntegrationTest.php1-267

Refresh this wiki

On this page