Use @see Tags
@see tags are how TestLink enables Cmd+Click navigation between tests and production code. They're the links your IDE follows when you click.
How @see Tags Enable Navigation
@see tags are PHPDoc annotations that IDEs recognize as clickable references:
class UserService
{
/**
* @see \Tests\UserServiceTest::test_creates_user ← Cmd+Click to jump
*/
public function create(array $data): User
{
// ...
}
}When you Cmd+Click (or Ctrl+Click) on the @see tag, your IDE jumps directly to that test. This works in both directions—from production to tests, and from tests to production.
Adding @see Tags
In production code
/**
* Creates a new user in the system.
*
* @see \Tests\Unit\UserServiceTest::test_creates_user
* @see \Tests\Unit\UserServiceTest::test_validates_email
*/
public function create(array $data): User
{
// implementation
}In test code
/**
* @see \App\Services\UserService::create
*/
public function test_creates_user(): void
{
// test implementation
}In Pest tests
/**
* @see \App\Services\UserService::create
*/
test('creates user with valid data', function () {
// test implementation
});@see Tag Syntax
Class reference
/** @see \App\Services\UserService */Method reference
/** @see \App\Services\UserService::create */Property reference
/** @see \App\Models\User::$email */Multiple references
/**
* @see \App\Services\UserService::create
* @see \App\Services\UserService::validate
* @see \App\Validators\EmailValidator::isValid
*/FQCN Format
Always use fully qualified class names:
// Correct - fully qualified
/** @see \App\Services\UserService::create */
// Incorrect - may not work in all contexts
/** @see UserService::create */Generating @see Tags with Pair (@@prefix)
The pair command can generate @see tags directly using the @@ prefix on placeholders.
PHPUnit Only
The @@ prefix only works with PHPUnit. Pest tests do not support @see tags.
Using @@prefix
Before pairing:
// Production
#[TestedBy('@@user-create')]
public function create(array $data): User { }
// Test (PHPUnit)
#[LinksAndCovers('@@user-create')]
public function testCreatesUser(): void { }Run pair:
./vendor/bin/testlink pairAfter pairing:
// Production - @see tag with FQCN
/** @see \Tests\Unit\UserServiceTest::testCreatesUser */
public function create(array $data): User { }
// Test - @see tag with FQCN
/** @see \App\Services\UserService::create */
public function testCreatesUser(): void { }@@prefix vs @prefix
| Prefix | Result |
|---|---|
@A | PHP attributes (#[TestedBy], #[LinksAndCovers]) |
@@A | PHPDoc @see tags with FQCN |
Choose based on your team's preference:
- Use
@for attribute-based traceability - Use
@@for documentation-style@seetags
Generating @see Tags with Sync
From #[TestedBy] attributes
If you have #[TestedBy] attributes:
#[TestedBy('Tests\UserServiceTest', 'test_creates_user')]
public function create(array $data): UserRun sync to generate @see tags in tests:
./vendor/bin/testlink syncResult in test file:
/**
* @see \App\Services\UserService::create
*/
public function test_creates_user(): voidFrom linksAndCovers()
If you have linksAndCovers() in tests:
test('creates user', function () {
// ...
})->linksAndCovers(UserService::class.'::create');Run sync with --link-only:
./vendor/bin/testlink sync --link-onlyResult in production:
/**
* @see \Tests\UserServiceTest::test_creates_user
*/
public function create(array $data): UserCombining with Attributes
Use both for maximum benefit:
use TestFlowLabs\TestingAttributes\TestedBy;
/**
* Creates a new user.
*
* @see \Tests\Unit\UserServiceTest::test_creates_user
*/
#[TestedBy('Tests\Unit\UserServiceTest', 'test_creates_user')]
public function create(array $data): User
{
// implementation
}@seeenables Cmd+Click navigation#[TestedBy]enables validation and sync
Validating @see Tags
Check for FQCN issues
./vendor/bin/testlink validateOutput:
✗ Found 1 @see tag FQCN issue(s):
tests/UserServiceTest.php:15
@see UserService::create (should use FQCN: \App\Services\UserService)Fix FQCN issues automatically
# Preview fixes
./vendor/bin/testlink validate --fix --dry-run
# Apply fixes
./vendor/bin/testlink validate --fixTestLink resolves short names using use statements in the file:
use Tests\Unit\UserServiceTest;
// Before fix:
/** @see UserServiceTest::creates_user */
// After fix:
/** @see \Tests\Unit\UserServiceTest::creates_user */Pruning Orphan @see Tags
Remove @see tags that point to non-existent code:
./vendor/bin/testlink sync --pruneThis removes:
/**
* @see \App\Services\DeletedService::method ← Removed
* @see \App\Services\UserService::create ← Kept
*/@see Tags vs Attributes
@see tags are essential for navigation—they're what your IDE clicks on. Attributes provide validation.
| Feature | @see Tags | Attributes |
|---|---|---|
| Cmd+Click navigation | ✓ | ✗ |
| Validation in CI | Limited | ✓ Full |
| PHP version | All | PHP 8+ |
| Visible in docs | ✓ | ✗ |
Use both together
For full functionality (navigation + validation), use both:
/**
* @see \Tests\UserServiceTest::test_creates_user ← For navigation
*/
#[TestedBy('Tests\UserServiceTest', 'test_creates_user')] // For validation
public function create(array $data): UserTestLink's sync command can generate @see tags from your attributes automatically.
Best Practices
1. Be consistent
Choose a pattern and stick to it:
- @see only
- Attributes only
- Both
2. Use FQCN always
// Always start with backslash
/** @see \Full\Namespace\Class::method */3. Keep @see tags updated
Run sync regularly:
./vendor/bin/testlink sync --prune4. Validate in CI
- run: ./vendor/bin/testlink validate