Reference
Protect important request profiles with Pest
Capture the real Laravel response, read its exact profile ID, and assert only the error or performance limits that represent stable product behavior.
-
Capture the response
Enable profiling before the test app boots and make the real request. -
Use its exact ID
Read X-NewDebugBar-Profile rather than choosing the latest stored profile. -
Assert the contract
Check response behavior and the stable query or error budget that matters.
Enable profiling before the test app boots
The New Debug Bar defaults to the local environment and follows APP_DEBUG. To capture profiles during tests, enable debug mode or set NEWDEBUGBAR_ENABLED=true in the test environment. Publish the package configuration and include testing in the allowed environments:
'environments' => ['local', 'testing'],
Read the exact profile ID from the response
Every profiled response includes X-NewDebugBar-Profile. Assert that the header exists, then pass its UUID to ProfileAssertions::stored().
Do not use “the latest profile” in a test. Related requests and background work can produce another profile after the response you meant to inspect.
Use focused profile assertions
| Assertion | Protects |
|---|---|
assertNoErrors() | No error response or exception finding |
assertNoRepeatedQueries() | No repeated normalized query pattern |
assertNoLikelyNPlusOneQueries() | No likely N+1 finding |
assertQueryCountAtMost($count) | Maximum query count |
assertQueryTimeAtMost($milliseconds) | Maximum total query time |
assertDurationAtMost($milliseconds) | Maximum full request duration |
assertPeakMemoryAtMost($megabytes) | Maximum peak memory |
Write a Pest profile test
<?php
use NewDebugBar\Testing\ProfileAssertions;
use function Pest\Laravel\get;
it('keeps the dashboard profile within its budget', function () {
$response = get('/dashboard')
->assertOk()
->assertHeader('X-NewDebugBar-Profile');
ProfileAssertions::stored(
(string) $response->headers->get('X-NewDebugBar-Profile'),
)
->assertNoErrors()
->assertQueryCountAtMost(12)
->assertNoLikelyNPlusOneQueries()
->assertDurationAtMost(300);
});
Choose budgets that describe stable behavior
- Prefer query counts and error findings when they are stable across machines.
- Give timing and memory budgets room for normal CI variation.
- Use realistic database records so a likely N+1 pattern can actually appear.
- Assert the response behavior separately; a healthy profile does not replace feature assertions.
Run a small profile assertion without extra models
After enabling profiling for the testing environment as described above, this Pest test defines its own simple JSON route. It needs a working database connection, but no additional table or model:
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use NewDebugBar\Testing\ProfileAssertions;
use function Pest\Laravel\get;
it('captures the example response within its query budget', function () {
Route::get('/profile-example', function () {
$result = DB::selectOne('select 1 as value');
return response()->json(['value' => (int) $result->value]);
});
$response = get('/profile-example')
->assertOk()
->assertExactJson(['value' => 1])
->assertHeader('X-NewDebugBar-Profile');
ProfileAssertions::stored(
(string) $response->headers->get('X-NewDebugBar-Profile'),
)
->assertNoErrors()
->assertQueryCountAtMost(1)
->assertNoLikelyNPlusOneQueries();
});
For your application route, replace the example route and use the fixture data that makes the behavior meaningful. The N+1 walkthrough needs several parent records so repeated relationship reads can appear.
Assert a supplied profile when you already have it
Use ProfileAssertions::for($profile) when your test already owns the captured profile array. Use stored($id) when the response ID is your source of truth. Both apply the package’s presentation and analysis to the profile.
ProfileAssertions::for($profile)
->assertQueryCountAtMost(12)
->assertQueryTimeAtMost(100);
If the test response has no profile header
- Confirm the package is enabled and testing is in the allowed environments before the application boots.
- Check for a disabled environment variable or cached configuration used by the test process.
- Make the intended application request; the package’s own routes are excluded.
- Keep the exact response ID when tests or workers create several profiles.
Test command profiles are different from HTTP response assertions. See Artisan commands for their command-level scope.
Next step
Inspect a failing profile with an agent
Pass the exact response-header profile ID to the local MCP server for bounded findings and deeper retained evidence.
Open the MCP setup guide