Skip to content

CLI Commands

TestLink provides two ways to run commands: the standalone CLI (testlink) and Pest plugin integration (pest --*).

The standalone CLI works with any testing framework (Pest, PHPUnit, or both).

Installation

After installing via Composer, the testlink command is available at:

bash
./vendor/bin/testlink

Commands

Report

Show coverage links from #[TestedBy] attributes:

bash
testlink report

Output:

  Coverage Links Report
  ─────────────────────

  App\Services\UserService

    create()
      → Tests\Unit\UserServiceTest::it creates a user
      → Tests\Unit\UserServiceTest::it validates email

    update()
      → Tests\Unit\UserServiceTest::it updates a user

  Summary
    Methods with tests: 2
    Total test links: 3

Options:

OptionDescription
--jsonOutput as JSON
--path=<dir>Limit scan to directory
--framework=<fw>Filter by framework (pest, phpunit)

Validate

Verify all coverage links are synchronized and detect unresolved placeholders:

bash
testlink validate

Success output:

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

  Link Summary
  ────────────

    PHPUnit attribute links: 5
    Pest method chain links: 10
    Total links: 15

  ✓ All links are valid!

Output with unresolved placeholders:

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

  Unresolved Placeholders
  ───────────────────────

    ⚠ @user-create  (1 production, 2 tests)
    ⚠ @A  (2 production, 0 tests)

    ⚠ Run "testlink pair" to resolve placeholders.

  Link Summary
  ────────────

    PHPUnit attribute links: 5
    Pest method chain links: 10
    Total links: 15

  ✓ All links are valid!

Failure output (duplicate links):

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

  Duplicate Links Found
  ─────────────────────

    ! Tests\Unit\UserServiceTest::test_creates_user
      → App\Services\UserService::create

  ⚠ Consider using only one linking method per test.

Options:

OptionDescription
--strictFail on warnings (including unresolved placeholders)
--jsonOutput as JSON
--path=<dir>Limit scan to directory

Placeholder Detection

The validate command automatically detects unresolved placeholders. In normal mode, this shows a warning but doesn't fail. Use --strict to fail when placeholders are found.

Sync

Synchronize #[TestedBy] attributes to test files:

bash
testlink sync

This reads all #[TestedBy] attributes and adds corresponding links to test files:

  • Pest: Adds ->linksAndCovers() method calls
  • PHPUnit: Adds #[LinksAndCovers] attributes

Options:

OptionDescription
--dry-runPreview changes without applying
--link-onlyUse links() / #[Links] instead of linksAndCovers() / #[LinksAndCovers]
--pruneRemove orphaned link calls
--forceRequired with --prune for safety
--path=<dir>Limit sync to directory
--framework=<fw>Target framework (pest, phpunit, auto)

Examples:

bash
# Preview changes
testlink sync --dry-run

# Apply changes
testlink sync

# Sync with links() only (no coverage)
testlink sync --link-only

# Sync and prune orphans
testlink sync --prune --force

# Sync specific directory
testlink sync --path=src/Services

# Target specific framework
testlink sync --framework=phpunit

Pair

Resolve placeholder markers (@A, @user-create) into real test-production links:

bash
testlink pair

Placeholders are temporary markers used during rapid TDD/BDD development. Instead of writing full class references, you use short markers that get resolved later.

Output:

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

  Scanning for placeholders...

  Found Placeholders
  ──────────────────

    ✓ @user-create  1 production × 2 tests = 2 links
    ✓ @A  2 production × 3 tests = 6 links

  Production Files
  ────────────────

    src/Services/UserService.php
      @user-create → UserServiceTest::it creates a user

  Test Files
  ──────────

    tests/Unit/UserServiceTest.php
      @user-create → UserService::create

  ✓ Pairing complete. Modified 2 file(s) with 8 change(s).

Options:

OptionDescription
--dry-runPreview changes without applying
--placeholder=@XResolve only the specified placeholder

Examples:

bash
# Preview all placeholder resolutions
testlink pair --dry-run

# Apply all placeholder resolutions
testlink pair

# Resolve only a specific placeholder
testlink pair --placeholder=@user-create

Placeholder Syntax

Placeholders must start with @ followed by a letter. Valid examples: @A, @B, @user-create, @MyFeature123.

See the Placeholder Pairing Guide for detailed usage.

Global Options

Available for all commands:

OptionDescription
--help, -hShow help
--version, -vShow version
--verboseShow detailed output
--no-colorDisable colored output

Pest Plugin (Alternative)

If you're using Pest, you can also use these commands through the Pest CLI:

Report

bash
pest --coverage-links

Report as JSON

bash
pest --coverage-links-json

Validate

bash
pest --validate-coverage-links

Sync

bash
pest --sync-coverage-links
pest --sync-coverage-links --dry-run
pest --sync-coverage-links --link-only
pest --sync-coverage-links --prune --force

Help

bash
pest --help-testlink

Choosing Between CLIs

The standalone testlink CLI is recommended because:

  • Works with both Pest and PHPUnit
  • Framework-agnostic output
  • Better for CI/CD pipelines
  • Consistent behavior across projects

Exit Codes

CodeMeaning
0Success
1Validation failed or errors occurred

CI Usage

GitHub Actions

yaml
name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
      - run: composer install
      - name: Validate Coverage Links
        run: ./vendor/bin/testlink validate --strict
      - name: Run Tests
        run: ./vendor/bin/pest  # or ./vendor/bin/phpunit

GitLab CI

yaml
test:
  stage: test
  script:
    - composer install
    - ./vendor/bin/testlink validate --strict
    - ./vendor/bin/pest  # or ./vendor/bin/phpunit

CircleCI

yaml
jobs:
  test:
    docker:
      - image: cimg/php:8.3
    steps:
      - checkout
      - run: composer install
      - run: ./vendor/bin/testlink validate --strict
      - run: ./vendor/bin/pest  # or ./vendor/bin/phpunit

JSON Output

Both CLI tools support JSON output for CI/CD integration:

bash
# Standalone CLI
testlink report --json > coverage-links.json

# Pest plugin
pest --coverage-links-json > coverage-links.json

Example JSON output:

json
{
  "links": {
    "App\\Services\\UserService::create": [
      "Tests\\Unit\\UserServiceTest::it creates a user",
      "Tests\\Unit\\UserServiceTest::it validates email"
    ]
  },
  "summary": {
    "total_methods": 1,
    "total_tests": 2
  }
}

Released under the MIT License.