Skip to content

Understanding Reports

This tutorial teaches you how to read and interpret TestLink's report output. Understanding reports helps you assess test coverage and identify gaps.

The Report Command

Run the report command to see all coverage links:

bash
./vendor/bin/testlink report

Report Structure

A typical report looks like this:

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

  App\Services\UserService
    create()
    → Tests\Unit\UserServiceTest::test_creates_a_new_user
    → Tests\Unit\UserServiceTest::test_validates_user_email

    update()
    → Tests\Unit\UserServiceTest::test_updates_existing_user

    delete()
    (no tests linked)

  App\Services\OrderService
    process()
    → Tests\Unit\OrderServiceTest::test_processes_order

  Summary
    Methods with tests: 3
    Methods without tests: 1
    Total test links: 4

Let's break down each section.

Class Grouping

Reports are organized by class:

  App\Services\UserService        ← Fully qualified class name

    create()                      ← Method name
    → Tests\Unit\UserServiceTest::test_creates_a_new_user
                                  ↑ Arrow indicates "tested by"

Method Coverage

Each method shows its linked tests:

    create()
    → Tests\Unit\UserServiceTest::test_creates_a_new_user
    → Tests\Unit\UserServiceTest::test_validates_user_email

This means create() is covered by two tests.

Methods Without Tests

Methods with no linked tests are clearly marked:

    delete()
    (no tests linked)

This helps identify untested code.

Summary Section

The summary gives you a quick overview:

  Summary
    Methods with tests: 3      ← Methods that have at least one test
    Methods without tests: 1   ← Methods with no linked tests
    Total test links: 4        ← Total number of test→method links

JSON Output

For CI/CD integration, use JSON output:

bash
./vendor/bin/testlink report --json
json
{
  "classes": {
    "App\\Services\\UserService": {
      "methods": {
        "create": {
          "tests": [
            "Tests\\Unit\\UserServiceTest::test_creates_a_new_user",
            "Tests\\Unit\\UserServiceTest::test_validates_user_email"
          ]
        },
        "update": {
          "tests": [
            "Tests\\Unit\\UserServiceTest::test_updates_existing_user"
          ]
        },
        "delete": {
          "tests": []
        }
      }
    }
  },
  "summary": {
    "methodsWithTests": 3,
    "methodsWithoutTests": 1,
    "totalLinks": 4
  }
}

Filtering Reports

By Path

Focus on specific directories:

bash
./vendor/bin/testlink report --path=src/Services

Verbose Mode

Get more details with verbose output:

bash
./vendor/bin/testlink report --verbose

This shows:

  • File paths
  • Line numbers
  • Link sources (attribute vs method chain)

Reading Validation Reports

The validate command provides a different view:

bash
./vendor/bin/testlink validate
  Validation Report
  ─────────────────

  Link Summary
    PHPUnit attribute links: 10
    Pest method chain links: 5
    @see tags: 0
    Total links: 15

  ✗ Found 2 orphan TestedBy link(s):
    App\UserService::create
      → Tests\UserServiceTest::test_old_test (test not found)
    App\UserService::update
      → Tests\UserServiceTest::test_removed (test not found)

Validation Issues

IssueMeaningSolution
Orphan TestedBy#[TestedBy] exists but no matching test linkAdd test link (->linksAndCovers() / #[LinksAndCovers] / @see) or remove #[TestedBy]
Missing TestedByTest has link but no #[TestedBy]Add #[TestedBy] to production code or run sync
Duplicate linksSame link appears in both attribute and method chainRemove one of the duplicates

TestLink finds links from multiple sources:

  1. PHPUnit attributes - #[LinksAndCovers] on test methods
  2. Pest method chains - ->linksAndCovers() on tests
  3. TestedBy attributes - #[TestedBy] on production methods

The report combines all sources into a unified view.

Common Patterns

Well-Covered Method

    validateEmail()
    → Tests\Unit\ValidatorTest::test_validates_correct_email
    → Tests\Unit\ValidatorTest::test_rejects_invalid_email
    → Tests\Unit\ValidatorTest::test_handles_empty_string

Multiple tests cover different scenarios.

Single Test Coverage

    getVersion()
    → Tests\Unit\AppTest::test_returns_correct_version

Simple methods may only need one test.

    processPayment()
    → Tests\Integration\PaymentFlowTest::test_complete_payment_flow
    → Tests\Unit\PaymentServiceTest::test_validates_payment_data

Methods can be covered by both unit and integration tests.

Best Practices

  1. Review reports regularly - Run reports as part of your workflow
  2. Address "(no tests linked)" entries - These highlight potential coverage gaps
  3. Use JSON for automation - Parse JSON output in CI pipelines
  4. Filter by path - Focus on specific areas when reviewing

What's Next?

Now that you understand reports:

Released under the MIT License.