Changeset 42343 for trunk/tests/phpunit/includes/speed-trap-listener.php
- Timestamp:
- 11/30/2017 11:09:33 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tests/phpunit/includes/speed-trap-listener.php
r35767 r42343 5 5 * results directly to the console. 6 6 */ 7 class SpeedTrapListener implements PHPUnit_Framework_TestListener 8 { 9 /** 10 * Internal tracking for test suites. 11 * 12 * Increments as more suites are run, then decremented as they finish. All 13 * suites have been run when returns to 0. 14 * 15 * @var integer 16 */ 17 protected $suites = 0; 18 19 /** 20 * Time in milliseconds at which a test will be considered "slow" and be 21 * reported by this listener. 22 * 23 * @var int 24 */ 25 protected $slowThreshold; 26 27 /** 28 * Number of tests to report on for slowness. 29 * 30 * @var int 31 */ 32 protected $reportLength; 33 34 /** 35 * Collection of slow tests. 36 * 37 * @var array 38 */ 39 protected $slow = array(); 40 41 /** 42 * Construct a new instance. 43 * 44 * @param array $options 45 */ 46 public function __construct(array $options = array()) 47 { 48 $this->loadOptions($options); 49 } 50 51 /** 52 * An error occurred. 53 * 54 * @param PHPUnit_Framework_Test $test 55 * @param Exception $e 56 * @param float $time 57 */ 58 public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) 59 { 60 } 61 62 /** 63 * A warning occurred. 64 * 65 * @param PHPUnit_Framework_Test $test 66 * @param PHPUnit_Framework_Warning $e 67 * @param float $time 68 * @since Method available since Release 5.1.0 69 */ 70 public function addWarning(PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time) 71 { 72 } 73 74 /** 75 * A failure occurred. 76 * 77 * @param PHPUnit_Framework_Test $test 78 * @param PHPUnit_Framework_AssertionFailedError $e 79 * @param float $time 80 */ 81 public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) 82 { 83 } 84 85 /** 86 * Incomplete test. 87 * 88 * @param PHPUnit_Framework_Test $test 89 * @param Exception $e 90 * @param float $time 91 */ 92 public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) 93 { 94 } 95 96 /** 97 * Risky test. 98 * 99 * @param PHPUnit_Framework_Test $test 100 * @param Exception $e 101 * @param float $time 102 * @since Method available since Release 4.0.0 103 */ 104 public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) 105 { 106 } 107 108 /** 109 * Skipped test. 110 * 111 * @param PHPUnit_Framework_Test $test 112 * @param Exception $e 113 * @param float $time 114 */ 115 public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) 116 { 117 } 118 119 /** 120 * A test started. 121 * 122 * @param PHPUnit_Framework_Test $test 123 */ 124 public function startTest(PHPUnit_Framework_Test $test) 125 { 126 } 127 128 /** 129 * A test ended. 130 * 131 * @param PHPUnit_Framework_Test $test 132 * @param float $time 133 */ 134 public function endTest(PHPUnit_Framework_Test $test, $time) 135 { 136 if (!$test instanceof PHPUnit_Framework_TestCase) return; 137 138 $time = $this->toMilliseconds($time); 139 $threshold = $this->getSlowThreshold($test); 140 141 if ($this->isSlow($time, $threshold)) { 142 $this->addSlowTest($test, $time); 143 } 144 } 145 146 /** 147 * A test suite started. 148 * 149 * @param PHPUnit_Framework_TestSuite $suite 150 */ 151 public function startTestSuite(PHPUnit_Framework_TestSuite $suite) 152 { 153 $this->suites++; 154 } 155 156 /** 157 * A test suite ended. 158 * 159 * @param PHPUnit_Framework_TestSuite $suite 160 */ 161 public function endTestSuite(PHPUnit_Framework_TestSuite $suite) 162 { 163 $this->suites--; 164 165 if (0 === $this->suites && $this->hasSlowTests()) { 166 arsort($this->slow); // Sort longest running tests to the top 167 168 $this->renderHeader(); 169 $this->renderBody(); 170 $this->renderFooter(); 171 } 172 } 173 174 /** 175 * Whether the given test execution time is considered slow. 176 * 177 * @param int $time Test execution time in milliseconds 178 * @param int $slowThreshold Test execution time at which a test should be considered slow (milliseconds) 179 * @return bool 180 */ 181 protected function isSlow($time, $slowThreshold) 182 { 183 return $time >= $slowThreshold; 184 } 185 186 /** 187 * Stores a test as slow. 188 * 189 * @param PHPUnit_Framework_TestCase $test 190 * @param int $time Test execution time in milliseconds 191 */ 192 protected function addSlowTest(PHPUnit_Framework_TestCase $test, $time) 193 { 194 $label = $this->makeLabel($test); 195 196 $this->slow[$label] = $time; 197 } 198 199 /** 200 * Whether at least one test has been considered slow. 201 * 202 * @return bool 203 */ 204 protected function hasSlowTests() 205 { 206 return !empty($this->slow); 207 } 208 209 /** 210 * Convert PHPUnit's reported test time (microseconds) to milliseconds. 211 * 212 * @param float $time 213 * @return int 214 */ 215 protected function toMilliseconds($time) 216 { 217 return (int) round($time * 1000); 218 } 219 220 /** 221 * Label for describing a test. 222 * 223 * @param PHPUnit_Framework_TestCase $test 224 * @return string 225 */ 226 protected function makeLabel(PHPUnit_Framework_TestCase $test) 227 { 228 return sprintf('%s:%s', get_class($test), $test->getName()); 229 } 230 231 /** 232 * Calculate number of slow tests to report about. 233 * 234 * @return int 235 */ 236 protected function getReportLength() 237 { 238 return min(count($this->slow), $this->reportLength); 239 } 240 241 /** 242 * Find how many slow tests occurred that won't be shown due to list length. 243 * 244 * @return int Number of hidden slow tests 245 */ 246 protected function getHiddenCount() 247 { 248 $total = count($this->slow); 249 $showing = $this->getReportLength($this->slow); 250 251 $hidden = 0; 252 if ($total > $showing) { 253 $hidden = $total - $showing; 254 } 255 256 return $hidden; 257 } 258 259 /** 260 * Renders slow test report header. 261 */ 262 protected function renderHeader() 263 { 264 echo sprintf("\n\nYou should really fix these slow tests (>%sms)...\n", $this->slowThreshold); 265 } 266 267 /** 268 * Renders slow test report body. 269 */ 270 protected function renderBody() 271 { 272 $slowTests = $this->slow; 273 274 $length = $this->getReportLength($slowTests); 275 for ($i = 1; $i <= $length; ++$i) { 276 $label = key($slowTests); 277 $time = array_shift($slowTests); 278 279 echo sprintf(" %s. %sms to run %s\n", $i, $time, $label); 280 } 281 } 282 283 /** 284 * Renders slow test report footer. 285 */ 286 protected function renderFooter() 287 { 288 if ($hidden = $this->getHiddenCount($this->slow)) { 289 echo sprintf("...and there %s %s more above your threshold hidden from view", $hidden == 1 ? 'is' : 'are', $hidden); 290 } 291 } 292 293 /** 294 * Populate options into class internals. 295 * 296 * @param array $options 297 */ 298 protected function loadOptions(array $options) 299 { 300 $this->slowThreshold = isset($options['slowThreshold']) ? $options['slowThreshold'] : 500; 301 $this->reportLength = isset($options['reportLength']) ? $options['reportLength'] : 10; 302 } 303 304 /** 305 * Get slow test threshold for given test. A TestCase can override the 306 * suite-wide slow threshold by using the annotation @slowThreshold with 307 * the threshold value in milliseconds. 308 * 309 * The following test will only be considered slow when its execution time 310 * reaches 5000ms (5 seconds): 311 * 312 * <code> 313 * @slowThreshold 5000 314 * public function testLongRunningProcess() {} 315 * </code> 316 * 317 * @param PHPUnit_Framework_TestCase $test 318 * @return int 319 */ 320 protected function getSlowThreshold(PHPUnit_Framework_TestCase $test) 321 { 322 $ann = $test->getAnnotations(); 323 324 return isset($ann['method']['slowThreshold'][0]) ? $ann['method']['slowThreshold'][0] : $this->slowThreshold; 325 } 7 class SpeedTrapListener implements PHPUnit_Framework_TestListener { 8 9 /** 10 * Internal tracking for test suites. 11 * 12 * Increments as more suites are run, then decremented as they finish. All 13 * suites have been run when returns to 0. 14 * 15 * @var integer 16 */ 17 protected $suites = 0; 18 19 /** 20 * Time in milliseconds at which a test will be considered "slow" and be 21 * reported by this listener. 22 * 23 * @var int 24 */ 25 protected $slowThreshold; 26 27 /** 28 * Number of tests to report on for slowness. 29 * 30 * @var int 31 */ 32 protected $reportLength; 33 34 /** 35 * Collection of slow tests. 36 * 37 * @var array 38 */ 39 protected $slow = array(); 40 41 /** 42 * Construct a new instance. 43 * 44 * @param array $options 45 */ 46 public function __construct( array $options = array() ) { 47 $this->loadOptions( $options ); 48 } 49 50 /** 51 * An error occurred. 52 * 53 * @param PHPUnit_Framework_Test $test 54 * @param Exception $e 55 * @param float $time 56 */ 57 public function addError( PHPUnit_Framework_Test $test, Exception $e, $time ) { 58 } 59 60 /** 61 * A warning occurred. 62 * 63 * @param PHPUnit_Framework_Test $test 64 * @param PHPUnit_Framework_Warning $e 65 * @param float $time 66 * @since Method available since Release 5.1.0 67 */ 68 public function addWarning( PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time ) { 69 } 70 71 /** 72 * A failure occurred. 73 * 74 * @param PHPUnit_Framework_Test $test 75 * @param PHPUnit_Framework_AssertionFailedError $e 76 * @param float $time 77 */ 78 public function addFailure( PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time ) { 79 } 80 81 /** 82 * Incomplete test. 83 * 84 * @param PHPUnit_Framework_Test $test 85 * @param Exception $e 86 * @param float $time 87 */ 88 public function addIncompleteTest( PHPUnit_Framework_Test $test, Exception $e, $time ) { 89 } 90 91 /** 92 * Risky test. 93 * 94 * @param PHPUnit_Framework_Test $test 95 * @param Exception $e 96 * @param float $time 97 * @since Method available since Release 4.0.0 98 */ 99 public function addRiskyTest( PHPUnit_Framework_Test $test, Exception $e, $time ) { 100 } 101 102 /** 103 * Skipped test. 104 * 105 * @param PHPUnit_Framework_Test $test 106 * @param Exception $e 107 * @param float $time 108 */ 109 public function addSkippedTest( PHPUnit_Framework_Test $test, Exception $e, $time ) { 110 } 111 112 /** 113 * A test started. 114 * 115 * @param PHPUnit_Framework_Test $test 116 */ 117 public function startTest( PHPUnit_Framework_Test $test ) { 118 } 119 120 /** 121 * A test ended. 122 * 123 * @param PHPUnit_Framework_Test $test 124 * @param float $time 125 */ 126 public function endTest( PHPUnit_Framework_Test $test, $time ) { 127 if ( ! $test instanceof PHPUnit_Framework_TestCase ) { 128 return; 129 } 130 131 $time = $this->toMilliseconds( $time ); 132 $threshold = $this->getSlowThreshold( $test ); 133 134 if ( $this->isSlow( $time, $threshold ) ) { 135 $this->addSlowTest( $test, $time ); 136 } 137 } 138 139 /** 140 * A test suite started. 141 * 142 * @param PHPUnit_Framework_TestSuite $suite 143 */ 144 public function startTestSuite( PHPUnit_Framework_TestSuite $suite ) { 145 $this->suites++; 146 } 147 148 /** 149 * A test suite ended. 150 * 151 * @param PHPUnit_Framework_TestSuite $suite 152 */ 153 public function endTestSuite( PHPUnit_Framework_TestSuite $suite ) { 154 $this->suites--; 155 156 if ( 0 === $this->suites && $this->hasSlowTests() ) { 157 arsort( $this->slow ); // Sort longest running tests to the top 158 159 $this->renderHeader(); 160 $this->renderBody(); 161 $this->renderFooter(); 162 } 163 } 164 165 /** 166 * Whether the given test execution time is considered slow. 167 * 168 * @param int $time Test execution time in milliseconds 169 * @param int $slowThreshold Test execution time at which a test should be considered slow (milliseconds) 170 * @return bool 171 */ 172 protected function isSlow( $time, $slowThreshold ) { 173 return $time >= $slowThreshold; 174 } 175 176 /** 177 * Stores a test as slow. 178 * 179 * @param PHPUnit_Framework_TestCase $test 180 * @param int $time Test execution time in milliseconds 181 */ 182 protected function addSlowTest( PHPUnit_Framework_TestCase $test, $time ) { 183 $label = $this->makeLabel( $test ); 184 185 $this->slow[ $label ] = $time; 186 } 187 188 /** 189 * Whether at least one test has been considered slow. 190 * 191 * @return bool 192 */ 193 protected function hasSlowTests() { 194 return ! empty( $this->slow ); 195 } 196 197 /** 198 * Convert PHPUnit's reported test time (microseconds) to milliseconds. 199 * 200 * @param float $time 201 * @return int 202 */ 203 protected function toMilliseconds( $time ) { 204 return (int) round( $time * 1000 ); 205 } 206 207 /** 208 * Label for describing a test. 209 * 210 * @param PHPUnit_Framework_TestCase $test 211 * @return string 212 */ 213 protected function makeLabel( PHPUnit_Framework_TestCase $test ) { 214 return sprintf( '%s:%s', get_class( $test ), $test->getName() ); 215 } 216 217 /** 218 * Calculate number of slow tests to report about. 219 * 220 * @return int 221 */ 222 protected function getReportLength() { 223 return min( count( $this->slow ), $this->reportLength ); 224 } 225 226 /** 227 * Find how many slow tests occurred that won't be shown due to list length. 228 * 229 * @return int Number of hidden slow tests 230 */ 231 protected function getHiddenCount() { 232 $total = count( $this->slow ); 233 $showing = $this->getReportLength( $this->slow ); 234 235 $hidden = 0; 236 if ( $total > $showing ) { 237 $hidden = $total - $showing; 238 } 239 240 return $hidden; 241 } 242 243 /** 244 * Renders slow test report header. 245 */ 246 protected function renderHeader() { 247 echo sprintf( "\n\nYou should really fix these slow tests (>%sms)...\n", $this->slowThreshold ); 248 } 249 250 /** 251 * Renders slow test report body. 252 */ 253 protected function renderBody() { 254 $slowTests = $this->slow; 255 256 $length = $this->getReportLength( $slowTests ); 257 for ( $i = 1; $i <= $length; ++$i ) { 258 $label = key( $slowTests ); 259 $time = array_shift( $slowTests ); 260 261 echo sprintf( " %s. %sms to run %s\n", $i, $time, $label ); 262 } 263 } 264 265 /** 266 * Renders slow test report footer. 267 */ 268 protected function renderFooter() { 269 if ( $hidden = $this->getHiddenCount( $this->slow ) ) { 270 echo sprintf( '...and there %s %s more above your threshold hidden from view', $hidden == 1 ? 'is' : 'are', $hidden ); 271 } 272 } 273 274 /** 275 * Populate options into class internals. 276 * 277 * @param array $options 278 */ 279 protected function loadOptions( array $options ) { 280 $this->slowThreshold = isset( $options['slowThreshold'] ) ? $options['slowThreshold'] : 500; 281 $this->reportLength = isset( $options['reportLength'] ) ? $options['reportLength'] : 10; 282 } 283 284 /** 285 * Get slow test threshold for given test. A TestCase can override the 286 * suite-wide slow threshold by using the annotation @slowThreshold with 287 * the threshold value in milliseconds. 288 * 289 * The following test will only be considered slow when its execution time 290 * reaches 5000ms (5 seconds): 291 * 292 * <code> 293 * 294 * @slowThreshold 5000 295 * public function testLongRunningProcess() {} 296 * </code> 297 * 298 * @param PHPUnit_Framework_TestCase $test 299 * @return int 300 */ 301 protected function getSlowThreshold( PHPUnit_Framework_TestCase $test ) { 302 $ann = $test->getAnnotations(); 303 304 return isset( $ann['method']['slowThreshold'][0] ) ? $ann['method']['slowThreshold'][0] : $this->slowThreshold; 305 } 326 306 }
Note: See TracChangeset
for help on using the changeset viewer.