Skip to content

Commit

Permalink
Merge pull request #208 from openforests-git/feature/SW/database-quer…
Browse files Browse the repository at this point in the history
…y-count-assertions

Adding helpers for asserting database query count
  • Loading branch information
Mohammad-Alavi authored Oct 7, 2024
2 parents 2d46ea0 + e84abef commit 3e839a7
Show file tree
Hide file tree
Showing 4 changed files with 661 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Abstracts/Tests/PhpUnit/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Apiato\Core\Traits\TestCaseTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestAssertionHelperTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestAuthHelperTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestDatabaseProfilerTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestRequestHelperTrait;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
Expand All @@ -20,6 +21,7 @@ abstract class TestCase extends LaravelTestCase
use TestAssertionHelperTrait;
use HashIdTrait;
use LazilyRefreshDatabase;
use TestDatabaseProfilerTrait;

/**
* The base URL to use while testing the application.
Expand Down
149 changes: 149 additions & 0 deletions src/Traits/TestTraits/PhpUnit/TestDatabaseProfilerTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

namespace Apiato\Core\Traits\TestTraits\PhpUnit;

trait TestDatabaseProfilerTrait
{
/**
* Start profiling database queries.
*/
protected function startDatabaseQueryLog(): void
{
$this->app->make('db')->enableQueryLog();
}

/**
* Stop profiling database queries.
*/
protected function stopDatabaseQueryLog(): void
{
$this->app->make('db')->disableQueryLog();
}

/**
* Get the database queries.
*/
protected function getDatabaseQueries(): array
{
return $this->app->make('db')->getQueryLog();
}

/**
* Dump the database queries.
*/
protected function dumpDatabaseQueries(): void
{
foreach ($this->getDatabaseQueries() as $query) {
dump($query['query']);
}
}

/**
* Dump and die the database queries.
*/
protected function ddDatabaseQueries(): never
{
dd($this->getDatabaseQueries());
}

/**
* Assert the number of database queries.
*/
protected function assertDatabaseQueryCount(int $expectedCount): void
{
$actualCount = count($this->getDatabaseQueries());
$this->assertEquals($expectedCount, $actualCount, "Expected $expectedCount database queries, but got $actualCount.");
}

/**
* Assert that the database queries contain the expected query.
*/
protected function assertDatabaseExecutedQuery(string $expectedQuery): void
{
$queries = $this->getDatabaseQueries();

$found = false;
foreach ($queries as $query) {
if (str_contains($query['query'], $expectedQuery)) {
$found = true;
break;
}
}

$this->assertTrue($found, "Expected query '$expectedQuery' not found in database queries.");
}

/**
* Assert that the database queries contain the expected queries.
*/
protected function assertDatabaseExecutedQueries(array $expectedQueries): void
{
$queries = $this->getDatabaseQueries();

foreach ($expectedQueries as $expectedQuery) {
$found = false;
foreach ($queries as $query) {
if (str_contains($query['query'], $expectedQuery)) {
$found = true;
break;
}
}

$this->assertTrue($found, "Expected query '$expectedQuery' not found in database queries.");
}
}

/**
* Wrapper to profile database queries.
*/
protected function profileDatabaseQueries(callable $callback): mixed
{
try {
$this->startDatabaseQueryLog();
$result = $callback();
} finally {
$this->stopDatabaseQueryLog();
}

return $result;
}

/**
* Wrapper to profile database queries and assert the number of queries.
*/
protected function profileDatabaseQueryCount(int $expectedCount, callable $callback): mixed
{
return $this->profileDatabaseQueries(function () use ($expectedCount, $callback) {
$result = $callback();
$this->assertDatabaseQueryCount($expectedCount);

return $result;
});
}

/**
* Wrapper to profile database queries and assert the executed query.
*/
protected function profileDatabaseExecutedQuery(string $expectedQuery, callable $callback): mixed
{
return $this->profileDatabaseQueries(function () use ($expectedQuery, $callback) {
$result = $callback();
$this->assertDatabaseExecutedQuery($expectedQuery);

return $result;
});
}

/**
* Wrapper to profile database queries and assert the executed queries.
*/
protected function profileDatabaseExecutedQueries(array $expectedQueries, callable $callback): mixed
{
return $this->profileDatabaseQueries(function () use ($expectedQueries, $callback) {
$result = $callback();
$this->assertDatabaseExecutedQueries($expectedQueries);

return $result;
});
}
}
35 changes: 35 additions & 0 deletions tests/Unit/Abstracts/Tests/PhpUnit/TestCaseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Apiato\Core\Tests\Unit\Abstracts\Tests\PhpUnit;

use Apiato\Core\Abstracts\Tests\PhpUnit\TestCase;
use Apiato\Core\Tests\Unit\UnitTestCase;
use Apiato\Core\Traits\HashIdTrait;
use Apiato\Core\Traits\TestCaseTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestAssertionHelperTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestAuthHelperTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestDatabaseProfilerTrait;
use Apiato\Core\Traits\TestTraits\PhpUnit\TestRequestHelperTrait;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use PHPUnit\Framework\Attributes\CoversClass;

#[CoversClass(TestCase::class)]
final class TestCaseTest extends UnitTestCase
{
public function testUsesTraits(): void
{
$traits = [
TestCaseTrait::class,
TestAuthHelperTrait::class,
TestRequestHelperTrait::class,
TestAssertionHelperTrait::class,
HashIdTrait::class,
LazilyRefreshDatabase::class,
TestDatabaseProfilerTrait::class,
];

foreach ($traits as $trait) {
$this->assertContains($trait, class_uses_recursive(TestCase::class));
}
}
}
Loading

0 comments on commit 3e839a7

Please sign in to comment.