Enforces PHPUnit-only testing in this project. Activates when writing tests, reviewing test files, or when any Pest syntax appears (it(), test(), describe(), uses(), expect() chains, beforeEach/afterEach hooks). Scans for and eliminates all Pest references from code, config, and documentation.
72
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Pest is NOT installed in this project and must never be used.
This project uses PHPUnit 12+ exclusively.
Never write, suggest, or accept:
it('description', fn () => ...)test('description', fn () => ...)describe('group', fn () => ...)uses(SomeClass::class)expect($value)->toBe(...)beforeEach(fn () => ...)afterEach(fn () => ...)pest() configurationEvery test MUST be a class extending one of the three base classes:
// Company panel tests
class FooTest extends AbstractCompanyPanelTestCase
{
#[Test]
public function it_does_something(): void
{
// ...
}
}
// Admin panel tests
class BarTest extends AbstractAdminPanelTestCase
{
#[Test]
public function it_does_something(): void
{
// ...
}
}
// Pure unit tests (no DB, no framework boot)
class BazTest extends AbstractTestCase
{
#[Test]
public function it_does_something(): void
{
// ...
}
}Base class locations: Modules/Core/Tests/
Use PHP 8.1+ attributes for test metadata:
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\CoversClass;
#[Test]
public function it_creates_an_invoice(): void {}
#[Test]
#[DataProvider('invoiceDataProvider')]
public function it_validates_invoice_fields(array $data, string $error): void {}Never use /** @test */ docblock annotations — use #[Test] attributes.
Use PHPUnit assertions, not Pest chains:
// Correct
$this->assertSame('expected', $actual);
$this->assertDatabaseHas('invoices', ['status' => 'paid']);
$this->assertCount(3, $results);
// Wrong — Pest chain
expect($actual)->toBe('expected');
expect($results)->toHaveCount(3);Filament/Livewire tests use the Livewire facade directly:
use Livewire\Livewire;
Livewire::actingAs($this->user)
->test(ListInvoices::class, ['tenant' => 'ivplv2'])
->assertSuccessful();Or the base class helper:
$this->testLivewire(ListInvoices::class)->assertSuccessful();Modules/<Name>/Tests/Unit/ ← AbstractTestCase, no DB
Modules/<Name>/Tests/Feature/ ← AbstractCompanyPanelTestCase or AbstractAdminPanelTestCasePHPUnit discovers tests via phpunit.xml:
<testsuite name="Unit"> <directory>Modules/*/Tests/Unit</directory> </testsuite>
<testsuite name="Feature"><directory>Modules/*/Tests/Feature</directory></testsuite>When asked to eliminate Pest from a codebase, check and fix all of the following:
"pestphp/pest-plugin": true from config.allow-pluginspestphp/pest* entries from require-devit('...', fn () => ...) → class method with #[Test] attributetest('...', fn () => ...) → class method with #[Test] attributeuses(...) declarationsexpect(...)->toBe(...) chains with $this->assertSame(...)beforeEach → setUp(), afterEach → tearDown()describe() wrappers; flatten into separate methods or classespest.php or tests/Pest.php if present--pest flag from CI workflow commands.gitignore comments: # PHPUnit / Pest → # PHPUnitCLAUDE.md testing section to state PHPUnit-only| Pest | PHPUnit equivalent |
|---|---|
it('desc', fn() => ...) | #[Test] public function it_desc(): void |
test('desc', fn() => ...) | #[Test] public function test_desc(): void |
expect($x)->toBe($y) | $this->assertSame($y, $x) |
expect($x)->toEqual($y) | $this->assertEquals($y, $x) |
expect($x)->toBeTrue() | $this->assertTrue($x) |
expect($x)->toBeFalse() | $this->assertFalse($x) |
expect($x)->toBeNull() | $this->assertNull($x) |
expect($x)->toBeEmpty() | $this->assertEmpty($x) |
expect($x)->toHaveCount(n) | $this->assertCount(n, $x) |
expect($x)->toContain($y) | $this->assertContains($y, $x) |
expect($x)->toMatchArray([...]) | $this->assertEquals([...], $x) |
expect($x)->toBeInstanceOf(Cls::class) | $this->assertInstanceOf(Cls::class, $x) |
beforeEach(fn() => ...) | protected function setUp(): void |
afterEach(fn() => ...) | protected function tearDown(): void |
uses(RefreshDatabase::class) | use RefreshDatabase; inside the class |
dataset(...) | public static function provider(): array + #[DataProvider('provider')] |
fb83b36
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.