Skip to content

TestLinkNavigate Tests ↔ Production

Cmd+Click to jump between your tests and production code. Instantly.

TestLink Logo

πŸ”— Click to Navigate ​

No more searching for tests. Cmd+Click any @see tag to jump directly to the related code.

From production code, click to see which tests verify it. From tests, click to see which production code they cover. Both directions, instantly navigable.

How it works β†’

php
class UserService
{
    /**
     * @see \Tests\UserServiceTest::creates_user      ← Cmd+Click
     * @see \Tests\UserServiceTest::validates_email   ← Cmd+Click
     */
    public function create(array $data): User
    {
        // Which tests verify this method? Just click above.
    }
}
php
/**
 * @see \App\Services\UserService::create   ← Cmd+Click
 */
test('creates user', function () {
    // What does this test cover? Just click above.
});

πŸ“Š See All Relationships ​

One method tested by 5 different tests? See them all at a glance.

One test covers multiple methods? Visible instantly. No more guessing which code is tested, or which tests cover what.

Understanding reports β†’

php
/**
 * @see \Tests\OrderServiceTest::creates_order
 * @see \Tests\OrderServiceTest::validates_items
 * @see \Tests\OrderServiceTest::calculates_total
 * @see \Tests\OrderFlowTest::complete_checkout
 * @see \Tests\OrderFlowTest::payment_flow
 */
public function create(array $items): Order
{
    // 5 tests verify this method - all visible here
}
bash
$ ./vendor/bin/testlink report

  OrderService
    create()
    β†’ OrderServiceTest::creates_order
    β†’ OrderServiceTest::validates_items
    β†’ OrderServiceTest::calculates_total
    β†’ OrderFlowTest::complete_checkout
    β†’ OrderFlowTest::payment_flow

  Summary
  ───────
    Methods with tests:       1
    Total test links:         5
    @see tags:                0

  βœ“ Report complete.

πŸ§ͺ Pest & PHPUnit ​

Works with your existing framework. Pest method chains, PHPUnit attributes, or @see tags.

Mix all three in the same project. TestLink recognizes them all.

See all methods β†’

php
test('creates user', function () {
    // ...
})->linksAndCovers(UserService::class.'::create');

Renamed a method? Deleted a test? Validation catches broken links instantly.

Run in CI/CD to ensure your navigation links stay accurate as code evolves.

Set up CI validation β†’

bash
$ ./vendor/bin/testlink validate

  Validation Report
  ─────────────────

  Orphan @see Tags
    βœ— UserServiceTest::old_name
      β†’ src/UserService.php:15

  Summary
  ───────
    PHPUnit attribute links:  10
    Pest method chain links:  5
    @see tags:                8
    Total links:              23

    Issues found:             1
      Orphan @see tags:       1

  βœ“ Validation complete with issues.

πŸ”„ Auto-Sync ​

Don't manually maintain links. Sync generates them bidirectionally.

Add a link on either sideβ€”production or testsβ€”and testlink sync propagates it to the other side. Start from whichever side feels natural for your workflow.

Sync workflow β†’

bash
$ ./vendor/bin/testlink sync

  Syncing Coverage Links
  ──────────────────────

  Modified Files
    βœ“ src/Services/UserService.php (1 change)
      + #[TestedBy(UserServiceTest::class, 'creates_user')]

    βœ“ tests/Unit/OrderServiceTest.php (1 change)
      + linksAndCovers(OrderService::class.'::process')

  Summary
  ───────
    Files modified:           2
    Files pruned:             0
    @see tags added:          0
    @see tags removed:        0
    #[TestedBy] added:        1

  βœ“ Sync complete.

⚑ TDD Placeholders ​

Writing tests before classes exist? Use @placeholder markers.

During rapid TDD, you don't know the final class name yet. Use placeholders like @user-create in both test and production code, then resolve them with testlink pair.

Placeholder strategy β†’

php
// Test written BEFORE the class exists
test('calculates discount', function () {
    $calc = new PriceCalculator();
    expect($calc->calculate(100, 0.1))->toBe(90);
})->linksAndCovers('@discount');

// Production code (written after test passes)
#[TestedBy('@discount')]
public function calculate(int $price, float $discount): int
{
    return (int) ($price * (1 - $discount));
}
bash
$ ./vendor/bin/testlink pair

  Pairing Placeholders
  ────────────────────

  Found Placeholders
    βœ“ @discount  1 production Γ— 1 tests = 1 links

  Summary
  ───────
    Placeholders resolved:    1
    Total changes:            2
    Files modified:           2

  βœ“ Pairing complete.

πŸ”§ Auto-Fix @see Tags ​

Short class names in @see tags? Fix them automatically.

TestLink detects non-FQCN references and resolves them using your use statements. One command converts UserService::create to \App\Services\UserService::create.

Using @see tags β†’

php
// Before: Short class name (IDE can't navigate)
/**
 * @see UserServiceTest::creates_user
 */
public function create(): User { }

// After: FQCN (Cmd+Click works!)
/**
 * @see \Tests\Unit\UserServiceTest::creates_user
 */
public function create(): User { }
bash
$ ./vendor/bin/testlink validate --fix

  Validation Report
  ─────────────────

  FQCN Conversion Results
    βœ“ src/TestLink/UserService.php
      + Tests\TestLink\UserServiceTest::creates
        β†’ \Tests\TestLink\UserServiceTest::creates

  βœ“ Converted 1 @see tag(s) in 1 file(s).

  Summary
  ───────
    PHPUnit attribute links:  5
    Pest method chain links:  3
    @see tags:                4
    Total links:              12

    Issues fixed:             1

  βœ“ Validation complete. All links are valid!

Released under the MIT License.