This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Snapshot is a PHP library for directory snapshot testing. It provides functionality for creating, comparing, and applying directory snapshots using a baseline + diff architecture. This is particularly useful for testing code generators, scaffolding tools, or any system that produces file output.
- Baseline: A reference directory representing the expected state
- Snapshot/Scenario: A set of diff files representing changes from baseline
- Diff: Unified diff format patches for file content changes
- Index: A scanned representation of a directory's files and content
- Source code:
AlexSkrypnyk\Snapshot\ - Tests:
AlexSkrypnyk\Snapshot\Tests\ - Autoloading: PSR-4 via Composer
src/
βββ Snapshot.php # Main facade class with static methods
βββ Testing/
β βββ SnapshotTrait.php # PHPUnit trait for snapshot testing
βββ Compare/
β βββ Comparer.php # Compares two directory indexes
β βββ ComparerInterface.php
β βββ Diff.php # Represents content differences
β βββ DiffInterface.php
β βββ RenderableInterface.php
βββ Index/
β βββ Index.php # Scans and indexes directory contents
β βββ IndexInterface.php
β βββ IndexedFile.php # Represents a file in an index
β βββ IndexedFileInterface.php
β βββ Rules.php # Skip/include/ignore rules for indexing
β βββ RulesInterface.php
βββ Patch/
β βββ Patcher.php # Applies unified diff patches
β βββ PatcherInterface.php
βββ Sync/
β βββ Syncer.php # Copies files from index to destination
β βββ SyncerInterface.php
βββ Exception/
βββ PatchException.php
βββ RulesException.php
βββ SnapshotException.php
| Class | Purpose |
|---|---|
Snapshot |
Static facade for all operations (compare, diff, patch, sync) |
SnapshotTrait |
PHPUnit trait with assertDirectoriesIdentical() and assertSnapshotMatchesBaseline() |
Index |
Scans directories, respects .ignorecontent rules |
IndexedFile |
File representation with content, hash, path info |
Rules |
Configures skip/include/ignore patterns for comparison |
Comparer |
Finds differences between two indexes |
Diff |
Generates unified diff output |
Patcher |
Applies patch files to recreate expected state |
Syncer |
Copies indexed files to destination |
# Run all linters (PHPCS, PHPStan, Rector)
composer lint
# Auto-fix code style issues
composer lint-fix
# Individual tools
./vendor/bin/phpcs # Check coding standards
./vendor/bin/phpcbf # Fix coding standards
./vendor/bin/phpstan # Static analysis (level 9)
./vendor/bin/rector --dry-run # Check Rector suggestions# Run all PHPUnit tests
composer test
# Run with coverage reports
composer test-coverage
# Coverage reports: .logs/.coverage-html/index.html, .logs/cobertura.xml
# Run unit tests only
./vendor/bin/phpunit tests/phpunit/Unit
# Run functional tests only
./vendor/bin/phpunit tests/phpunit/Functional
# Run specific test file
./vendor/bin/phpunit tests/phpunit/Unit/SnapshotTest.php
# Run specific test method
./vendor/bin/phpunit --filter testMethodName-
PHP_CodeSniffer - Drupal coding standards + strict types
- Config:
phpcs.xml - Rules: Drupal standard, Generic.PHP.RequireStrictTypes
- Relaxed rules in test files
- Config:
-
PHPStan - Level 9 static analysis
- Config:
phpstan.neon
- Config:
-
Rector - PHP 8.2/8.3 modernization
- Config:
rector.php - Sets: PHP_82, PHP_83, CODE_QUALITY, CODING_STYLE, DEAD_CODE, TYPE_DECLARATION
- Config:
- All PHP files must declare
strict_types=1 - Use single quotes for strings (double quotes if containing single quote)
- All files must end with a newline character
- Local variables/method arguments:
snake_case - Method names/class properties:
camelCase
tests/phpunit/
βββ Unit/ # Unit tests - isolated, fast
β βββ ComparerTest.php
β βββ DiffTest.php
β βββ IndexedFileTest.php
β βββ IndexTest.php
β βββ PatcherTest.php
β βββ RulesTest.php
β βββ SnapshotAssertionsTraitTest.php
β βββ SnapshotTest.php
β βββ SyncerTest.php
βββ Functional/ # Integration tests - subprocess testing
β βββ FunctionalTestCase.php
β βββ SnapshotTraitUpdateTest.php
βββ Fixtures/ # Test fixture directories
β βββ compare/ # Comparison test fixtures
β βββ diff/ # Diff/patch test fixtures
βββ UnitTestCase.php # Base test case
- Use PHPUnit 11 attributes:
#[CoversClass()],#[DataProvider()] - Data provider method names start with
dataProvider - Use
UnitTestCaseas base class (includesSnapshotTraitandLocationsTrait) - Functional tests use
FunctionalTestCasewhich addsProcessTrait
For comparison tests (tests/phpunit/Fixtures/compare/):
scenario_name/
βββ directory1/ # Left side (baseline/expected)
β βββ .ignorecontent # Optional ignore rules
β βββ ...files...
βββ directory2/ # Right side (actual)
βββ ...files...
For diff/patch tests (tests/phpunit/Fixtures/diff/):
scenario_name/
βββ baseline/ # Original state
βββ diff/ # Patch files to apply
βββ result/ # Expected result after patching
Controls which files are compared. Supports patterns:
*.log- Skip files matching glob patterndir/- Skip entire directory!important.txt- Include file (override skip)^content.txt- Ignore content differences (compare existence only)
The trait provides two main assertions for PHPUnit tests:
use AlexSkrypnyk\Snapshot\Testing\SnapshotTrait;
class MyTest extends TestCase {
use SnapshotTrait;
// Compare two directories directly
public function testOutput(): void {
$this->assertDirectoriesIdentical($expected, $actual);
}
// Compare actual against baseline + diffs
public function testScenario(): void {
$this->assertSnapshotMatchesBaseline($actual, $baseline, $diffs);
}
// Enable auto-update on failure (call in tearDown)
protected function tearDown(): void {
$this->snapshotUpdateOnFailure($snapshots, $actual);
parent::tearDown();
}
}Set UPDATE_SNAPSHOTS=1 environment variable to automatically update snapshots
when tests fail due to directory comparison mismatches:
UPDATE_SNAPSHOTS=1 ./vendor/bin/phpunitCLI that runs PHPUnit per dataset with UPDATE_SNAPSHOTS=1 (in parallel, with
timeouts and retries) to regenerate many snapshots at once:
vendor/bin/update-snapshots testMySnapshot tests/snapshotsExit-code contract: successfully updating snapshots is the expected outcome
and exits 0. The script exits non-zero only when a dataset genuinely
cannot be updated - a non-snapshot failure or a timeout.
A per-dataset PHPUnit run still exits non-zero when it updates a snapshot (the
assertion fails before tearDown() rewrites it). The script reclassifies such
runs as "updated" by detecting SnapshotTrait's [SNAPSHOT] Baseline updated /
[SNAPSHOT] Diffs updated completion markers in the captured output - so those
marker strings are a contract shared with src/Testing/SnapshotTrait.php; keep
them in sync.
Functional tests run the script as a subprocess against fixtures in
tests/phpunit/Fixtures/functional_update/. Coverage measures src/ only, so
bin/ is not coverage-gated.
PHPBench benchmarks measure performance of core Snapshot operations.
# Run benchmarks with baseline comparison (used by CI)
composer benchmark
# Create or update baseline for performance comparison
composer benchmark-baseline
# Run specific benchmark class
./vendor/bin/phpbench run benchmarks/SnapshotBench.php --ref=baseline
# Quick testing: verify benchmark works without full suite
./vendor/bin/phpbench run benchmarks/SnapshotBench.php --iterations=1 --revs=1The SnapshotBench class measures:
- benchCompareIdentical: Comparing identical directories (baseline)
- benchCompareContentDiffs: Comparing with 20% modified content
- benchCompareStructuralDiffs: Comparing with missing/extra files
- benchDiff: Creating diff files from differences
- benchPatch: Applying patches to baseline
- benchSync: Syncing directories
- benchCompareLargeDirectory: Large directory (500 files) comparison
- Baseline benchmarks stored in
.phpbench/storage/directory - CI compares new benchmarks against baseline with Β±5% threshold
- Performance regressions exceeding Β±5% will fail CI checks
- Update baseline manually:
composer benchmark-baseline
GitHub Actions workflows test across:
- PHP versions: 8.2, 8.3
- Separate jobs: lint, test, coverage upload (Codecov)
Key workflows:
.github/workflows/test-php.yml- PHP testing.github/workflows/benchmark-php.yml- Performance benchmarks