]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/TextUI/Command.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / TextUI / Command.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 3.0.0
45  */
46
47 require_once 'PHPUnit/TextUI/TestRunner.php';
48 require_once 'PHPUnit/Util/Configuration.php';
49 require_once 'PHPUnit/Util/Fileloader.php';
50 require_once 'PHPUnit/Util/Filter.php';
51 require_once 'PHPUnit/Util/Getopt.php';
52
53 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
54
55 /**
56  * A TestRunner for the Command Line Interface (CLI)
57  * PHP SAPI Module.
58  *
59  * @category   Testing
60  * @package    PHPUnit
61  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
62  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
63  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
64  * @version    Release: 3.3.17
65  * @link       http://www.phpunit.de/
66  * @since      Class available since Release 3.0.0
67  */
68 class PHPUnit_TextUI_Command
69 {
70     /**
71      */
72     public static function main($exit = TRUE)
73     {
74         if ( !extension_loaded('dom') ) 
75             self::showMissingDependency('The dom extension is not loaded.');
76             
77         $arguments = self::handleArguments();
78         $runner    = new PHPUnit_TextUI_TestRunner;
79
80         if (is_object($arguments['test']) && $arguments['test'] instanceof PHPUnit_Framework_Test) {
81             $suite = $arguments['test'];
82         } else {
83             $suite = $runner->getTest(
84               $arguments['test'],
85               $arguments['testFile'],
86               $arguments['syntaxCheck']
87             );
88         }
89
90         if ($suite->testAt(0) instanceof PHPUnit_Framework_Warning &&
91             strpos($suite->testAt(0)->getMessage(), 'No tests found in class') !== FALSE) {
92             $message   = $suite->testAt(0)->getMessage();
93             $start     = strpos($message, '"') + 1;
94             $end       = strpos($message, '"', $start);
95             $className = substr($message, $start, $end - $start);
96
97             require_once 'PHPUnit/Util/Skeleton/Test.php';
98
99             $skeleton = new PHPUnit_Util_Skeleton_Test(
100                 $className,
101                 $arguments['testFile']
102             );
103
104             $result = $skeleton->generate(TRUE);
105
106             if (!$result['incomplete']) {
107                 eval(str_replace(array('<?php', '?>'), '', $result['code']));
108                 $suite = new PHPUnit_Framework_TestSuite($arguments['test'] . 'Test');
109             }
110         }
111
112         if ($arguments['listGroups']) {
113             PHPUnit_TextUI_TestRunner::printVersionString();
114
115             print "Available test group(s):\n";
116
117             $groups = $suite->getGroups();
118             sort($groups);
119
120             foreach ($groups as $group) {
121                 print " - $group\n";
122             }
123
124             exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
125         }
126
127         try {
128             $result = $runner->doRun(
129               $suite,
130               $arguments
131             );
132         }
133
134         catch (Exception $e) {
135             throw new RuntimeException(
136               'Could not create and run test suite: ' . $e->getMessage()
137             );
138         }
139
140         if ($exit) {
141             if ($result->wasSuccessful()) {
142                 exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
143             }
144
145             else if ($result->errorCount() > 0) {
146                 exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT);
147             }
148
149             else {
150                 exit(PHPUnit_TextUI_TestRunner::FAILURE_EXIT);
151             }
152         }
153     }
154
155     /**
156      */
157     protected static function handleArguments()
158     {
159         $arguments = array(
160           'listGroups'  => FALSE,
161           'syntaxCheck' => TRUE
162         );
163
164         $longOptions = array(
165           'ansi',
166           'colors',
167           'bootstrap=',
168           'configuration=',
169           'coverage-html=',
170           'coverage-clover=',
171           'coverage-source=',
172           'coverage-xml=',
173           'debug',
174           'exclude-group=',
175           'filter=',
176           'group=',
177           'help',
178           'list-groups',
179           'loader=',
180           'log-graphviz=',
181           'log-json=',
182           'log-metrics=',
183           'log-pmd=',
184           'log-tap=',
185           'log-xml=',
186           'repeat=',
187           'report=',
188           'skeleton',
189           'skeleton-class',
190           'skeleton-test',
191           'stop-on-failure',
192           'story',
193           'story-html=',
194           'story-text=',
195           'tap',
196           'test-db-dsn=',
197           'test-db-log-rev=',
198           'test-db-log-prefix=',
199           'test-db-log-info=',
200           'testdox',
201           'testdox-html=',
202           'testdox-text=',
203           'no-syntax-check',
204           'verbose',
205           'version',
206           'wait'
207         );
208
209         try {
210             $options = PHPUnit_Util_Getopt::getopt(
211               $_SERVER['argv'],
212               'd:',
213               $longOptions
214             );
215         }
216
217         catch (RuntimeException $e) {
218             PHPUnit_TextUI_TestRunner::showError($e->getMessage());
219         }
220
221         if (isset($options[1][0])) {
222             $arguments['test'] = $options[1][0];
223         }
224
225         if (isset($options[1][1])) {
226             $arguments['testFile'] = $options[1][1];
227         } else {
228             $arguments['testFile'] = '';
229         }
230
231         if (isset($arguments['test']) && is_file($arguments['test'])) {
232             $arguments['testFile'] = realpath($arguments['test']);
233             $arguments['test']     = substr($arguments['test'], 0, strrpos($arguments['test'], '.'));
234         }
235
236         $skeletonClass = FALSE;
237         $skeletonTest  = FALSE;
238
239         foreach ($options[0] as $option) {
240             switch ($option[0]) {
241                 case '--ansi':
242                 case '--colors': {
243                     $arguments['colors'] = TRUE;
244                 }
245                 break;
246
247                 case '--bootstrap': {
248                     $arguments['bootstrap'] = $option[1];
249                 }
250                 break;
251
252                 case '--configuration': {
253                     $arguments['configuration'] = $option[1];
254                 }
255                 break;
256
257                 case '--coverage-clover':
258                 case '--coverage-xml': {
259                     if (extension_loaded('tokenizer') && extension_loaded('xdebug')) {
260                         $arguments['coverageClover'] = $option[1];
261                     } else {
262                         if (!extension_loaded('tokenizer')) {
263                             self::showMissingDependency('The tokenizer extension is not loaded.');
264                         } else {
265                             self::showMissingDependency('The Xdebug extension is not loaded.');
266                         }
267                     }
268                 }
269                 break;
270
271                 case '--coverage-source': {
272                     if (extension_loaded('tokenizer') && extension_loaded('xdebug')) {
273                         $arguments['coverageSource'] = $option[1];
274                     } else {
275                         if (!extension_loaded('tokenizer')) {
276                             self::showMissingDependency('The tokenizer extension is not loaded.');
277                         } else {
278                             self::showMissingDependency('The Xdebug extension is not loaded.');
279                         }
280                     }
281                 }
282                 break;
283
284                 case '--coverage-html':
285                 case '--report': {
286                     if (extension_loaded('tokenizer') && extension_loaded('xdebug')) {
287                         $arguments['reportDirectory'] = $option[1];
288                     } else {
289                         if (!extension_loaded('tokenizer')) {
290                             self::showMissingDependency('The tokenizer extension is not loaded.');
291                         } else {
292                             self::showMissingDependency('The Xdebug extension is not loaded.');
293                         }
294                     }
295                 }
296                 break;
297
298                 case 'd': {
299                     $ini = explode('=', $option[1]);
300
301                     if (isset($ini[0])) {
302                         if (isset($ini[1])) {
303                             ini_set($ini[0], $ini[1]);
304                         } else {
305                             ini_set($ini[0], TRUE);
306                         }
307                     }
308                 }
309                 break;
310
311                 case '--debug': {
312                     $arguments['debug'] = TRUE;
313                 }
314                 break;
315
316                 case '--help': {
317                     self::showHelp();
318                     exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
319                 }
320                 break;
321
322                 case '--filter': {
323                     $arguments['filter'] = $option[1];
324                 }
325                 break;
326
327                 case '--group': {
328                     $arguments['groups'] = explode(',', $option[1]);
329                 }
330                 break;
331
332                 case '--exclude-group': {
333                     $arguments['excludeGroups'] = explode(',', $option[1]);
334                 }
335                 break;
336
337                 case '--list-groups': {
338                     $arguments['listGroups'] = TRUE;
339                 }
340                 break;
341
342                 case '--loader': {
343                     self::handleLoader($option[1]);
344                 }
345                 break;
346
347                 case '--log-json': {
348                     $arguments['jsonLogfile'] = $option[1];
349                 }
350                 break;
351
352                 case '--log-graphviz': {
353                     if (PHPUnit_Util_Filesystem::fileExistsInIncludePath('Image/GraphViz.php')) {
354                         $arguments['graphvizLogfile'] = $option[1];
355                     } else {
356                         self::showMissingDependency('The Image_GraphViz package is not installed.');
357                     }
358                 }
359                 break;
360
361                 case '--log-tap': {
362                     $arguments['tapLogfile'] = $option[1];
363                 }
364                 break;
365
366                 case '--log-xml': {
367                     $arguments['xmlLogfile'] = $option[1];
368                 }
369                 break;
370
371                 case '--log-pmd': {
372                     if (extension_loaded('tokenizer') && extension_loaded('xdebug')) {
373                         $arguments['pmdXML'] = $option[1];
374                     } else {
375                         if (!extension_loaded('tokenizer')) {
376                             self::showMissingDependency('The tokenizer extension is not loaded.');
377                         } else {
378                             self::showMissingDependency('The Xdebug extension is not loaded.');
379                         }
380                     }
381                 }
382                 break;
383
384                 case '--log-metrics': {
385                     if (extension_loaded('tokenizer') && extension_loaded('xdebug')) {
386                         $arguments['metricsXML'] = $option[1];
387                     } else {
388                         if (!extension_loaded('tokenizer')) {
389                             self::showMissingDependency('The tokenizer extension is not loaded.');
390                         } else {
391                             self::showMissingDependency('The Xdebug extension is not loaded.');
392                         }
393                     }
394                 }
395                 break;
396
397                 case '--repeat': {
398                     $arguments['repeat'] = (int)$option[1];
399                 }
400                 break;
401
402                 case '--stop-on-failure': {
403                     $arguments['stopOnFailure'] = TRUE;
404                 }
405                 break;
406
407                 case '--test-db-dsn': {
408                     if (extension_loaded('pdo')) {
409                         $arguments['testDatabaseDSN'] = $option[1];
410                     } else {
411                         self::showMissingDependency('The PDO extension is not loaded.');
412                     }
413                 }
414                 break;
415
416                 case '--test-db-log-rev': {
417                     if (extension_loaded('pdo')) {
418                         $arguments['testDatabaseLogRevision'] = $option[1];
419                     } else {
420                         self::showMissingDependency('The PDO extension is not loaded.');
421                     }
422                 }
423                 break;
424
425                 case '--test-db-prefix': {
426                     if (extension_loaded('pdo')) {
427                         $arguments['testDatabasePrefix'] = $option[1];
428                     } else {
429                         self::showMissingDependency('The PDO extension is not loaded.');
430                     }
431                 }
432                 break;
433
434                 case '--test-db-log-info': {
435                     if (extension_loaded('pdo')) {
436                         $arguments['testDatabaseLogInfo'] = $option[1];
437                     } else {
438                         self::showMissingDependency('The PDO extension is not loaded.');
439                     }
440                 }
441                 break;
442
443                 case '--skeleton':
444                 case '--skeleton-test': {
445                     $skeletonTest  = TRUE;
446                     $skeletonClass = FALSE;
447                 }
448                 break;
449
450                 case '--skeleton-class': {
451                     $skeletonClass = TRUE;
452                     $skeletonTest  = FALSE;
453                 }
454                 break;
455
456                 case '--tap': {
457                     require_once 'PHPUnit/Util/Log/TAP.php';
458
459                     $arguments['printer'] = new PHPUnit_Util_Log_TAP;
460                 }
461                 break;
462
463                 case '--story': {
464                     require_once 'PHPUnit/Extensions/Story/ResultPrinter/Text.php';
465
466                     $arguments['printer'] = new PHPUnit_Extensions_Story_ResultPrinter_Text;
467                 }
468                 break;
469
470                 case '--story-html': {
471                     $arguments['storyHTMLFile'] = $option[1];
472                 }
473                 break;
474
475                 case '--story-text': {
476                     $arguments['storyTextFile'] = $option[1];
477                 }
478                 break;
479
480                 case '--testdox': {
481                     require_once 'PHPUnit/Util/TestDox/ResultPrinter/Text.php';
482
483                     $arguments['printer'] = new PHPUnit_Util_TestDox_ResultPrinter_Text;
484                 }
485                 break;
486
487                 case '--testdox-html': {
488                     $arguments['testdoxHTMLFile'] = $option[1];
489                 }
490                 break;
491
492                 case '--testdox-text': {
493                     $arguments['testdoxTextFile'] = $option[1];
494                 }
495                 break;
496
497                 case '--no-syntax-check': {
498                     $arguments['syntaxCheck'] = FALSE;
499                 }
500                 break;
501
502                 case '--verbose': {
503                     $arguments['verbose'] = TRUE;
504                 }
505                 break;
506
507                 case '--version': {
508                     PHPUnit_TextUI_TestRunner::printVersionString();
509                     exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
510                 }
511                 break;
512
513                 case '--wait': {
514                     $arguments['wait'] = TRUE;
515                 }
516                 break;
517             }
518         }
519
520         if (isset($arguments['bootstrap'])) {
521             PHPUnit_Util_Fileloader::load($arguments['bootstrap']);
522         }
523
524         if (!isset($arguments['configuration']) && file_exists('phpunit.xml')) {
525             $arguments['configuration'] = realpath('phpunit.xml');
526         }
527
528         if (isset($arguments['configuration'])) {
529             $configuration = new PHPUnit_Util_Configuration(
530               $arguments['configuration']
531             );
532
533             $configuration->handlePHPConfiguration();
534
535             if (!isset($arguments['bootstrap'])) {
536                 $phpunitConfiguration = $configuration->getPHPUnitConfiguration();
537
538                 if (isset($phpunitConfiguration['bootstrap'])) {
539                     PHPUnit_Util_Fileloader::load($phpunitConfiguration['bootstrap']);
540                 }
541             }
542
543             $browsers = $configuration->getSeleniumBrowserConfiguration();
544
545             if (!empty($browsers)) {
546                 require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
547                 PHPUnit_Extensions_SeleniumTestCase::$browsers = $browsers;
548             }
549
550             if (!isset($arguments['test'])) {
551                 $testSuite = $configuration->getTestSuiteConfiguration(
552                   $arguments['syntaxCheck']
553                 );
554
555                 if ($testSuite !== NULL) {
556                     $arguments['test'] = $testSuite;
557                 }
558             }
559         }
560
561         if (isset($arguments['test']) && is_string($arguments['test']) && substr($arguments['test'], -5, 5) == '.phpt') {
562             require_once 'PHPUnit/Extensions/PhptTestCase.php';
563
564             $test = new PHPUnit_Extensions_PhptTestCase($arguments['test']);
565
566             $arguments['test'] = new PHPUnit_Framework_TestSuite;
567             $arguments['test']->addTest($test);
568         }
569
570         if (!isset($arguments['test']) ||
571             (isset($arguments['testDatabaseLogRevision']) && !isset($arguments['testDatabaseDSN']))) {
572             self::showHelp();
573             exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT);
574         }
575
576         if ($skeletonClass || $skeletonTest) {
577             if (isset($arguments['test']) && $arguments['test'] !== FALSE) {
578                 PHPUnit_TextUI_TestRunner::printVersionString();
579
580                 if ($skeletonClass) {
581                     require_once 'PHPUnit/Util/Skeleton/Class.php';
582
583                     $class = 'PHPUnit_Util_Skeleton_Class';
584                 } else {
585                     require_once 'PHPUnit/Util/Skeleton/Test.php';
586
587                     $class = 'PHPUnit_Util_Skeleton_Test';
588                 }
589
590                 try {
591                     $args      = array();
592                     $reflector = new ReflectionClass($class);
593
594                     for ($i = 0; $i <= 3; $i++) {
595                         if (isset($options[1][$i])) {
596                             $args[] = $options[1][$i];
597                         }
598                     }
599
600                     $skeleton = $reflector->newInstanceArgs($args);
601                     $skeleton->write();
602                 }
603
604                 catch (Exception $e) {
605                     print $e->getMessage() . "\n";
606                     exit(PHPUnit_TextUI_TestRunner::FAILURE_EXIT);
607                 }
608
609                 printf(
610                   'Wrote skeleton for "%s" to "%s".' . "\n",
611                   $skeleton->getOutClassName(),
612                   $skeleton->getOutSourceFile()
613                 );
614
615                 exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
616             } else {
617                 self::showHelp();
618                 exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT);
619             }
620         }
621
622         return $arguments;
623     }
624
625     /**
626      * @param  string  $loaderName
627      */
628     protected static function handleLoader($loaderName)
629     {
630         if (!class_exists($loaderName, FALSE)) {
631             PHPUnit_Util_Fileloader::checkAndLoad(
632               str_replace('_', '/', $loaderName) . '.php'
633             );
634         }
635
636         if (class_exists($loaderName, FALSE)) {
637             $class = new ReflectionClass($loaderName);
638
639             if ($class->implementsInterface('PHPUnit_Runner_TestSuiteLoader') &&
640                 $class->isInstantiable()) {
641                 $loader = $class->newInstance();
642             }
643         }
644
645         if (!isset($loader)) {
646             PHPUnit_TextUI_TestRunner::showError(
647               sprintf(
648                 'Could not use "%s" as loader.',
649
650                 $loaderName
651               )
652             );
653         }
654
655         PHPUnit_TextUI_TestRunner::setLoader($loader);
656     }
657
658     /**
659      * @param string $message
660      */
661     public static function showMissingDependency($message)
662     {
663         PHPUnit_TextUI_TestRunner::printVersionString();
664         print $message . "\n";
665         exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT);
666     }
667
668     /**
669      */
670     public static function showHelp()
671     {
672         PHPUnit_TextUI_TestRunner::printVersionString();
673
674         print <<<EOT
675 Usage: phpunit [switches] UnitTest [UnitTest.php]
676        phpunit [switches] <directory>
677
678   --log-graphviz <file>    Log test execution in GraphViz markup.
679   --log-json <file>        Log test execution in JSON format.
680   --log-tap <file>         Log test execution in TAP format to file.
681   --log-xml <file>         Log test execution in XML format to file.
682   --log-metrics <file>     Write metrics report in XML format.
683   --log-pmd <file>         Write violations report in PMD XML format.
684
685   --coverage-html <dir>    Generate code coverage report in HTML format.
686   --coverage-clover <file> Write code coverage data in Clover XML format.
687   --coverage-source <dir>  Write code coverage / source data in XML format.
688
689   --test-db-dsn <dsn>      DSN for the test database.
690   --test-db-log-rev <rev>  Revision information for database logging.
691   --test-db-prefix ...     Prefix that should be stripped from filenames.
692   --test-db-log-info ...   Additional information for database logging.
693
694   --story-html <file>      Write Story/BDD results in HTML format to file.
695   --story-text <file>      Write Story/BDD results in Text format to file.
696
697   --testdox-html <file>    Write agile documentation in HTML format to file.
698   --testdox-text <file>    Write agile documentation in Text format to file.
699
700   --filter <pattern>       Filter which tests to run.
701   --group ...              Only runs tests from the specified group(s).
702   --exclude-group ...      Exclude tests from the specified group(s).
703   --list-groups            List available test groups.
704
705   --loader <loader>        TestSuiteLoader implementation to use.
706   --repeat <times>         Runs the test(s) repeatedly.
707
708   --story                  Report test execution progress in Story/BDD format.
709   --tap                    Report test execution progress in TAP format.
710   --testdox                Report test execution progress in TestDox format.
711
712   --no-syntax-check        Disable syntax check of test source files.
713   --stop-on-failure        Stop execution upon first error or failure.
714   --colors                 Use colors in output.
715   --verbose                Output more verbose information.
716   --wait                   Waits for a keystroke after each test.
717
718   --skeleton-class         Generate Unit class for UnitTest in UnitTest.php.
719   --skeleton-test          Generate UnitTest class for Unit in Unit.php.
720
721   --help                   Prints this usage information.
722   --version                Prints the version and exits.
723
724   --bootstrap <file>       A "bootstrap" PHP file that is run before the tests.
725   --configuration <file>   Read configuration from XML file.
726   -d key[=value]           Sets a php.ini value.
727
728 EOT;
729     }
730 }
731 ?>