Enhancing PHP Unit Tests: Adding Artisan Test Styles to PHPUnit Output
When working on a Laravel project, I often find myself toggling between phpunit
for running unit tests and php artisan test
for its enhanced output. The latter not only offers a more visually pleasing format but provides helpful additional information like the duration of each test. This is particularly useful for identifying slow tests in the suite — a crucial aspect when aiming for efficient test optimizations.
The standard output of PHPUnit, while thorough, lacks the immediate clarity and additional metrics provided by Laravel’s php artisan test
. Knowing that this command is essentially a wrapper for PHPUnit with an enhanced console output sparked my curiosity: could I somehow combine the benefits of using php artisan test
(specifically its appealing format and test duration data), with the flexibility and additional logging capabilities of running phpunit
directly?
Exploring the Artisan Command
Laravel’s php artisan test
leverages a package called Collision, which enhances the PHPUnit output. Collision provides a beautifully styled output, making test results more readable and easier to debug. My challenge was to bring some of this styling and functionality, such as test execution time, directly into the bare PHPUnit setting.
Customizing PHPUnit using Listeners
PHPUnit supports “listeners” which can be used to hook into the test execution lifecycle to add additional functionality or modify the output. By defining a custom listener, I might capture timing data for each test and output it in a format similar to what php artisan test
provides.
Considering our Laravel setup, here’s a basic setup you could experiment with:
- Create a Custom Test Listener
I can start by creating a custom listener class within my Laravel project that implements PHPUnit\Framework\TestListener
. This listener would listen for test start and test end events to calculate and store test durations.
// app/Testing/CustomTestListener.php namespace App\Testing; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestListener; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\Warning; class CustomTestListener implements TestListener { private $startTime; public function startTest(Test $test) : void { $this->startTime = microtime(true); } public function endTest(Test $test, float $time) : void { $duration = microtime(true) - $this->startTime; echo sprintf("%s took %s seconds\n", get_class($test), number_format($duration, 3)); } // Other necessary methods would be implemented here, potentially no-ops or logging. }
- Register the Listener in phpunit.xml
Next, I would configure PHPUnit to use this listener by adding it to my phpunit.xml
configuration file:
<listeners> <listener class="App\Testing\CustomTestListener" file="app/Testing/CustomTestListener.php"/> </listeners>
- Running PHPUnit with the Custom Listener
Now, when I run phpunit
, it should utilize the custom listener, echoing out the duration of each test, emulating part of what php artisan test
outputs.
While this setup doesn’t fully replicate the style of php artisan test
, it does provide the useful time metrics, which was a key feature I didn’t want to miss from Laravel’s testing output.
By bridging some of the functionalities of php artisan test
and phpunit
in this way, I can maintain the necessary flexibility for logging and other configurations within PHPUnit testing, while gaining additional insights typically provided by Laravel’s enhanced test output. This blended approach allows me to enhance the readability and effectiveness of my testing workflow in Laravel projects.
Leave a Reply