Note: this is for PHPUnit 3.5 or less. We’re restricted by a platform limitation from upgrading etc etc.
I wanted to find out which unit tests were taking a long time to run and to try and get our build time down a little. I believe that unit tests should not take longer then 2 seconds to run. Not the entire suite, that’s silly. Each test. Ideally, it’d be less then a second but, hey we don’t live in a perfect world.
So I implemented a Test Listener. The listener checks the timing provided by PHP Unit against constants set and can fail our CI Build if you check in a slow test. Enough rambling, here’s the code.
In your phpunit.xml add the following:
<listeners> <listener class="TestTimesListener" file="./TestTimesListener.php" /> </listeners>
Create the file TestTimesListener.php right next to it, or in the directory of your choice.
<?php class TestTimesListener implements PHPUnit_Framework_TestListener { /** * Anything above this threshold is deemed slow * @var float $seconds */ const MAX_EXECUTION_TIME = 0.2; /** * Absolute max time we should allow a unit test to run. * @var float $seconds */ const FAIL_IF_LONGER_THAN = 2.0; /** * Helper variables for assinting with naming * @var string */ private $_currentSuite; private $_fullTestName; public function startTest(PHPUnit_Framework_Test $test) { $this->_fullTestName = $this->_currentSuite->getName() . "::" . $test->getName(); } public function endTest(PHPUnit_Framework_Test $test, $time) { if ($time > self::MAX_EXECUTION_TIME) { printf( PHP_EOL . "%s took %f seconds" . PHP_EOL, $this->_fullTestName, $time ); if ($time >= self::FAIL_IF_LONGER_THAN) { $test->fail( sprintf( "%s is too slow, it takes %f seconds", $this->_fullTestName, $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 addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) { } public function startTestSuite(PHPUnit_Framework_TestSuite $suite) { $this->_currentSuite = $suite; } public function endTestSuite(PHPUnit_Framework_TestSuite $suite) { } }
Now, set those thresholds to something nice and low and run your test suites!