Unit Tests: add `SpeedTrapListener` to `phpunit/includes` and add the config node to `phpunit.xml.dist`.
See #30017, #33968. git-svn-id: https://develop.svn.wordpress.org/trunk@35214 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
159a5b518b
commit
2845280ffd
|
@ -31,4 +31,15 @@
|
|||
<php>
|
||||
<const name="WP_RUN_CORE_TESTS" value="1" />
|
||||
</php>
|
||||
<listeners>
|
||||
<listener class="SpeedTrapListener" file="tests/phpunit/includes/speed-trap-listener.php">
|
||||
<arguments>
|
||||
<array>
|
||||
<element key="slowThreshold">
|
||||
<integer>150</integer>
|
||||
</element>
|
||||
</array>
|
||||
</arguments>
|
||||
</listener>
|
||||
</listeners>
|
||||
</phpunit>
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* A PHPUnit TestListener that exposes your slowest running tests by outputting
|
||||
* results directly to the console.
|
||||
*/
|
||||
class SpeedTrapListener implements \PHPUnit_Framework_TestListener
|
||||
{
|
||||
/**
|
||||
* Internal tracking for test suites.
|
||||
*
|
||||
* Increments as more suites are run, then decremented as they finish. All
|
||||
* suites have been run when returns to 0.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $suites = 0;
|
||||
|
||||
/**
|
||||
* Time in milliseconds at which a test will be considered "slow" and be
|
||||
* reported by this listener.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $slowThreshold;
|
||||
|
||||
/**
|
||||
* Number of tests to report on for slowness.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $reportLength;
|
||||
|
||||
/**
|
||||
* Collection of slow tests.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $slow = array();
|
||||
|
||||
/**
|
||||
* Construct a new instance.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
$this->loadOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* An error occurred.
|
||||
*
|
||||
* @param \PHPUnit_Framework_Test $test
|
||||
* @param \Exception $e
|
||||
* @param float $time
|
||||
*/
|
||||
public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A failure occurred.
|
||||
*
|
||||
* @param \PHPUnit_Framework_Test $test
|
||||
* @param \PHPUnit_Framework_AssertionFailedError $e
|
||||
* @param float $time
|
||||
*/
|
||||
public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Incomplete test.
|
||||
*
|
||||
* @param \PHPUnit_Framework_Test $test
|
||||
* @param \Exception $e
|
||||
* @param float $time
|
||||
*/
|
||||
public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Risky test.
|
||||
*
|
||||
* @param \PHPUnit_Framework_Test $test
|
||||
* @param \Exception $e
|
||||
* @param float $time
|
||||
* @since Method available since Release 4.0.0
|
||||
*/
|
||||
public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Skipped test.
|
||||
*
|
||||
* @param \PHPUnit_Framework_Test $test
|
||||
* @param \Exception $e
|
||||
* @param float $time
|
||||
*/
|
||||
public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A test started.
|
||||
*
|
||||
* @param \PHPUnit_Framework_Test $test
|
||||
*/
|
||||
public function startTest(\PHPUnit_Framework_Test $test)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A test ended.
|
||||
*
|
||||
* @param \PHPUnit_Framework_Test $test
|
||||
* @param float $time
|
||||
*/
|
||||
public function endTest(\PHPUnit_Framework_Test $test, $time)
|
||||
{
|
||||
if (!$test instanceof \PHPUnit_Framework_TestCase) return;
|
||||
|
||||
$time = $this->toMilliseconds($time);
|
||||
$threshold = $this->getSlowThreshold($test);
|
||||
|
||||
if ($this->isSlow($time, $threshold)) {
|
||||
$this->addSlowTest($test, $time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A test suite started.
|
||||
*
|
||||
* @param \PHPUnit_Framework_TestSuite $suite
|
||||
*/
|
||||
public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
|
||||
{
|
||||
$this->suites++;
|
||||
}
|
||||
|
||||
/**
|
||||
* A test suite ended.
|
||||
*
|
||||
* @param \PHPUnit_Framework_TestSuite $suite
|
||||
*/
|
||||
public function endTestSuite(\PHPUnit_Framework_TestSuite $suite)
|
||||
{
|
||||
$this->suites--;
|
||||
|
||||
if (0 === $this->suites && $this->hasSlowTests()) {
|
||||
arsort($this->slow); // Sort longest running tests to the top
|
||||
|
||||
$this->renderHeader();
|
||||
$this->renderBody();
|
||||
$this->renderFooter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given test execution time is considered slow.
|
||||
*
|
||||
* @param int $time Test execution time in milliseconds
|
||||
* @param int $slowThreshold Test execution time at which a test should be considered slow (milliseconds)
|
||||
* @return bool
|
||||
*/
|
||||
protected function isSlow($time, $slowThreshold)
|
||||
{
|
||||
return $time >= $slowThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a test as slow.
|
||||
*
|
||||
* @param \PHPUnit_Framework_TestCase $test
|
||||
* @param int $time Test execution time in milliseconds
|
||||
*/
|
||||
protected function addSlowTest(\PHPUnit_Framework_TestCase $test, $time)
|
||||
{
|
||||
$label = $this->makeLabel($test);
|
||||
|
||||
$this->slow[$label] = $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether at least one test has been considered slow.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasSlowTests()
|
||||
{
|
||||
return !empty($this->slow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert PHPUnit's reported test time (microseconds) to milliseconds.
|
||||
*
|
||||
* @param float $time
|
||||
* @return int
|
||||
*/
|
||||
protected function toMilliseconds($time)
|
||||
{
|
||||
return (int) round($time * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Label for describing a test.
|
||||
*
|
||||
* @param \PHPUnit_Framework_TestCase $test
|
||||
* @return string
|
||||
*/
|
||||
protected function makeLabel(\PHPUnit_Framework_TestCase $test)
|
||||
{
|
||||
return sprintf('%s:%s', get_class($test), $test->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate number of slow tests to report about.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getReportLength()
|
||||
{
|
||||
return min(count($this->slow), $this->reportLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find how many slow tests occurred that won't be shown due to list length.
|
||||
*
|
||||
* @return int Number of hidden slow tests
|
||||
*/
|
||||
protected function getHiddenCount()
|
||||
{
|
||||
$total = count($this->slow);
|
||||
$showing = $this->getReportLength($this->slow);
|
||||
|
||||
$hidden = 0;
|
||||
if ($total > $showing) {
|
||||
$hidden = $total - $showing;
|
||||
}
|
||||
|
||||
return $hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders slow test report header.
|
||||
*/
|
||||
protected function renderHeader()
|
||||
{
|
||||
echo sprintf("\n\nYou should really fix these slow tests (>%sms)...\n", $this->slowThreshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders slow test report body.
|
||||
*/
|
||||
protected function renderBody()
|
||||
{
|
||||
$slowTests = $this->slow;
|
||||
|
||||
$length = $this->getReportLength($slowTests);
|
||||
for ($i = 1; $i <= $length; ++$i) {
|
||||
$label = key($slowTests);
|
||||
$time = array_shift($slowTests);
|
||||
|
||||
echo sprintf(" %s. %sms to run %s\n", $i, $time, $label);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders slow test report footer.
|
||||
*/
|
||||
protected function renderFooter()
|
||||
{
|
||||
if ($hidden = $this->getHiddenCount($this->slow)) {
|
||||
echo sprintf("...and there %s %s more above your threshold hidden from view", $hidden == 1 ? 'is' : 'are', $hidden);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate options into class internals.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
protected function loadOptions(array $options)
|
||||
{
|
||||
$this->slowThreshold = isset($options['slowThreshold']) ? $options['slowThreshold'] : 500;
|
||||
$this->reportLength = isset($options['reportLength']) ? $options['reportLength'] : 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get slow test threshold for given test. A TestCase can override the
|
||||
* suite-wide slow threshold by using the annotation @slowThreshold with
|
||||
* the threshold value in milliseconds.
|
||||
*
|
||||
* The following test will only be considered slow when its execution time
|
||||
* reaches 5000ms (5 seconds):
|
||||
*
|
||||
* <code>
|
||||
* \@slowThreshold 5000
|
||||
* public function testLongRunningProcess() {}
|
||||
* </code>
|
||||
*
|
||||
* @param \PHPUnit_Framework_TestCase $test
|
||||
* @return int
|
||||
*/
|
||||
protected function getSlowThreshold(\PHPUnit_Framework_TestCase $test)
|
||||
{
|
||||
$ann = $test->getAnnotations();
|
||||
|
||||
return isset($ann['method']['slowThreshold'][0]) ? $ann['method']['slowThreshold'][0] : $this->slowThreshold;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue