[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

/tests/phpunit/includes/ -> speed-trap-listener.php (source)

   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  }


Generated: Fri Mar 29 01:00:56 2024 Cross-referenced by PHPXref 0.7.1