Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .ai/pest/3/skill/pest-testing/SKILL.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,28 @@

Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag.

## Performance

### Database

- **Prefer `LazilyRefreshDatabase` over `RefreshDatabase`.** Tests that never touch the DB skip the migration/truncation cost entirely. Only use `RefreshDatabase` when the test specifically needs fresh migrations.
- **Use `$factory->recycle($model)`** to create a shared parent once and thread it through nested factory calls, instead of each nested factory creating its own parent.
- **Create only the models the test needs.** Audit factory usage — avoid nested `create()` calls that spawn extra rows the test never inspects.

### Faking

Fake any external interaction that is not the subject of the test:

- `Notification::fake()`, `Mail::fake()`, `Bus::fake()`, `Event::fake()`, `Queue::fake()`.
- If the test hits an HTTP endpoint that dispatches jobs, fake the queue unless the test is asserting job behavior — otherwise jobs execute inline and pull in everything they touch.

For project-level environment and CI optimizations, see [reference/performance.md](reference/performance.md).

## Common Pitfalls

- Not importing `use function Pest\Laravel\mock;` before using mock
- Using `assertStatus(200)` instead of `assertSuccessful()`
- Forgetting datasets for repetitive validation tests
- Deleting tests without approval
- Enabling `RefreshDatabase` on every test even when the test does not hit the DB
- Adding `Queue::fake()` but still asserting side effects of the job (those will never happen)
39 changes: 39 additions & 0 deletions .ai/pest/3/skill/pest-testing/reference/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Test Performance Reference

Environment and tooling optimizations for faster Laravel test suites. These are project-level or CI-level settings — not per-test code changes.

## Environment and config

- **Set `BCRYPT_ROUNDS=4`** in `.env.testing` (or `phpunit.xml`). Default is 12 and hashing dominates auth tests.
- **Disable XDebug.** Disable pcov too at scale unless you specifically need coverage.
- **Disable background packages** in the testing environment: Pulse, Telescope, Nightwatch, and similar 3rd-party packages that do work on every request/command.
- **Use `WithCachedConfig` and `WithCachedRoutes` traits** to avoid re-parsing config and routes on every test.
- **Call `withoutVite()` (or `withoutMix()`)** in your test setup so the framework does not try to resolve built assets.
- **`Http::preventingStrayRequests()`** in your base `Pest.php`. A single slow stray request can punish every test. Note this only catches requests made through Laravel's HTTP client. Audit direct Guzzle / cURL usage separately.
- **`Sleep::fake(syncWithCarbon: true)`** in your base `Pest.php` so retries and backoffs do not actually sleep.
- **`Exceptions::fake()`** to make sure you are not reporting to Flare/Sentry/Bugsnag from within tests.

## Profile and diagnose

- **`./vendor/bin/pest --profile`** prints the slowest tests per shard. Start there. Patterns in the top-10 often apply suite-wide.
- When a slow test is mysterious, instrument event listeners or add temporary logging to find the unexpected work happening behind the scenes.

## Quick reference

| Area | Action |
|------|--------|
| Hashing | `BCRYPT_ROUNDS=4` |
| Debuggers | Disable XDebug, disable pcov |
| Background pkgs | Disable Pulse, Telescope, Nightwatch |
| Config / routes | `WithCachedConfig`, `WithCachedRoutes` |
| Assets | `withoutVite()` / `withoutMix()` |
| HTTP | `Http::preventingStrayRequests()` |
| Sleep | `Sleep::fake(syncWithCarbon: true)` |
| Exceptions | `Exceptions::fake()` |
| Profiling | `pest --profile` |

## Common environment mistakes

- Running the suite with XDebug loaded "just in case" a test fails.
- Leaving `BCRYPT_ROUNDS` at the default because `.env.testing` was never created.
- Calling real `sleep()` or using Carbon in production code, which prevents `Sleep::fake()` from helping.
19 changes: 19 additions & 0 deletions .ai/pest/4/skill/pest-testing/SKILL.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,29 @@
->toHaveSuffix('Controller');
@endboostsnippet

## Performance

### Database

- **Prefer `LazilyRefreshDatabase` over `RefreshDatabase`.** Tests that never touch the DB skip the migration/truncation cost entirely. Only use `RefreshDatabase` when the test specifically needs fresh migrations.
- **Use `$factory->recycle($model)`** to create a shared parent once and thread it through nested factory calls, instead of each nested factory creating its own parent.
- **Create only the models the test needs.** Audit factory usage — avoid nested `create()` calls that spawn extra rows the test never inspects.

### Faking

Fake any external interaction that is not the subject of the test:

- `Notification::fake()`, `Mail::fake()`, `Bus::fake()`, `Event::fake()`, `Queue::fake()`.
- If the test hits an HTTP endpoint that dispatches jobs, fake the queue unless the test is asserting job behavior — otherwise jobs execute inline and pull in everything they touch.

For project-level environment and CI optimizations, see [reference/performance.md](reference/performance.md).

## Common Pitfalls

- Not importing `use function Pest\Laravel\mock;` before using mock
- Using `assertStatus(200)` instead of `assertSuccessful()`
- Forgetting datasets for repetitive validation tests
- Deleting tests without approval
- Forgetting `assertNoJavaScriptErrors()` in browser tests
- Enabling `RefreshDatabase` on every test even when the test does not hit the DB
- Adding `Queue::fake()` but still asserting side effects of the job (those will never happen)
39 changes: 39 additions & 0 deletions .ai/pest/4/skill/pest-testing/reference/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Test Performance Reference

Environment and tooling optimizations for faster Laravel test suites. These are project-level or CI-level settings — not per-test code changes.

## Environment and config

- **Set `BCRYPT_ROUNDS=4`** in `.env.testing` (or `phpunit.xml`). Default is 12 and hashing dominates auth tests.
- **Disable XDebug.** Disable pcov too at scale unless you specifically need coverage.
- **Disable background packages** in the testing environment: Pulse, Telescope, Nightwatch, and similar 3rd-party packages that do work on every request/command.
- **Use `WithCachedConfig` and `WithCachedRoutes` traits** to avoid re-parsing config and routes on every test.
- **Call `withoutVite()` (or `withoutMix()`)** in your test setup so the framework does not try to resolve built assets.
- **`Http::preventingStrayRequests()`** in your base `Pest.php`. A single slow stray request can punish every test. Note this only catches requests made through Laravel's HTTP client. Audit direct Guzzle / cURL usage separately.
- **`Sleep::fake(syncWithCarbon: true)`** in your base `Pest.php` so retries and backoffs do not actually sleep.
- **`Exceptions::fake()`** to make sure you are not reporting to Flare/Sentry/Bugsnag from within tests.

## Profile and diagnose

- **`./vendor/bin/pest --profile`** prints the slowest tests per shard. Start there. Patterns in the top-10 often apply suite-wide.
- When a slow test is mysterious, instrument event listeners or add temporary logging to find the unexpected work happening behind the scenes.

## Quick reference

| Area | Action |
|------|--------|
| Hashing | `BCRYPT_ROUNDS=4` |
| Debuggers | Disable XDebug, disable pcov |
| Background pkgs | Disable Pulse, Telescope, Nightwatch |
| Config / routes | `WithCachedConfig`, `WithCachedRoutes` |
| Assets | `withoutVite()` / `withoutMix()` |
| HTTP | `Http::preventingStrayRequests()` |
| Sleep | `Sleep::fake(syncWithCarbon: true)` |
| Exceptions | `Exceptions::fake()` |
| Profiling | `pest --profile` |

## Common environment mistakes

- Running the suite with XDebug loaded "just in case" a test fails.
- Leaving `BCRYPT_ROUNDS` at the default because `.env.testing` was never created.
- Calling real `sleep()` or using Carbon in production code, which prevents `Sleep::fake()` from helping.
Loading