Skip to content

Released: Pyrameter 0.0.1

Choose a tag to compare

@samsonasik samsonasik released this 15 Jun 08:13
0.0.1
e285fdb

Pyrameter 0.0.1 — Initial Release

Pyrameter

Pyrameter is a PHPUnit extension that measures the shape of your test suite.

Latest Version ci build Code Coverage PHPStan Downloads

Windows macOS Linux

It classifies tests by the classes and namespaces each test file consumes, then prints a pyramid shape report after PHPUnit runs.

Use it to spot when your suite is getting heavier, agree on what "healthy" means for your project, and optionally fail CI when the pyramid drifts too far.

Installation

composer require --dev boundwize/pyrameter

Quick start

Register the PHPUnit extension:

<extensions>
    <bootstrap class="Pyrameter\Extension"/>
</extensions>

Then run PHPUnit as usual:

vendor/bin/phpunit

After the test run, Pyrameter prints a summary of your suite shape:

Pyrameter
=========

Shape: Integration Mountain
Result: Violated ⚠

Kind          Tests   Actual   Target      Status
Unit             39    65.0%   >= 70.0%    ✗
Functional       10    16.7%   <= 20.0%    ✓
Integration       9    15.0%   <=  8.0%    ✗
E2E               1     1.7%   <=  2.0%    ✓
Unknown           1     1.7%   <=  2.0%    ✓

Total: 60 tests

Your suite is getting heavier.

How classification works

Pyrameter does not trust test directories.

It does not scan production classes.

Instead, it classifies tests by configured class or namespace usage in test files:

  • no configured heavy usage => unit
  • framework test runtime => functional
  • real resource boundary usage, such as database, cache, queue, filesystem, or external service => integration
  • browser driver usage => e2e

When multiple usages match, the heaviest kind wins.

Mocked heavy dependencies stay unit.

Configuration

If no config path is provided, Pyrameter looks for pyrameter.php in the current working directory.

Start with defaults() to keep the built-in rules for common heavy usage, then tune the target shape for your project:

<?php

declare(strict_types=1);

use Pyrameter\Config\PyrameterConfig;
use Pyrameter\TestKind;

return PyrameterConfig::defaults()
    ->usesClass(App\Analyser\Analyser::class, TestKind::Integration)
    ->usesNamespace('App\Tests\Browser\\', TestKind::E2E)
    ->targetShape(
        unit: ['min' => 75],
        functional: ['max' => 15],
        integration: ['max' => 7],
        e2e: ['max' => 2],
        unknown: ['max' => 1],
    );

Use create() when you want full control with no built-in usage rules:

<?php

declare(strict_types=1);

use Pyrameter\Config\PyrameterConfig;
use Pyrameter\TestKind;

return PyrameterConfig::create()
    ->usesClass(PDO::class, TestKind::Integration)
    ->usesNamespace('Doctrine\DBAL\\', TestKind::Integration)
    ->usesNamespace('Symfony\Bundle\FrameworkBundle\Test\\', TestKind::Functional)
    ->usesNamespace('Symfony\Component\Panther\\', TestKind::E2E)
    ->usesNamespace('Facebook\WebDriver\\', TestKind::E2E)
    ->targetShape(
        unit: ['min' => 70],
        functional: ['max' => 18],
        integration: ['max' => 8],
        e2e: ['max' => 2],
        unknown: ['max' => 2],
    );

CI enforcement

By default, Pyrameter is report-only.

It prints target violations without changing PHPUnit's exit code.

When you are ready to enforce the shape in CI:

return PyrameterConfig::defaults()
    ->failOnViolation();

Requirements

Pyrameter supports PHP 8.2+ and PHPUnit 11 or 12.

Notes

This is an early 0.0.1 release. The API should be considered unstable — breaking changes may occur in minor versions before 1.0.0.

Feedback, issues, and contributions are very welcome at https://github.com/boundwize/pyrameter