This document provides essential context for AI assistants working on the TestLink project.
TestLink is a framework-agnostic test traceability tool for PHP that creates bidirectional links between production code and tests. It supports both Pest and PHPUnit testing frameworks.
TestLink uses a two-package architecture that is critical to understand:
Contains all PHP attributes used in code:
#[TestedBy]- Used on production code to declare which tests verify a method#[LinksAndCovers]- Used on test code to link tests to production methods (with coverage)#[Links]- Used on test code for traceability without coverage
Why production dependency? These attributes are placed on production classes. PHP needs the attribute classes available when autoloading production code in any environment (including production).
Contains CLI tools and infrastructure:
testlink report- Show coverage links reporttestlink validate- Validate bidirectional synctestlink sync- Auto-sync links between production and test codetestlink pair- Resolve placeholder markers into real links- Scanners, parsers, validators, and sync functionality
Why dev dependency? These tools only run during development and CI/CD, never in production.
Users must install both packages correctly:
# Production dependency - attributes for production code
composer require testflowlabs/test-attributes
# Dev dependency - CLI tools
composer require --dev testflowlabs/testlinkIf testlink is installed as dev-only without test-attributes as production, applications will fail to load production classes that use #[TestedBy] in production environments.
src/
├── Adapter/ # Framework adapters (Pest, PHPUnit)
├── Console/ # CLI application and commands
│ └── Command/ # CLI command implementations (Report, Validate, Sync, Pair)
├── Contract/ # Interfaces
├── Discovery/ # Framework detection (FrameworkDetector)
├── Modifier/ # Test file modifiers
├── Parser/ # Test file parsers
├── Placeholder/ # Placeholder pairing system
│ ├── PlaceholderScanner.php # Scans for @placeholder markers
│ ├── PlaceholderRegistry.php # Stores placeholder entries
│ ├── PlaceholderResolver.php # Resolves placeholders to real links
│ └── PlaceholderModifier.php # Applies resolved changes to files
├── Registry/ # Link storage
├── Reporter/ # Console and JSON reporters
├── Runtime/ # Pest runtime bootstrap
├── Scanner/ # Attribute scanners
├── Sync/ # Bidirectional sync system
└── Validator/ # Link validators
tests/
├── Fixtures/ # Test fixtures (ProductionCode, TestCode)
└── Unit/ # Unit tests
docs/ # VitePress documentation site
bin/testlink # CLI entry point
TestFlowLabs\TestingAttributes\*- Attributes (from test-attributes package)TestFlowLabs\TestLink\*- CLI tools and infrastructure (this package)
The core concept is bidirectional linking:
- Production → Test:
#[TestedBy(TestClass::class, 'test_method')]on production methods - Test → Production:
linksAndCovers(Class::method)(Pest) or#[LinksAndCovers(Class, 'method')](PHPUnit)
Both directions should be synchronized. The testlink validate command checks for mismatches.
Placeholders allow temporary markers during rapid TDD/BDD development:
- Syntax:
@A,@B,@user-create,@MyFeature(must start with@followed by a letter) - Usage: Use
#[TestedBy('@placeholder')]in production and->linksAndCovers('@placeholder')in tests - Resolution: Run
testlink pairto resolve placeholders into real class references - N:M Matching: Same placeholder creates links between ALL matching production methods and ALL matching tests
| Command | Description |
|---|---|
testlink report |
Show coverage links from #[TestedBy] attributes |
testlink validate |
Verify all coverage links are synchronized |
testlink sync |
Synchronize #[TestedBy] attributes to test files |
testlink pair |
Resolve placeholder markers into real links |
Common options: --dry-run, --json, --path=<dir>, --verbose
composer test # Run all checks (rector, pint, phpstan, unit tests, type coverage)
composer test:unit # Run unit tests only with coverage (min 60%)
composer test:phpstan # Run static analysis
composer test:types # Run type coverage check
composer test:pint # Run code style check
composer test:rector # Run rector dry-run
composer test:mutation # Run mutation testing (min 50%)- Use Conventional Commits format (e.g.,
fix:,feat:,refactor:,docs:,test:,chore:) - Commit atomically: Create a commit immediately after each fix/change, don't wait for entire task completion
- No emojis in commit messages
- No Claude traces in commits (no "generated with claude", "co-authored by claude", etc.)
- https://github.com/TestFlowLabs/test-attributes - PHP attributes package
- https://github.com/TestFlowLabs/testlink - This package (CLI tools)