Skip to content

Pest Methods ​

TestLink provides method chains for Pest tests to declare coverage links.

Available Methods ​

MethodDescription
linksAndCovers()Links to production code (with coverage)
links()Links to production code (without coverage)

linksAndCovers() ​

Declares that a test covers and links to production methods.

Signature ​

php
->linksAndCovers(string $methodIdentifier): self

Parameters ​

ParameterTypeDescription
$methodIdentifierstringClass::method format or placeholder

Usage ​

php
test('creates user', function () {
    $service = new UserService();
    $user = $service->create(['name' => 'John']);

    expect($user)->toBeInstanceOf(User::class);
})->linksAndCovers(UserService::class.'::create');

Multiple methods ​

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

With describe blocks ​

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

        test('validates email format', function () {
            // ...
        })->linksAndCovers(UserService::class.'::create');
    });
});

With placeholder ​

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

Declares that a test links to production methods without affecting coverage.

Signature ​

php
->links(string $methodIdentifier): self

Parameters ​

ParameterTypeDescription
$methodIdentifierstringClass::method format or placeholder

Usage ​

php
test('complete registration flow', function () {
    // Integration test
})
->links(UserService::class.'::create')
->links(EmailService::class.'::sendWelcome');

When to use ​

Use links() for:

  • Integration tests
  • E2E tests
  • Tests where unit tests provide coverage
php
// Unit test - provides coverage
test('creates user', function () {
    // ...
})->linksAndCovers(UserService::class.'::create');

// Integration test - just links
test('user registration flow', function () {
    // ...
})->links(UserService::class.'::create');

Method Identifier Format ​

Using ::class constant ​

php
// Recommended format
->linksAndCovers(UserService::class.'::create')

This becomes "App\Services\UserService::create".

String format ​

php
// Also valid
->linksAndCovers('App\Services\UserService::create')

Placeholder format ​

php
// Resolved with `testlink pair`
->linksAndCovers('@user-create')

Chaining ​

Methods can be chained in any order:

php
test('creates and validates user', function () {
    // ...
})
->linksAndCovers(UserService::class.'::create')
->linksAndCovers(UserValidator::class.'::validate')
->links(AuditService::class.'::log');

Comparison with PHPUnit Attributes ​

PestPHPUnit
->linksAndCovers(Class::class.'::method')#[LinksAndCovers(Class::class, 'method')]
->links(Class::class.'::method')#[Links(Class::class, 'method')]

Converting between formats ​

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

// PHPUnit equivalent
#[LinksAndCovers(UserService::class, 'create')]
public function test_creates_user(): void
{
    // ...
}

Common Patterns ​

One test, one method ​

php
test('adds two numbers', function () {
    expect((new Calculator())->add(2, 3))->toBe(5);
})->linksAndCovers(Calculator::class.'::add');

One test, multiple methods ​

php
test('processes order', function () {
    // Tests complete order processing
})
->linksAndCovers(OrderService::class.'::validate')
->linksAndCovers(OrderService::class.'::save')
->linksAndCovers(OrderService::class.'::notify');

Multiple tests, one method ​

php
test('adds positive numbers', function () {
    expect((new Calculator())->add(2, 3))->toBe(5);
})->linksAndCovers(Calculator::class.'::add');

test('adds negative numbers', function () {
    expect((new Calculator())->add(-2, -3))->toBe(-5);
})->linksAndCovers(Calculator::class.'::add');

test('adds zeros', function () {
    expect((new Calculator())->add(0, 0))->toBe(0);
})->linksAndCovers(Calculator::class.'::add');
php
test('refund after payment', function () {
    // Focus is on refund, payment is just setup
})
->linksAndCovers(PaymentService::class.'::refund')  // Coverage for refund
->links(PaymentService::class.'::charge');          // No coverage for charge

Validation ​

TestLink validates Pest method chains:

bash
./vendor/bin/testlink validate

Errors ​

✗ Invalid linksAndCovers:
  tests/UserServiceTest.php:15
    → App\UserService::nonexistent (method not found)

Released under the MIT License.