mattiasgeniar/phpunit-query-count-assertions
Add PHPUnit/Pest assertions to count and analyze SQL queries in tests. Catch N+1 issues, duplicate queries, slow queries, missing indexes (EXPLAIN), row count problems, and Laravel lazy loading. Supports Laravel 11/12, Doctrine DBAL 4, and Phalcon 6+.
Full Changelog: https://github.com/mattiasgeniar/phpunit-query-count-assertions/compare/1.1.6...1.1.7
PHP 8.4 support
Support for Laravel 12
Support for Laravel 11.x added
Full Changelog: https://github.com/mattiasgeniar/phpunit-query-count-assertions/compare/1.2.2...1.2.4
This release adds powerful query performance assertions to catch inefficient queries in your tests.
Detect full table scans and missing indexes by running EXPLAIN on your queries:
$this->assertAllQueriesUseIndexes(function () {
User::where('email', 'test@example.com')->first();
});
Supports MySQL, MariaDB, and SQLite. Detects full table scans, unused indexes, filesort, temporary tables, and more.
Catch repeated identical queries:
$this->assertNoDuplicateQueries(function () {
User::find(1);
User::find(1); // Fails - duplicate
});
Set performance budgets for your queries:
$this->assertMaxQueryTime(100, fn() => ...); // No single query over 100ms
$this->assertTotalQueryTime(500, fn() => ...); // Total time under 500ms
Fail when queries examine too many rows:
$this->assertMaxRowsExamined(1000, fn() => User::where('status', 'active')->get());
Check everything at once—N+1, duplicates, and index usage:
$this->assertQueriesAreEfficient(function () {
$users = User::with('posts')->get();
});
Or use trackQueries() in setUp/beforeEach for test-wide tracking.
Add support for additional databases:
AssertsQueryCounts::registerQueryAnalyser(new PostgresAnalyser());
Fully backwards compatible. All existing methods unchanged.
trackQueriesForEfficiency() into trackQueries() — one method now does everythingtrackQueries() from static to instance method for consistent $this-> APIself::trackQueries() → $this->trackQueries()
The method is no longer static. Update your setUp/beforeEach:
// Before
protected function setUp(): void
{
parent::setUp();
self::trackQueries();
}
// After
protected function setUp(): void
{
parent::setUp();
$this->trackQueries();
}
trackQueriesForEfficiency() is deprecated
Replace with trackQueries():
// Before
$this->trackQueriesForEfficiency();
// After
$this->trackQueries();
Find and replace in your test files:
| Find | Replace |
|---|---|
self::trackQueries() |
$this->trackQueries() |
$this->trackQueriesForEfficiency() |
$this->trackQueries() |
The previous API had two methods that were confusingly similar:
trackQueries() — basic query loggingtrackQueriesForEfficiency() — query logging + N+1 detectionNow there's just one method that does everything. If you only need query counts, the efficiency tracking has zero overhead — just don't call assertQueriesAreEfficient().
How can I help you explore Laravel packages today?