[ Index ] |
PHP Cross Reference of BBPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * A PHPUnit TestListener that exposes your slowest running tests by outputting 5 * results directly to the console. 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 } 326 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sat Dec 21 01:00:52 2024 | Cross-referenced by PHPXref 0.7.1 |