mrpunyapal/peststan

PHPStan extension for Pest PHP testing framework

Maintainers

Package info

github.com/MrPunyapal/PestStan

Type:phpstan-extension

pkg:composer/mrpunyapal/peststan

Fund package maintenance!

mrpunyapal

Statistics

Installs: 304

Dependents: 0

Suggesters: 0

Stars: 4

Open Issues: 0

0.0.2 2026-02-22 20:09 UTC

This package is auto-updated.

Last update: 2026-02-22 20:11:18 UTC


README

PHPStan extension for Pest PHP testing framework. Provides type-safe expectations, proper $this binding in test closures, and accurate return types for all Pest functions.

Latest Version on Packagist Total Downloads CI

Requirements

  • PHP ^8.2
  • PHPStan ^2.0
  • Pest PHP ^3.0 or ^4.0

Installation

composer require --dev mrpunyapal/peststan

If you have phpstan/extension-installer (recommended), the extension is registered automatically.

Otherwise, add it manually to your phpstan.neon or phpstan.neon.dist:

includes:
    - vendor/mrpunyapal/peststan/extension.neon

Features

Generic expect() Function

The extension provides generic type inference for Pest's expect() function, so PHPStan knows the exact type of the expectation value:

expect('hello');           // Expectation<string>
expect(42);                // Expectation<int>
expect(['a' => 1]);        // Expectation<array{a: int}>
expect($user);             // Expectation<User>
expect();                  // Expectation<null>

Type Narrowing Assertions

Type-checking assertion methods narrow the generic type parameter, so PHPStan tracks the type through assertion chains:

/** @var int|string $value */
$value = getValue();

expect($value)->toBeString();
// PHPStan now knows the expectation wraps a string

expect($value)->toBeInstanceOf(User::class);
// PHPStan now knows the expectation wraps a User

Supported type-narrowing assertions: toBeString, toBeInt, toBeFloat, toBeBool, toBeArray, toBeList, toBeObject, toBeCallable, toBeIterable, toBeNumeric, toBeScalar, toBeResource, toBeTrue, toBeFalse, toBeNull, toBeInstanceOf.

Type-Safe and() Chaining

The and() method properly changes the generic type parameter, enabling type-safe assertion chains:

expect('hello')
    ->toBeString()       // Expectation<string>
    ->and(42)            // Expectation<int>
    ->toBeInt()          // Expectation<int>
    ->and(['a', 'b'])    // Expectation<array{string, string}>
    ->toHaveCount(2);    // Expectation<array{string, string}>

$this Binding in Test Closures

The extension ensures $this is properly typed as PHPUnit\Framework\TestCase inside all Pest test closures and lifecycle hooks:

it('can access test case methods', function () {
    $this->markTestSkipped();  // PHPStan knows $this is TestCase
});

beforeEach(function () {
    $this->assertTrue(true);   // Works in hooks too
});

Supported functions: it(), test(), describe(), beforeEach(), afterEach(), beforeAll(), afterAll().

Pest Function Return Types

Accurate return types for all Pest global functions:

Function Return Type
expect($value) Expectation<TValue>
it() / test() / todo() TestCall
describe() DescribeCall

not() and each() Return Types

expect('hello')->not();    // OppositeExpectation<string>
expect([1, 2])->each();    // EachExpectation<array{int, int}>

TestCall Chaining

All TestCall methods are properly typed for fluent chaining:

it('does something', function () { /* ... */ })
    ->with(['a', 'b'])
    ->group('unit', 'feature')
    ->skip(false)
    ->depends('other test')
    ->throws(RuntimeException::class)
    ->repeat(3);

Architecture Testing Support

Architecture testing methods are fully supported:

expect('App\Models')
    ->toExtend('Illuminate\Database\Eloquent\Model')
    ->ignoring('App\Models\Legacy');

expect('App')
    ->classes()
    ->toBeFinal();

expect('App\Actions')->toBeInvokable();
expect('App\DTOs')->toBeReadonly();
expect('App')->toUseStrictTypes();

Testing

composer test        # Run all checks (lint + types + unit)
composer lint        # Apply code style fixes (Rector + Pint)
composer test:lint   # Check code style (dry-run)
composer test:types  # Run PHPStan analysis
composer test:unit   # Run Pest unit tests

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License. See LICENSE for more information.

Credits