]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Framework/TestResult.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / Framework / TestResult.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @category   Testing
38  * @package    PHPUnit
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
43  * @link       http://www.phpunit.de/
44  * @since      File available since Release 2.0.0
45  */
46
47 require_once 'PHPUnit/Framework.php';
48 require_once 'PHPUnit/Util/CodeCoverage.php';
49 require_once 'PHPUnit/Util/ErrorHandler.php';
50 require_once 'PHPUnit/Util/Filter.php';
51 require_once 'PHPUnit/Util/Printer.php';
52 require_once 'PHPUnit/Util/Test.php';
53 require_once 'PHPUnit/Util/Timer.php';
54
55 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
56
57 if (!class_exists('PHPUnit_Framework_TestResult', FALSE)) {
58
59 /**
60  * A TestResult collects the results of executing a test case.
61  *
62  * @category   Testing
63  * @package    PHPUnit
64  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
65  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
66  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
67  * @version    Release: 3.3.17
68  * @link       http://www.phpunit.de/
69  * @since      Class available since Release 2.0.0
70  */
71 class PHPUnit_Framework_TestResult implements Countable
72 {
73     protected static $xdebugLoaded = NULL;
74     protected static $useXdebug = NULL;
75
76     /**
77      * @var    array
78      */
79     protected $errors = array();
80
81     /**
82      * @var    array
83      */
84     protected $failures = array();
85
86     /**
87      * @var    array
88      */
89     protected $notImplemented = array();
90
91     /**
92      * @var    array
93      */
94     protected $skipped = array();
95
96     /**
97      * @var    array
98      */
99     protected $listeners = array();
100
101     /**
102      * @var    integer
103      */
104     protected $runTests = 0;
105
106     /**
107      * @var    float
108      */
109     protected $time = 0;
110
111     /**
112      * @var    PHPUnit_Framework_TestSuite
113      */
114     protected $topTestSuite = NULL;
115
116     /**
117      * Code Coverage information provided by Xdebug.
118      *
119      * @var    array
120      */
121     protected $codeCoverageInformation = array();
122
123     /**
124      * @var    boolean
125      */
126     protected $collectCodeCoverageInformation = FALSE;
127
128     /**
129      * @var    boolean
130      */
131     protected $convertErrorsToExceptions = TRUE;
132
133     /**
134      * @var    boolean
135      */
136     protected $stop = FALSE;
137
138     /**
139      * @var    boolean
140      */
141     protected $stopOnFailure = FALSE;
142
143     /**
144      * @var    boolean
145      */
146     protected $lastTestFailed = FALSE;
147
148     /**
149      * Registers a TestListener.
150      *
151      * @param  PHPUnit_Framework_TestListener
152      */
153     public function addListener(PHPUnit_Framework_TestListener $listener)
154     {
155         $this->listeners[] = $listener;
156     }
157
158     /**
159      * Unregisters a TestListener.
160      *
161      * @param  PHPUnit_Framework_TestListener $listener
162      */
163     public function removeListener(PHPUnit_Framework_TestListener $listener)
164     {
165         foreach ($this->listeners as $key => $_listener) {
166             if ($listener === $_listener) {
167                 unset($this->listeners[$key]);
168             }
169         }
170     }
171
172     /**
173      * Flushes all flushable TestListeners.
174      *
175      * @since  Method available since Release 3.0.0
176      */
177     public function flushListeners()
178     {
179         foreach ($this->listeners as $listener) {
180             if ($listener instanceof PHPUnit_Util_Printer) {
181                 $listener->flush();
182             }
183         }
184     }
185
186     /**
187      * Adds an error to the list of errors.
188      * The passed in exception caused the error.
189      *
190      * @param  PHPUnit_Framework_Test $test
191      * @param  Exception              $e
192      * @param  float                  $time
193      */
194     public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
195     {
196         if ($e instanceof PHPUnit_Framework_IncompleteTest) {
197             $this->notImplemented[] = new PHPUnit_Framework_TestFailure($test, $e);
198             $notifyMethod           = 'addIncompleteTest';
199         }
200
201         else if ($e instanceof PHPUnit_Framework_SkippedTest) {
202             $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e);
203             $notifyMethod    = 'addSkippedTest';
204         }
205
206         else {
207             $this->errors[] = new PHPUnit_Framework_TestFailure($test, $e);
208             $notifyMethod   = 'addError';
209
210             if ($this->stopOnFailure) {
211                 $this->stop();
212             }
213         }
214
215         foreach ($this->listeners as $listener) {
216             $listener->$notifyMethod($test, $e, $time);
217         }
218
219         $this->lastTestFailed = TRUE;
220         $this->time          += $time;
221     }
222
223     /**
224      * Adds a failure to the list of failures.
225      * The passed in exception caused the failure.
226      *
227      * @param  PHPUnit_Framework_Test                 $test
228      * @param  PHPUnit_Framework_AssertionFailedError $e
229      * @param  float                                  $time
230      */
231     public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
232     {
233         if ($e instanceof PHPUnit_Framework_IncompleteTest) {
234             $this->notImplemented[] = new PHPUnit_Framework_TestFailure($test, $e);
235             $notifyMethod           = 'addIncompleteTest';
236         }
237
238         else if ($e instanceof PHPUnit_Framework_SkippedTest) {
239             $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e);
240             $notifyMethod    = 'addSkippedTest';
241         }
242
243         else {
244             $this->failures[] = new PHPUnit_Framework_TestFailure($test, $e);
245             $notifyMethod     = 'addFailure';
246
247             if ($this->stopOnFailure) {
248                 $this->stop();
249             }
250         }
251
252         foreach ($this->listeners as $listener) {
253             $listener->$notifyMethod($test, $e, $time);
254         }
255
256         $this->lastTestFailed = TRUE;
257         $this->time          += $time;
258     }
259
260     /**
261      * Informs the result that a testsuite will be started.
262      *
263      * @param  PHPUnit_Framework_TestSuite $suite
264      * @since  Method available since Release 2.2.0
265      */
266     public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
267     {
268         if ($this->topTestSuite === NULL) {
269             $this->topTestSuite = $suite;
270         }
271
272         foreach ($this->listeners as $listener) {
273             $listener->startTestSuite($suite);
274         }
275     }
276
277     /**
278      * Informs the result that a testsuite was completed.
279      *
280      * @param  PHPUnit_Framework_TestSuite $suite
281      * @since  Method available since Release 2.2.0
282      */
283     public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
284     {
285         foreach ($this->listeners as $listener) {
286             $listener->endTestSuite($suite);
287         }
288     }
289
290     /**
291      * Informs the result that a test will be started.
292      *
293      * @param  PHPUnit_Framework_Test $test
294      */
295     public function startTest(PHPUnit_Framework_Test $test)
296     {
297         $this->lastTestFailed = FALSE;
298         $this->runTests      += count($test);
299
300         foreach ($this->listeners as $listener) {
301             $listener->startTest($test);
302         }
303     }
304
305     /**
306      * Informs the result that a test was completed.
307      *
308      * @param  PHPUnit_Framework_Test $test
309      * @param  float                  $time
310      */
311     public function endTest(PHPUnit_Framework_Test $test, $time)
312     {
313         foreach ($this->listeners as $listener) {
314             $listener->endTest($test, $time);
315         }
316
317         if (!$this->lastTestFailed) {
318             $this->time += $time;
319         }
320     }
321
322     /**
323      * Returns TRUE if no incomplete test occured.
324      *
325      * @return boolean
326      */
327     public function allCompletlyImplemented()
328     {
329         return $this->notImplementedCount() == 0;
330     }
331
332     /**
333      * Gets the number of incomplete tests.
334      *
335      * @return integer
336      */
337     public function notImplementedCount()
338     {
339         return count($this->notImplemented);
340     }
341
342     /**
343      * Returns an Enumeration for the incomplete tests.
344      *
345      * @return array
346      */
347     public function notImplemented()
348     {
349         return $this->notImplemented;
350     }
351
352     /**
353      * Returns TRUE if no test has been skipped.
354      *
355      * @return boolean
356      * @since  Method available since Release 3.0.0
357      */
358     public function noneSkipped()
359     {
360         return $this->skippedCount() == 0;
361     }
362
363     /**
364      * Gets the number of skipped tests.
365      *
366      * @return integer
367      * @since  Method available since Release 3.0.0
368      */
369     public function skippedCount()
370     {
371         return count($this->skipped);
372     }
373
374     /**
375      * Returns an Enumeration for the skipped tests.
376      *
377      * @return array
378      * @since  Method available since Release 3.0.0
379      */
380     public function skipped()
381     {
382         return $this->skipped;
383     }
384
385     /**
386      * Gets the number of detected errors.
387      *
388      * @return integer
389      */
390     public function errorCount()
391     {
392         return count($this->errors);
393     }
394
395     /**
396      * Returns an Enumeration for the errors.
397      *
398      * @return array
399      */
400     public function errors()
401     {
402         return $this->errors;
403     }
404
405     /**
406      * Gets the number of detected failures.
407      *
408      * @return integer
409      */
410     public function failureCount()
411     {
412         return count($this->failures);
413     }
414
415     /**
416      * Returns an Enumeration for the failures.
417      *
418      * @return array
419      */
420     public function failures()
421     {
422         return $this->failures;
423     }
424
425     /**
426      * Returns the (top) test suite.
427      *
428      * @return PHPUnit_Framework_TestSuite
429      * @since  Method available since Release 3.0.0
430      */
431     public function topTestSuite()
432     {
433         return $this->topTestSuite;
434     }
435
436     /**
437      * Enables or disables the collection of Code Coverage information.
438      *
439      * @param  boolean $flag
440      * @throws InvalidArgumentException
441      * @since  Method available since Release 2.3.0
442      */
443     public function collectCodeCoverageInformation($flag)
444     {
445         if (is_bool($flag)) {
446             $this->collectCodeCoverageInformation = $flag;
447         } else {
448             throw new InvalidArgumentException;
449         }
450     }
451
452     /**
453      * Returns whether code coverage information should be collected.
454      *
455      * @return boolean If code coverage should be collected
456      * @since  Method available since Release 3.2.0
457      */
458     public function getCollectCodeCoverageInformation()
459     {
460         return $this->collectCodeCoverageInformation;
461     }
462
463     /**
464      * Appends code coverage information to the test
465      *
466      * @param PHPUnit_Framework_Test $test
467      * @param array                  $data
468      * @since Method available since Release 3.2.0
469      */
470     public function appendCodeCoverageInformation(PHPUnit_Framework_Test $test, $data)
471     {
472         $deadCode       = array();
473         $executableCode = array();
474
475         foreach (array_keys($data) as $file) {
476             if (PHPUnit_Util_Filter::isFiltered($file, FALSE)) {
477                 unset($data[$file]);
478             }
479         }
480
481         $newFilesToCollect = array_diff_key($data, PHPUnit_Util_Filter::getCoveredFiles());
482
483         if (count($newFilesToCollect) > 0) {
484             $deadCode       = PHPUnit_Util_CodeCoverage::getDeadLines($newFilesToCollect);
485             $executableCode = PHPUnit_Util_CodeCoverage::getExecutableLines($newFilesToCollect);
486
487             foreach (array_keys($newFilesToCollect) as $file) {
488                 PHPUnit_Util_Filter::addCoveredFile($file);
489             }
490
491             unset($newFilesToCollect);
492         }
493
494         if ($test instanceof PHPUnit_Framework_TestCase) {
495             $linesToBeCovered = PHPUnit_Util_Test::getLinesToBeCovered(
496               get_class($test), $test->getName()
497             );
498
499             if (!empty($linesToBeCovered)) {
500                 $data = array_intersect_key($data, $linesToBeCovered);
501
502                 foreach (array_keys($data) as $file) {
503                     $data[$file] = array_intersect_key($data[$file], array_flip($linesToBeCovered[$file]));
504                 }
505             }
506         }
507
508         $executed = PHPUnit_Util_CodeCoverage::getExecutedLines($data);
509         unset($data);
510
511         $this->codeCoverageInformation[] = array(
512           'test'       => $test,
513           'files'      => $executed,
514           'dead'       => $deadCode,
515           'executable' => $executableCode,
516         );
517     }
518
519     /**
520      * Returns Code Coverage data per test case.
521      *
522      * Format of the result array:
523      *
524      * <code>
525      * array(
526      *   array(
527      *     'test'  => PHPUnit_Framework_Test
528      *     'files' => array(
529      *       "/tested/code.php" => array(
530      *         linenumber => flag
531      *       )
532      *     )
533      *   )
534      * )
535      * </code>
536      *
537      * flag < 0: Line is executable but was not executed.
538      * flag > 0: Line was executed.
539      *
540      * @param  boolean $filterTests
541      * @return array
542      */
543     public function getCodeCoverageInformation($filterTests = TRUE)
544     {
545         return PHPUnit_Util_Filter::getFilteredCodeCoverage(
546           $this->codeCoverageInformation, $filterTests
547         );
548     }
549
550     /**
551      * Returns unfiltered Code Coverage data per test case.
552      * Returns data in the same form as getCodeCoverageInformation().
553      *
554      * @return array
555      */
556     public function getUncoveredWhitelistFiles()
557     {
558         list(, $missing) = PHPUnit_Util_Filter::getFileCodeCoverageDisposition(
559           $this->codeCoverageInformation
560         );
561
562         return $missing;
563     }
564
565     /**
566      * Runs a TestCase.
567      *
568      * @param  PHPUnit_Framework_Test $test
569      */
570     public function run(PHPUnit_Framework_Test $test)
571     {
572         PHPUnit_Framework_Assert::resetCount();
573
574         $error   = FALSE;
575         $failure = FALSE;
576
577         $this->startTest($test);
578
579         $errorHandlerSet = FALSE;
580
581         if ($this->convertErrorsToExceptions) {
582             $oldErrorHandler = set_error_handler(
583               array('PHPUnit_Util_ErrorHandler', 'handleError'), E_ALL | E_STRICT
584             );
585
586             if ($oldErrorHandler === NULL) {
587                 $errorHandlerSet = TRUE;
588             } else {
589                 restore_error_handler();
590             }
591         }
592
593         if (self::$xdebugLoaded === NULL) {
594             self::$xdebugLoaded = extension_loaded('xdebug');
595             self::$useXdebug = self::$xdebugLoaded;
596         }
597
598         $useXdebug = self::$useXdebug && $this->collectCodeCoverageInformation && !$test instanceof PHPUnit_Extensions_SeleniumTestCase;
599
600         if ($useXdebug) {
601             xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
602         }
603
604         PHPUnit_Util_Timer::start();
605
606         try {
607             $test->runBare();
608         }
609
610         catch (PHPUnit_Framework_AssertionFailedError $e) {
611             $failure = TRUE;
612         }
613
614         catch (Exception $e) {
615             $error = TRUE;
616         }
617
618         $time = PHPUnit_Util_Timer::stop();
619
620         if ($useXdebug) {
621             $codeCoverage = xdebug_get_code_coverage();
622             xdebug_stop_code_coverage();
623
624             $this->appendCodeCoverageInformation(
625               $test, $codeCoverage
626             );
627         }
628
629         if ($errorHandlerSet === TRUE) {
630             restore_error_handler();
631         }
632
633         $test->addToAssertionCount(PHPUnit_Framework_Assert::getCount());
634
635         if ($error === TRUE) {
636             $this->addError($test, $e, $time);
637         }
638
639         else if ($failure === TRUE) {
640             $this->addFailure($test, $e, $time);
641         }
642
643         $this->endTest($test, $time);
644     }
645
646     /**
647      * Gets the number of run tests.
648      *
649      * @return integer
650      */
651     public function count()
652     {
653         return $this->runTests;
654     }
655
656     /**
657      * Checks whether the test run should stop.
658      *
659      * @return boolean
660      */
661     public function shouldStop()
662     {
663         return $this->stop;
664     }
665
666     /**
667      * Marks that the test run should stop.
668      *
669      */
670     public function stop()
671     {
672         $this->stop = TRUE;
673     }
674
675     /**
676      * Enables or disables the error-to-exception conversion.
677      *
678      * @param  boolean $flag
679      * @throws InvalidArgumentException
680      * @since  Method available since Release 3.2.14
681      */
682     public function convertErrorsToExceptions($flag)
683     {
684         if (is_bool($flag)) {
685             $this->convertErrorsToExceptions = $flag;
686         } else {
687             throw new InvalidArgumentException;
688         }
689     }
690
691     /**
692      * Enables or disables the stopping when a failure or error occurs.
693      *
694      * @param  boolean $flag
695      * @throws InvalidArgumentException
696      * @since  Method available since Release 3.1.0
697      */
698     public function stopOnFailure($flag)
699     {
700         if (is_bool($flag)) {
701             $this->stopOnFailure = $flag;
702         } else {
703             throw new InvalidArgumentException;
704         }
705     }
706
707     /**
708      * Returns the time spent running the tests.
709      *
710      * @return float
711      */
712     public function time()
713     {
714         return $this->time;
715     }
716
717     /**
718      * Returns whether the entire test was successful or not.
719      *
720      * @return boolean
721      */
722     public function wasSuccessful()
723     {
724         return empty($this->errors) && empty($this->failures);
725     }
726 }
727
728 }
729 ?>