timer = new Benchmark_Timer(); $this->hasTimer = true; } else { $this->hasTimer = false; } $this->suiteResults = array( 'suites' => array(), // array of suites run 'hasTimer' => $this->hasTimer, // availability of PEAR Benchmark_Timer 'totalTests' => 0 // total number of tests run ); } /** * Returns the suite results * * @access public * @return array Suite results */ public function getSuiteResults() { return $this->suiteResults; } /** * Sets up the container for result details of the current test suite when * each suite is first run * * @access public * @param obj PHPUnit2_Framework_TestSuite, the suite that is been run * @return void */ public function startTestSuite( PHPUnit_Framework_TestSuite $suite) { if(strlen($suite->getName())) { $this->currentSuite = array( 'suite' => $suite, // the test suite 'tests' => array(), // the tests in the suite 'errors' => 0, // number of tests with errors 'failures' => 0, // number of tests which failed 'incomplete' => 0); // number of tests that were not completed correctly } } /** * Sets up the container for result details of the current test when each * test is first run * * @access public * @param obj PHPUnit_Framework_Test, the test that is being run * @return void */ public function startTest(PHPUnit_Framework_Test $test) { $this->startTestTime = microtime(true); if($test instanceof PHPUnit_Framework_TestCase) { $this->currentTest = array( 'name' => preg_replace('(\(.*\))', '', $test->toString()), // the name of the test (without the suite name) 'timeElapsed' => 0, // execution time of the test 'status' => TEST_SUCCESS, // status of the test execution 'message' => '', // user message of test result 'exception' => NULL, // original caught exception thrown by test upon failure/error 'uid' => md5(microtime()) // a unique ID for this test (used for identification purposes in results) ); if($this->hasTimer) $this->timer->start(); } } /** * Adds the failure detail to the current test and increases the failure * count for the current suite * * @access public * @param obj PHPUnit_Framework_Test, current test that is being run * @param obj PHPUnit_Framework_AssertationFailedError, PHPUnit error * @return void */ public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) { $this->currentSuite['failures']++; $this->currentTest['status'] = TEST_FAILURE; $this->currentTest['message'] = $e->toString(); $this->currentTest['exception'] = $this->getTestException($test, $e); $this->currentTest['trace'] = $e->getTrace(); } /** * Adds the error detail to the current test and increases the error * count for the current suite * * @access public * @param obj PHPUnit_Framework_Test, current test that is being run * @param obj PHPUnit_Framework_AssertationFailedError, PHPUnit error * @return void */ public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) { $this->currentSuite['errors']++; $this->currentTest['status'] = TEST_ERROR; $this->currentTest['message'] = $e->getMessage(); $this->currentTest['exception'] = $this->getTestException($test, $e); $this->currentTest['trace'] = $e->getTrace(); } /** * Adds the test incomplete detail to the current test and increases the incomplete * count for the current suite * * @access public * @param obj PHPUnit_Framework_Test, current test that is being run * @param obj PHPUnit_Framework_AssertationFailedError, PHPUnit error * @return void */ public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) { $this->currentSuite['incomplete']++; $this->currentTest['status'] = TEST_INCOMPLETE; $this->currentTest['message'] = $e->toString(); $this->currentTest['exception'] = $this->getTestException($test, $e); $this->currentTest['trace'] = $e->getTrace(); } /** * Not used * * @param PHPUnit_Framework_Test $test * @param unknown_type $time */ public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) { // not implemented } /** * Upon completion of a test, records the execution time (if available) and adds the test to * the tests performed in the current suite. * * @access public * @param obj PHPUnit_Framework_Test, current test that is being run * @return void */ public function endTest( PHPUnit_Framework_Test $test, $time) { $testDuration = microtime(true) - $this->startTestTime; $this->testSpeeds[$this->currentSuite['suite']->getName() . '.' . $this->currentTest['name']] = $testDuration; if($this->hasTimer) { $this->timer->stop(); $this->currentTest['timeElapsed'] = $this->timer->timeElapsed(); } array_push($this->currentSuite['tests'], $this->currentTest); if(method_exists($test, 'getActualOutput')) { $output = $test->getActualOutput(); if($output) echo "\nOutput:\n$output"; } } /** * Upon completion of a test suite adds the suite to the suties performed * * @access public * @param obj PHPUnit_Framework_TestSuite, current suite that is being run * @return void */ public function endTestSuite( PHPUnit_Framework_TestSuite $suite) { if(strlen($suite->getName())) { array_push($this->suiteResults['suites'], $this->currentSuite); } } /** * Trys to get the original exception thrown by the test on failure/error * to enable us to give a bit more detail about the failure/error * * @access private * @param obj PHPUnit_Framework_Test, current test that is being run * @param obj PHPUnit_Framework_AssertationFailedError, PHPUnit error * @return array */ private function getTestException(PHPUnit_Framework_Test $test, Exception $e) { // get the name of the testFile from the test $testName = ereg_replace('(.*)\((.*[^)])\)', '\\2', $test->toString()); $trace = $e->getTrace(); // loop through the exception trace to find the original exception for($i = 0; $i < count($trace); $i++) { if(array_key_exists('file', $trace[$i])) { if(stristr($trace[$i]['file'], $testName.'.php') != false) return $trace[$i]; } if(array_key_exists('file:protected', $trace[$i])) { if(stristr($trace[$i]['file:protected'], $testName.'.php') != false) return $trace[$i]; } } } /** * Display error bar if it exists */ public function writeResults() { $passCount = 0; $failCount = 0; $testCount = 0; $errorCount = 0; foreach($this->suiteResults['suites'] as $suite) { foreach($suite['tests'] as $test) { $testCount++; ($test['status'] == 1) ? $passCount++ : $failCount++; if ($test['status'] != 1) { echo "
".htmlentities($test['message'], ENT_COMPAT, 'UTF-8')."