Skip to content

ParityKnow the test that owns the file.

A release gate for matched coverage: connect each production file to its belonging test, then prove the relationship in CI.

A Parity trace view connecting production files to their belonging tests and matched coverage results

The missing relationship

Coverage is not ownership.

A global percentage can look healthy while the test that belongs to one file barely exercises it. Parity keeps the useful context together: source file, owning test, matched lines, and the rule that decides whether the proof is enough.

01 Declare the owner02 Match the coverage03 Gate the release
parity checkservices / ownership
3 files / 3 owners
InvoiceTotal.phpInvoiceTotalTest.php91%pass
Slugger.phpSluggerTest.php100%pass
CheckoutGateway.phpCheckoutGatewayTest.php18%review

! The suite may pass. The owning test still needs more proof.

A small addition to your existing workflow

Keep the runner. Add the relationship.

Parity reads the report your test tool already produces. When that report cannot identify tests individually, parity test can run them one at a time and build the per-test evidence that parity check evaluates.

  1. 01Describe ownership

    Map source folders to tests, or use static ownership links from Pest and PHPUnit.

  2. 02Feed coverage

    Use Parity JSON, PHPUnit XML, Clover, or Cobertura when the tool already records attribution.

  3. 03Generate when needed

    Run each test through parity test to create one report per test in a stable directory.

  4. 04Gate with context

    Fail with the file, its belonging test, matched percentage, and the threshold that was missed.

quickstart / existing test commandready
$ composer require --dev testparity/parity
$ php vendor/bin/parity init

# Let Parity generate per-test reports when the coverage tool cannot.
$ php vendor/bin/parity test

# Check every source/test relationship in CI.
$ php vendor/bin/parity check --format=json

PASS 18 files mapped  /  16 owners proven  /  2 review items

The contract

Make the belonging test explicit.

A rule is only useful when a reviewer can see what it protects. Keep the threshold next to the source/test map.

min_matched_coverage: 70

structure:
  - name: Services
    paths:
      source: app/Services
      test: tests/Unit/Services
    rules:
      - test-exists
      - matched-coverage:
          min: 70
Read the configuration reference ->

The result a reviewer needs

Not “coverage is low.”
“This test missed this file.”

JSON is made for CI. Table output is made for a human scanning a failed merge. Both carry the same local proof, so a release failure is actionable instead of another number to investigate.

Explore output and rules ->
parity check --format=json1 failure
{
  "source": "app/Services/CheckoutGateway.php",
  "test": "tests/Unit/Services/CheckoutGatewayTest.php",
  "matched_coverage": 18,
  "minimum": 70,
  "error": "matched coverage is below minimum"
}

Proof across real stacks

See the file/test relationship in the language you already ship.

The public samples are small on purpose. Each repository installs Parity in CI, produces coverage, runs the check, and documents the difference between global coverage and the coverage attributable to one test.

Browse the sample repositories ->
StackRunnerEvidenceSample
PHPPHPUnitPHPUnit XMLphpunit-sample
PHPPestcovers() + XMLpest-sample
JS / TSJest + VitestPer-test JSONtypescript-sample
RustCargoPortable coveragerust-sample
Built in public, checked in CI.

Parity checks its own ownership rules, publishes a PHAR, and keeps the docs and implementation specs together.

Read the source ->