Migrate Existing Project
This guide shows how to add TestLink to an existing project with pre-existing tests.
Overview
Migration involves:
- Installing packages
- Identifying critical code to link
- Adding links incrementally
- Setting up validation
Step 1: Install Packages
bash
# Production dependency - attributes
composer require testflowlabs/test-attributes
# Dev dependency - CLI tools
composer require --dev testflowlabs/testlinkStep 2: Verify Installation
bash
./vendor/bin/testlink reportYou should see an empty report (no links exist yet):
Coverage Links Report
─────────────────────
No coverage links found.Step 3: Choose a Migration Strategy
Strategy A: Top-Down (Recommended)
Start with the most critical production code:
- Identify core business logic
- Add
#[TestedBy]to those methods - Run sync to add test links
- Expand gradually
Strategy B: Bottom-Up
Start with tests:
- Add test links (
->linksAndCovers()/#[LinksAndCovers]/@see) to existing tests - Run sync to add production links
- Validate and expand
Strategy C: Feature-by-Feature
Add links when working on features:
- When you touch a file, add its links
- New code always gets links
- Eventually full coverage
Step 4: Start Linking (Top-Down Example)
4.1 Identify critical classes
Choose your most important classes:
src/
├── Services/
│ ├── UserService.php ← Start here
│ ├── OrderService.php ← Then here
│ └── PaymentService.php ← Then here4.2 Add attributes to production
php
<?php
// src/Services/UserService.php
namespace App\Services;
use TestFlowLabs\TestingAttributes\TestedBy;
class UserService
{
#[TestedBy('Tests\Unit\UserServiceTest', 'test_creates_user')]
#[TestedBy('Tests\Unit\UserServiceTest', 'test_validates_email')]
public function create(array $data): User
{
// existing implementation
}
#[TestedBy('Tests\Unit\UserServiceTest', 'test_finds_user_by_id')]
public function find(int $id): ?User
{
// existing implementation
}
}4.3 Run sync to update tests
bash
# Preview changes
./vendor/bin/testlink sync --dry-run
# Apply changes
./vendor/bin/testlink sync4.4 Validate
bash
./vendor/bin/testlink validateStep 5: Handle Common Situations
Tests without matching methods
If your test names don't match method names:
php
// Test name
public function test_it_should_create_a_user()
// Doesn't match production method name
// Use the actual test name in TestedBy
#[TestedBy('Tests\UserServiceTest', 'test_it_should_create_a_user')]Multiple test classes for one production class
php
#[TestedBy('Tests\Unit\UserServiceTest', 'test_creates_user')]
#[TestedBy('Tests\Integration\UserFlowTest', 'test_user_registration_flow')]
public function create(array $data): UserLegacy tests without clear method mapping
Start with links() instead of linksAndCovers() for integration tests:
php
test('legacy integration test', function () {
// Tests multiple things
})
->links(UserService::class.'::create')
->links(UserService::class.'::validate');Step 6: Set Up CI
Add validation to your CI pipeline:
yaml
# .github/workflows/test.yml
- name: TestLink Validation
run: ./vendor/bin/testlink validateStart with warnings allowed, then enable strict mode:
yaml
# Phase 1: Allow warnings
- run: ./vendor/bin/testlink validate
# Phase 2 (later): Strict mode
- run: ./vendor/bin/testlink validate --strictMigration Checklist
Week 1
- [ ] Install packages
- [ ] Link 1-2 critical classes
- [ ] Run validation locally
Week 2-4
- [ ] Link remaining core services
- [ ] Add to CI (non-blocking)
- [ ] Document approach for team
Month 2+
- [ ] Link all new code
- [ ] Gradually link existing code
- [ ] Enable strict CI validation
Tips for Large Codebases
Use path filtering
Focus on specific directories:
bash
./vendor/bin/testlink report --path=src/Services
./vendor/bin/testlink validate --path=src/ServicesTrack progress
bash
# Count linked methods
./vendor/bin/testlink report --json | jq '.summary.methodsWithTests'
# Count unlinked methods
./vendor/bin/testlink report --json | jq '.summary.methodsWithoutTests'Batch linking
For classes with many methods, add links in batches:
bash
# This week: UserService
# Next week: OrderService
# Week after: PaymentServiceCommon Mistakes to Avoid
- Don't try to link everything at once - It's overwhelming
- Don't skip validation - Run it regularly
- Don't forget integration tests - Use
links()for them - Don't ignore existing test names - Use them exactly as written
Measuring Success
Track these metrics:
| Metric | Start | Target |
|---|---|---|
| Methods with links | 0 | 80%+ |
| Validation errors | N/A | 0 |
| CI passes | N/A | 100% |