is there a way to print the execution time of each test with PHPUnit?
Many of the current answers discuss how to access and analyze the duration times in the log file. I will share two ways to modify the CLI output in phpUnit version 3.7.38 (which is what Travis-CI uses for PHP by default), building on @edorian's incomplete answer.
Use a custom printer to override the CLI output. I can't find any documentation for printers but they appear to be supported. You can see which methods are available in the source code.
class TestDurationPrinter extends PHPUnit_TextUI_ResultPrinter
{
public function endTest(PHPUnit_Framework_Test $test, $time)
{
printf("Test '%s' ended and took %s seconds.\n",
$test->getName(),
$time
);
}
}
Then add these lines as attributes to phpunit
in the phpunit.xml
file:
printerFile="path/to/TestDurationPrinter.php"
printerClass="TestDurationPrinter"
You can also use the --printer
CLI option but that doesn't play well with namespaces.
You can add to the CLI output, as opposed to overriding it, with a TestListener by implementing the PHPUnit_Framework_TestListener
interface (this is the same interface that printers use). This will still print .
, S
, and F
so be sure to account for that, if you desire.
class TestDurationListener implements PHPUnit_Framework_TestListener
{
public function endTest(PHPUnit_Framework_Test $test, $time)
{
printf("Test '%s' ended and took %s seconds.\n",
$test->getName(),
$time
);
}
public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
{
}
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
{
}
public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
{
}
public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time)
{
}
public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
{
}
public function startTest(PHPUnit_Framework_Test $test)
{
}
public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
{
}
public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
{
}
}
In version 3.8 and above there is a PHPUnit_Framework_BaseTestListener
that can be extended so that you only define the methods you want to override.
class TestDurationListener extends PHPUnit_Framework_BaseTestListener
{
public function endTest(PHPUnit_Framework_Test $test, $time)
{
printf("Test '%s' ended.\n", $test->getName());
}
}
To include your new listener, add these lines to your phpunit.xml
file:
<listeners>
<listener class="TestDurationListener" file="path/to/TestDurationListener.php" />
</listeners>
In my opinion, the simplest solution is to export test statistic as json:
$ phpunit --log-json testExport.json
Just add --log-junit "my_tests_log.xml" and then open this file with spreadsheet application (Excel, Numbers, Calc) to view it. You get all information you ask for, and you can sort by test execution time.
I guess you could use the setUp
and tearDown
methods (which are called at the beginning and end of each test, respectively) to :
setUp
,tearDown
.
Of course, you'll have to do this in each one of your test classes -- or in a super-class which will be inherited by all your test classes.
Well, you can have it export the execution time with Logging. It's not directly outputted as the result, but you could write a pretty report viewer that would output the results of the log file (either from JSON or XML). That should get you what you want...
Here's a complete example based on the idea from edorians answer. Tested on PHPunit 4.
Create the following PHP class:
class ProfilingTestListener extends PHPUnit_Framework_BaseTestListener
{
public function endTest(PHPUnit_Framework_Test $test, $time)
{
printf("Test '%s' ended.\tTotal time %s s.\tTest time %s s.\n",
str_pad($test->toString(), 50),
number_format($test->getTestResultObject()->time(), 3),
number_format($time, 3)
);
}
}
Add the following to your phpunit.xml:
<phpunit ..>
...
<listeners>
<listener class="ProfilingTestListener"></listener>
</listeners>
...
</phpunit>
Example output:
PHPUnit 4.7.7 by Sebastian Bergmann and contributors.
Test 'FooTest::testFoo ' ended. Total time 2.050 s. Test time 0.026 s.
.Test 'FooTest::testBar ' ended. Total time 2.077 s. Test time 1.000 s.
.Test 'FooTest::testBar2 ' ended. Total time 3.077 s. Test time 0.730 s.