Skip to content

Commit

Permalink
improved Writer unit testing
Browse files Browse the repository at this point in the history
  • Loading branch information
onlime committed Jun 3, 2021
1 parent c2a7c63 commit c8dd058
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 30 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

### Added
- Added new config param `queries.exclude_pattern` (env var `SQL_REPORTER_QUERIES_EXCLUDE_PATTERN`) to narrow down queries to be logged without bloating include pattern regex.
- Added unit tests for `Writer`, testing query include/exclude patterns and min exec time.

### Changed
- Renamed `SQL_REPORTER_QUERIES_PATTERN` env var to `SQL_REPORTER_QUERIES_INCLUDE_PATTERN`
- Renamed methods in `Writer` for clarity.
- Improved testability of `Writer::writeQuery()` by returning true if query was written to log.

## [v0.9 (2021-06-02)](https://github.com/onlime/laravel-sql-reporter/releases/tag/v0.9)

Expand Down
2 changes: 1 addition & 1 deletion src/SqlLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function log()
{
foreach (DB::getQueryLog() as $query) {
$sqlQuery = new SqlQuery(++$this->queryNumber, $query['query'], $query['bindings'], $query['time']);
$this->writer->save($sqlQuery);
$this->writer->writeQuery($sqlQuery);
}
}
}
29 changes: 17 additions & 12 deletions src/Writer.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,47 +26,52 @@ public function __construct(
) {}

/**
* Save queries to log.
* Write a query to log.
*
* @param SqlQuery $query
* @return bool true if query was written to log, false if skipped
*/
public function save(SqlQuery $query)
public function writeQuery(SqlQuery $query): bool
{
$this->createDirectoryIfNotExists($query->number());

if ($this->shouldLogQuery($query)) {
if (0 === $this->logCount) {
// only write header information on first query to be logged
$this->saveLine(
$this->writeLine(
$this->formatter->getHeader(),
$this->config->queriesOverrideLog()
);
}
$this->saveLine(
$this->writeLine(
$this->formatter->getLine($query)
);
$this->logCount++;
return true;
}
return false;
}

/**
* Create directory if it does not exist yet.
*
* @param int $queryNumber
* @return bool true on successful directory creation
*/
protected function createDirectoryIfNotExists(int $queryNumber)
protected function createDirectoryIfNotExists(int $queryNumber): bool
{
if ($queryNumber == 1 && ! file_exists($directory = $this->directory())) {
mkdir($directory, 0777, true);
return mkdir($directory, 0777, true);
}
return false;
}

/**
* Get directory where file should be located.
*
* @return string
*/
protected function directory()
protected function directory(): string
{
return rtrim($this->config->logDirectory(), '\\/');
}
Expand All @@ -75,10 +80,9 @@ protected function directory()
* Verify whether query should be logged.
*
* @param SqlQuery $query
*
* @return bool
*/
protected function shouldLogQuery(SqlQuery $query)
protected function shouldLogQuery(SqlQuery $query): bool
{
return $this->config->queriesEnabled() &&
$query->time() >= $this->config->queriesMinExecTime() &&
Expand All @@ -87,14 +91,15 @@ protected function shouldLogQuery(SqlQuery $query)
}

/**
* Save data to log file.
* Write data to log file.
*
* @param string $line
* @param bool $override
* @return int|false the number of bytes that were written to the file, or false on failure.
*/
protected function saveLine(string $line, bool $override = false)
protected function writeLine(string $line, bool $override = false): int|false
{
file_put_contents(
return file_put_contents(
$this->directory() . DIRECTORY_SEPARATOR . $this->fileName->getLogfile(),
$line . PHP_EOL,
$override ? 0 : FILE_APPEND
Expand Down
12 changes: 6 additions & 6 deletions tests/Unit/SqlLoggerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public function it_runs_writer_with_valid_query()
]);

$sqlQuery = new SqlQuery(1, 'anything', [], 1.23);
// $this->writer->shouldReceive('save')->once()->with($sqlQuery)
$this->writer->shouldReceive('save')->once()->with(Mockery::on(function($arg) use ($sqlQuery) {
// $this->writer->shouldReceive('writeQuery')->once()->with($sqlQuery)
$this->writer->shouldReceive('writeQuery')->once()->with(Mockery::on(function($arg) use ($sqlQuery) {
return $sqlQuery == $arg;
}));

Expand All @@ -52,14 +52,14 @@ public function it_uses_valid_query_number_for_multiple_queries()
]);

$sqlQuery = new SqlQuery(1, 'anything', ['one', 1], 1.23);
// $this->writer->shouldReceive('save')->once()->with($sqlQuery);
$this->writer->shouldReceive('save')->once()->with(Mockery::on(function($arg) use ($sqlQuery) {
// $this->writer->shouldReceive('writeQuery')->once()->with($sqlQuery);
$this->writer->shouldReceive('writeQuery')->once()->with(Mockery::on(function($arg) use ($sqlQuery) {
return $sqlQuery == $arg;
}));

$sqlQuery2 = new SqlQuery(2, 'anything2', ['two', 2], 4.56);
// $this->writer->shouldReceive('save')->once()->with($sqlQuery2);
$this->writer->shouldReceive('save')->once()->with(Mockery::on(function($arg) use ($sqlQuery2) {
// $this->writer->shouldReceive('writeQuery')->once()->with($sqlQuery2);
$this->writer->shouldReceive('writeQuery')->once()->with(Mockery::on(function($arg) use ($sqlQuery2) {
return $sqlQuery2 == $arg;
}));

Expand Down
72 changes: 61 additions & 11 deletions tests/Unit/WriterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function it_creates_directory_if_it_does_not_exist_for_1st_query()
$this->config->shouldReceive('queriesEnabled')->once()->withNoArgs()->andReturn(false);
$this->config->shouldReceive('logDirectory')->once()->withNoArgs()->andReturn($this->directory);
$this->assertFileDoesNotExist($this->directory);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertFileExists($this->directory);
$this->assertEmpty($this->filesystem->allFiles($this->directory));
}
Expand All @@ -85,7 +85,7 @@ public function it_does_not_create_directory_if_it_does_not_exist_for_2nd_query(
$this->config->shouldReceive('queriesEnabled')->once()->withNoArgs()->andReturn(false);
$this->config->shouldNotReceive('logDirectory');
$this->assertFileDoesNotExist($this->directory);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertFileDoesNotExist($this->directory);
}

Expand All @@ -106,7 +106,7 @@ public function it_creates_log_file()
$this->config->shouldReceive('queriesOverrideLog')->once()->withNoArgs()->andReturn(false);
$this->config->shouldReceive('queriesMinExecTime')->once()->withNoArgs()->andReturn(0);
$this->filename->shouldReceive('getLogfile')->times(2)->withNoArgs()->andReturn($expectedFileName);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertFileExists($this->directory);
$this->assertCount(1, $this->filesystem->allFiles($this->directory));
$this->assertFileExists($this->directory . '/' . $expectedFileName);
Expand Down Expand Up @@ -135,7 +135,7 @@ public function it_appends_to_existing_log_file()
$this->config->shouldReceive('queriesMinExecTime')->once()->withNoArgs()->andReturn(0);
$this->filename->shouldReceive('getLogfile')->times(2)->withNoArgs()->andReturn($expectedFileName);
$this->assertFileExists($this->directory . '/' . $expectedFileName);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertCount(1, $this->filesystem->allFiles($this->directory));
$this->assertFileExists($this->directory . '/' . $expectedFileName);
$this->assertSame($expectedContent, file_get_contents($this->directory . '/' . $expectedFileName));
Expand Down Expand Up @@ -163,7 +163,7 @@ public function it_replaces_current_file_content_for_1st_query_when_overriding_i
$this->config->shouldReceive('queriesMinExecTime')->once()->withNoArgs()->andReturn(0);
$this->filename->shouldReceive('getLogfile')->times(2)->withNoArgs()->andReturn($expectedFileName);
$this->assertFileExists($this->directory . '/' . $expectedFileName);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertCount(1, $this->filesystem->allFiles($this->directory));
$this->assertFileExists($this->directory . '/' . $expectedFileName);
$this->assertSame($expectedContent, file_get_contents($this->directory . '/' . $expectedFileName));
Expand Down Expand Up @@ -192,8 +192,8 @@ public function it_appends_to_current_file_content_for_2nd_query_when_overriding
$this->config->shouldReceive('queriesMinExecTime')->twice()->withNoArgs()->andReturn(0);
$this->filename->shouldReceive('getLogfile')->times(3)->withNoArgs()->andReturn($expectedFileName);
$this->assertFileExists($this->directory . '/' . $expectedFileName);
$this->writer->save($query1);
$this->writer->save($query2);
$this->writer->writeQuery($query1);
$this->writer->writeQuery($query2);
$this->assertCount(1, $this->filesystem->allFiles($this->directory));
$this->assertFileExists($this->directory . '/' . $expectedFileName);
$this->assertSame($expectedContent, file_get_contents($this->directory . '/' . $expectedFileName));
Expand All @@ -216,7 +216,7 @@ public function it_saves_select_query_to_file_when_pattern_set_to_select_queries
$this->config->shouldReceive('queriesMinExecTime')->once()->withNoArgs()->andReturn(0);
$this->filename->shouldReceive('getLogfile')->twice()->withNoArgs()->andReturn($expectedFileName);
$this->config->shouldReceive('queriesOverrideLog')->once()->withNoArgs()->andReturn(false);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertFileExists($this->directory);
$this->assertCount(1, $this->filesystem->allFiles($this->directory));

Expand All @@ -232,7 +232,7 @@ public function it_doesnt_save_select_query_to_file_when_pattern_set_to_insert_o
$this->config->shouldReceive('queriesIncludePattern')->once()->withNoArgs()->andReturn('#^(?:UPDATE|INSERT) .*$#i');
$this->config->shouldReceive('queriesMinExecTime')->once()->withNoArgs()->andReturn(0);
$this->config->shouldReceive('logDirectory')->once()->withNoArgs()->andReturn($this->directory);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertFileExists($this->directory);
$this->assertCount(0, $this->filesystem->allFiles($this->directory));
}
Expand All @@ -254,7 +254,7 @@ public function it_saves_insert_query_to_file_when_pattern_set_to_insert_or_upda
$this->config->shouldReceive('queriesMinExecTime')->once()->withNoArgs()->andReturn(0);
$this->filename->shouldReceive('getLogfile')->twice()->withNoArgs()->andReturn($expectedFileName);
$this->config->shouldReceive('queriesOverrideLog')->once()->withNoArgs()->andReturn(false);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertFileExists($this->directory);
$this->assertCount(1, $this->filesystem->allFiles($this->directory));

Expand All @@ -279,11 +279,61 @@ public function it_uses_raw_query_without_bindings_when_using_query_pattern()
$this->filename->shouldReceive('getLogfile')->twice()->withNoArgs()->andReturn($expectedFileName);
$this->config->shouldReceive('queriesMinExecTime')->once()->withNoArgs()->andReturn(0);
$this->config->shouldReceive('queriesOverrideLog')->once()->withNoArgs()->andReturn(false);
$this->writer->save($query);
$this->writer->writeQuery($query);
$this->assertFileExists($this->directory);
$this->assertCount(1, $this->filesystem->allFiles($this->directory));

$this->assertFileExists($this->directory . '/' . $expectedFileName);
$this->assertSame($expectedContent, file_get_contents($this->directory . '/' . $expectedFileName));
}

/** @test */
public function it_only_logs_slow_queries()
{
$query1 = new SqlQuery(1, 'test1', [], 5.41);
$query2 = new SqlQuery(2, 'test2', [], 500.5);

$this->config->shouldReceive('queriesEnabled')->twice()->withNoArgs()->andReturn(true);
$this->config->shouldReceive('logDirectory')->once()->withNoArgs()->andReturn($this->directory);
$this->config->shouldReceive('queriesMinExecTime')->twice()->withNoArgs()->andReturn(500);
$this->config->shouldReceive('queriesIncludePattern')->once()->withNoArgs()->andReturn('/.*/i');
$this->config->shouldReceive('queriesExcludePattern')->once()->withNoArgs()->andReturn('/^$/');
$this->config->shouldReceive('queriesOverrideLog')->once()->withNoArgs()->andReturn(false);

$this->formatter->shouldReceive('getHeader')->once()->withNoArgs()->andReturn('');
$this->formatter->shouldReceive('getLine')->once()->with($query2)->andReturn('');

$writer = Mockery::mock(Writer::class, [$this->formatter, $this->config, $this->filename])
->makePartial()->shouldAllowMockingProtectedMethods();
$writer->shouldReceive('writeLine')->twice()->andReturn(false);

$this->assertFalse($writer->writeQuery($query1));
$this->assertTrue($writer->writeQuery($query2));
}

/** @test */
public function it_respects_query_patterns()
{
$query1 = new SqlQuery(1, 'select foo from bar', [], 5.41);
$query2 = new SqlQuery(2, 'update bar set foo = ?', [1], 3.55);
$query3 = new SqlQuery(3, 'update bar set last_visit = ?', ['2021-06-03 10:26:00'], 3.22);

$this->config->shouldReceive('queriesEnabled')->times(3)->withNoArgs()->andReturn(true);
$this->config->shouldReceive('logDirectory')->once()->withNoArgs()->andReturn($this->directory);
$this->config->shouldReceive('queriesMinExecTime')->times(3)->withNoArgs()->andReturn(0);
$this->config->shouldReceive('queriesIncludePattern')->times(3)->withNoArgs()->andReturn('/^(?!SELECT).*$/i');
$this->config->shouldReceive('queriesExcludePattern')->twice()->withNoArgs()->andReturn('/^UPDATE.*last_visit/i');
$this->config->shouldReceive('queriesOverrideLog')->once()->withNoArgs()->andReturn(false);

$this->formatter->shouldReceive('getHeader')->once()->withNoArgs()->andReturn('');
$this->formatter->shouldReceive('getLine')->once()->with($query2)->andReturn('');

$writer = Mockery::mock(Writer::class, [$this->formatter, $this->config, $this->filename])
->makePartial()->shouldAllowMockingProtectedMethods();
$writer->shouldReceive('writeLine')->twice()->andReturn(false);

$this->assertFalse($writer->writeQuery($query1));
$this->assertTrue($writer->writeQuery($query2));
$this->assertFalse($writer->writeQuery($query3));
}
}

0 comments on commit c8dd058

Please sign in to comment.