Pest Control
SkillFiles & storageKeeps your agent writing PHPUnit tests instead of Pest and removes any Pest code from the project.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Pest Control skill
About this capability
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.
What this skill tells your AI
The instructions your AI receives, as published by bottelet/daybydaycrm in .claude/skills/pest-control/SKILL.md and read by ahel’s review.
Rule 0 — Hard Stop
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()configuration
Rule 1 — Correct Test Class Pattern
Every 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/
Rule 2 — Attribute Syntax
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.
Rule 3 — Assertion Style
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);
Rule 4 — Livewire Testing
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();
Rule 5 — File Placement
Modules/<Name>/Tests/Unit/ ← AbstractTestCase, no DB
Modules/<Name>/Tests/Feature/ ← AbstractCompanyPanelTestCase or AbstractAdminPanelTestCase
PHPUnit discovers tests via phpunit.xml:
<testsuite name="Unit"> <directory>Modules/*/Tests/Unit</directory> </testsuite>
<testsuite name="Feature"><directory>Modules/*/Tests/Feature</directory></testsuite>
Rule 6 — Pest Elimination Checklist
When asked to eliminate Pest from a codebase, check and fix all of the following:
composer.json
- Remove
"pestphp/pest-plugin": truefromconfig.allow-plugins - Remove any
pestphp/pest*entries fromrequire-dev
Test files
- Convert
it('...', fn () => ...)→ class method with#[Test]attribute - Convert
test('...', fn () => ...)→ class method with#[Test]attribute - Remove all
uses(...)declarations - Replace
expect(...)->toBe(...)chains with$this->assertSame(...) - Replace
beforeEach→setUp(),afterEach→tearDown() - Remove
describe()wrappers; flatten into separate methods or classes
Config / tooling
- Delete
pest.phportests/Pest.phpif present - Remove any
--pestflag from CI workflow commands - Update
.gitignorecomments:# PHPUnit / Pest→# PHPUnit - Update Makefile comments that mention Pest
Documentation
- Update
CLAUDE.mdtesting section to state PHPUnit-only - Update any README or CONTRIBUTING docs that mention Pest
Rule 7 — Conversion Reference
| 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')] |
Signals
- GitHub stars
- 2k
- Forks
- 767
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
pest-control- Source
- github.com/bottelet/daybydaycrm