From 2845280ffd00996e9b9b169a46d4d7da758c5176 Mon Sep 17 00:00:00 2001 From: Scott Taylor Date: Fri, 16 Oct 2015 00:27:28 +0000 Subject: [PATCH] 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 --- phpunit.xml.dist | 11 + .../phpunit/includes/speed-trap-listener.php | 314 ++++++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 tests/phpunit/includes/speed-trap-listener.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 731fb4ae3f..52717bfa53 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -31,4 +31,15 @@ + + + + + + 150 + + + + + diff --git a/tests/phpunit/includes/speed-trap-listener.php b/tests/phpunit/includes/speed-trap-listener.php new file mode 100644 index 0000000000..e7e3c1a61c --- /dev/null +++ b/tests/phpunit/includes/speed-trap-listener.php @@ -0,0 +1,314 @@ +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): + * + * + * \@slowThreshold 5000 + * public function testLongRunningProcess() {} + * + * + * @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; + } +}