Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpunit Query Count Assertions Laravel Package

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+.

View on GitHub
Deep Wiki
Context7
1.1.5

PHP 8.4 support

1.1.4

Support for Laravel 12

1.1.3

Support for Laravel 11.x added

1.1.2
  • support Laravel 10
1.1.1
  • support Laravel 9
1.0.1
  • support Laravel 9
Query

Query Performance Assertions: Index Usage, Duplicates & Timing

This release adds powerful query performance assertions to catch inefficient queries in your tests.

New Assertions

Index Usage Detection

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.

Duplicate Query Detection

Catch repeated identical queries:

$this->assertNoDuplicateQueries(function () {
    User::find(1);
    User::find(1); // Fails - duplicate
});








Query Timing Assertions

Set performance budgets for your queries:

$this->assertMaxQueryTime(100, fn() => ...);    // No single query over 100ms
$this->assertTotalQueryTime(500, fn() => ...);  // Total time under 500ms








Row Count Threshold (MySQL/MariaDB)

Fail when queries examine too many rows:

$this->assertMaxRowsExamined(1000, fn() => User::where('status', 'active')->get());








Combined Efficiency Assertion

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.

Custom Query Analysers

Add support for additional databases:

AssertsQueryCounts::registerQueryAnalyser(new PostgresAnalyser());








Other Improvements

  • Issue severity levels (ERROR, WARNING, INFO) with configurable failure thresholds
  • Small table optimization: ignores full scans on tables < 10 rows
  • FK constraint context in SQLite scan warnings
  • PHPStan analysis added to CI

Backwards Compatibility

Fully backwards compatible. All existing methods unchanged.

Multi-framework

Summary

  • Add Doctrine/Symfony and Phalcon support via a driver-based architecture, while keeping Laravel zero-config
  • Unsupported features (lazy loading on Doctrine/Phalcon, query timing on Doctrine) now emit PHPUnit warnings instead of skipping the entire test
  • Add CI matrix covering all three frameworks across PHP 8.2–8.4
Cleanup

Simplify API by consolidating tracking methods

Summary

  • Consolidated trackQueriesForEfficiency() into trackQueries() — one method now does everything
  • Changed trackQueries() from static to instance method for consistent $this-> API

Breaking Changes

self::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();





Migration

Find and replace in your test files:

Find Replace
self::trackQueries() $this->trackQueries()
$this->trackQueriesForEfficiency() $this->trackQueries()

Why

The previous API had two methods that were confusingly similar:

  • trackQueries() — basic query logging
  • trackQueriesForEfficiency() — query logging + N+1 detection

Now 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().

1.0.0
  • initial release
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport