1<?php 2/** 3 * PHPUnit 4 * 5 * Copyright (c) 2001-2012, Sebastian Bergmann <sebastian@phpunit.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 * @package PHPUnit 38 * @subpackage TextUI 39 * @author Sebastian Bergmann <sebastian@phpunit.de> 40 * @copyright 2001-2012 Sebastian Bergmann <sebastian@phpunit.de> 41 * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License 42 * @link http://www.phpunit.de/ 43 * @since File available since Release 3.0.0 44 */ 45 46/** 47 * A TestRunner for the Command Line Interface (CLI) 48 * PHP SAPI Module. 49 * 50 * @package PHPUnit 51 * @subpackage TextUI 52 * @author Sebastian Bergmann <sebastian@phpunit.de> 53 * @copyright 2001-2012 Sebastian Bergmann <sebastian@phpunit.de> 54 * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License 55 * @version Release: @package_version@ 56 * @link http://www.phpunit.de/ 57 * @since Class available since Release 3.0.0 58 */ 59class PHPUnit_TextUI_Command 60{ 61 /** 62 * @var array 63 */ 64 protected $arguments = array( 65 'listGroups' => FALSE, 66 'loader' => NULL, 67 'useDefaultConfiguration' => TRUE 68 ); 69 70 /** 71 * @var array 72 */ 73 protected $options = array(); 74 75 /** 76 * @var array 77 */ 78 protected $longOptions = array( 79 'colors' => NULL, 80 'bootstrap=' => NULL, 81 'configuration=' => NULL, 82 'coverage-html=' => NULL, 83 'coverage-clover=' => NULL, 84 'coverage-php=' => NULL, 85 'coverage-text==' => NULL, 86 'debug' => NULL, 87 'exclude-group=' => NULL, 88 'filter=' => NULL, 89 'testsuite=' => NULL, 90 'group=' => NULL, 91 'help' => NULL, 92 'include-path=' => NULL, 93 'list-groups' => NULL, 94 'loader=' => NULL, 95 'log-json=' => NULL, 96 'log-junit=' => NULL, 97 'log-tap=' => NULL, 98 'process-isolation' => NULL, 99 'repeat=' => NULL, 100 'stderr' => NULL, 101 'stop-on-error' => NULL, 102 'stop-on-failure' => NULL, 103 'stop-on-incomplete' => NULL, 104 'stop-on-skipped' => NULL, 105 'strict' => NULL, 106 'tap' => NULL, 107 'testdox' => NULL, 108 'testdox-html=' => NULL, 109 'testdox-text=' => NULL, 110 'test-suffix=' => NULL, 111 'no-configuration' => NULL, 112 'no-globals-backup' => NULL, 113 'printer=' => NULL, 114 'static-backup' => NULL, 115 'verbose' => NULL, 116 'version' => NULL 117 ); 118 119 /** 120 * @var array 121 */ 122 protected $missingExtensions = array(); 123 124 /** 125 * @param boolean $exit 126 */ 127 public static function main($exit = TRUE) 128 { 129 $command = new PHPUnit_TextUI_Command; 130 return $command->run($_SERVER['argv'], $exit); 131 } 132 133 /** 134 * @param array $argv 135 * @param boolean $exit 136 */ 137 public function run(array $argv, $exit = TRUE) 138 { 139 $this->handleArguments($argv); 140 141 $runner = $this->createRunner(); 142 143 if (is_object($this->arguments['test']) && 144 $this->arguments['test'] instanceof PHPUnit_Framework_Test) { 145 $suite = $this->arguments['test']; 146 } else { 147 $suite = $runner->getTest( 148 $this->arguments['test'], 149 $this->arguments['testFile'], 150 $this->arguments['testSuffixes'] 151 ); 152 } 153 154 if ($this->arguments['listGroups']) { 155 PHPUnit_TextUI_TestRunner::printVersionString(); 156 157 print "Available test group(s):\n"; 158 159 $groups = $suite->getGroups(); 160 sort($groups); 161 162 foreach ($groups as $group) { 163 print " - $group\n"; 164 } 165 166 if ($exit) { 167 exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); 168 } else { 169 return PHPUnit_TextUI_TestRunner::SUCCESS_EXIT; 170 } 171 } 172 173 unset($this->arguments['test']); 174 unset($this->arguments['testFile']); 175 176 try { 177 $result = $runner->doRun($suite, $this->arguments); 178 } 179 180 catch (PHPUnit_Framework_Exception $e) { 181 print $e->getMessage() . "\n"; 182 } 183 184 $ret = PHPUnit_TextUI_TestRunner::FAILURE_EXIT; 185 186 if (isset($result) && $result->wasSuccessful()) { 187 $ret = PHPUnit_TextUI_TestRunner::SUCCESS_EXIT; 188 } 189 190 else if (!isset($result) || $result->errorCount() > 0) { 191 $ret = PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT; 192 } 193 194 if ($exit) { 195 exit($ret); 196 } else { 197 return $ret; 198 } 199 } 200 201 /** 202 * Create a TestRunner, override in subclasses. 203 * 204 * @return PHPUnit_TextUI_TestRunner 205 * @since Method available since Release 3.6.0 206 */ 207 protected function createRunner() 208 { 209 return new PHPUnit_TextUI_TestRunner($this->arguments['loader']); 210 } 211 212 /** 213 * Handles the command-line arguments. 214 * 215 * A child class of PHPUnit_TextUI_Command can hook into the argument 216 * parsing by adding the switch(es) to the $longOptions array and point to a 217 * callback method that handles the switch(es) in the child class like this 218 * 219 * <code> 220 * <?php 221 * class MyCommand extends PHPUnit_TextUI_Command 222 * { 223 * public function __construct() 224 * { 225 * $this->longOptions['--my-switch'] = 'myHandler'; 226 * } 227 * 228 * // --my-switch foo -> myHandler('foo') 229 * protected function myHandler($value) 230 * { 231 * } 232 * } 233 * </code> 234 * 235 * @param array $argv 236 */ 237 protected function handleArguments(array $argv) 238 { 239 try { 240 $this->options = PHPUnit_Util_Getopt::getopt( 241 $argv, 242 'd:c:hv', 243 array_keys($this->longOptions) 244 ); 245 } 246 247 catch (PHPUnit_Framework_Exception $e) { 248 PHPUnit_TextUI_TestRunner::showError($e->getMessage()); 249 } 250 251 foreach ($this->options[0] as $option) { 252 switch ($option[0]) { 253 case '--colors': { 254 $this->arguments['colors'] = TRUE; 255 } 256 break; 257 258 case '--bootstrap': { 259 $this->arguments['bootstrap'] = $option[1]; 260 } 261 break; 262 263 case 'c': 264 case '--configuration': { 265 $this->arguments['configuration'] = $option[1]; 266 } 267 break; 268 269 case '--coverage-clover': 270 case '--coverage-html': 271 case '--coverage-php': 272 case '--coverage-text': { 273 if (!extension_loaded('tokenizer')) { 274 $this->showExtensionNotLoadedMessage( 275 'tokenizer', 'No code coverage will be generated.' 276 ); 277 278 continue; 279 } 280 281 if (!extension_loaded('xdebug')) { 282 $this->showExtensionNotLoadedMessage( 283 'Xdebug', 'No code coverage will be generated.' 284 ); 285 286 continue; 287 } 288 289 switch ($option[0]) { 290 case '--coverage-clover': { 291 $this->arguments['coverageClover'] = $option[1]; 292 } 293 break; 294 295 case '--coverage-html': { 296 $this->arguments['reportDirectory'] = $option[1]; 297 } 298 break; 299 300 case '--coverage-php': { 301 $this->arguments['coveragePHP'] = $option[1]; 302 } 303 break; 304 305 case '--coverage-text': { 306 if ($option[1] === NULL) { 307 $option[1] = 'php://stdout'; 308 } 309 310 $this->arguments['coverageText'] = $option[1]; 311 $this->arguments['coverageTextShowUncoveredFiles'] = FALSE; 312 } 313 break; 314 } 315 } 316 break; 317 318 case 'd': { 319 $ini = explode('=', $option[1]); 320 321 if (isset($ini[0])) { 322 if (isset($ini[1])) { 323 ini_set($ini[0], $ini[1]); 324 } else { 325 ini_set($ini[0], TRUE); 326 } 327 } 328 } 329 break; 330 331 case '--debug': { 332 $this->arguments['debug'] = TRUE; 333 } 334 break; 335 336 case 'h': 337 case '--help': { 338 $this->showHelp(); 339 exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); 340 } 341 break; 342 343 case '--filter': { 344 $this->arguments['filter'] = $option[1]; 345 } 346 break; 347 348 case '--testsuite': { 349 $this->arguments['testsuite'] = $option[1]; 350 } 351 break; 352 353 case '--group': { 354 $this->arguments['groups'] = explode(',', $option[1]); 355 } 356 break; 357 358 case '--exclude-group': { 359 $this->arguments['excludeGroups'] = explode( 360 ',', $option[1] 361 ); 362 } 363 break; 364 365 case '--test-suffix': { 366 $this->arguments['testSuffixes'] = explode( 367 ',', $option[1] 368 ); 369 } 370 break; 371 372 case '--include-path': { 373 $includePath = $option[1]; 374 } 375 break; 376 377 case '--list-groups': { 378 $this->arguments['listGroups'] = TRUE; 379 } 380 break; 381 382 case '--printer': { 383 $this->arguments['printer'] = $option[1]; 384 } 385 break; 386 387 case '--loader': { 388 $this->arguments['loader'] = $option[1]; 389 } 390 break; 391 392 case '--log-json': { 393 $this->arguments['jsonLogfile'] = $option[1]; 394 } 395 break; 396 397 case '--log-junit': { 398 $this->arguments['junitLogfile'] = $option[1]; 399 } 400 break; 401 402 case '--log-tap': { 403 $this->arguments['tapLogfile'] = $option[1]; 404 } 405 break; 406 407 case '--process-isolation': { 408 $this->arguments['processIsolation'] = TRUE; 409 } 410 break; 411 412 case '--repeat': { 413 $this->arguments['repeat'] = (int)$option[1]; 414 } 415 break; 416 417 case '--stderr': { 418 $this->arguments['printer'] = new PHPUnit_TextUI_ResultPrinter( 419 'php://stderr', 420 isset($this->arguments['verbose']) ? $this->arguments['verbose'] : FALSE 421 ); 422 } 423 break; 424 425 case '--stop-on-error': { 426 $this->arguments['stopOnError'] = TRUE; 427 } 428 break; 429 430 case '--stop-on-failure': { 431 $this->arguments['stopOnFailure'] = TRUE; 432 } 433 break; 434 435 case '--stop-on-incomplete': { 436 $this->arguments['stopOnIncomplete'] = TRUE; 437 } 438 break; 439 440 case '--stop-on-skipped': { 441 $this->arguments['stopOnSkipped'] = TRUE; 442 } 443 break; 444 445 case '--tap': { 446 $this->arguments['printer'] = new PHPUnit_Util_Log_TAP; 447 } 448 break; 449 450 case '--testdox': { 451 $this->arguments['printer'] = new PHPUnit_Util_TestDox_ResultPrinter_Text; 452 } 453 break; 454 455 case '--testdox-html': { 456 $this->arguments['testdoxHTMLFile'] = $option[1]; 457 } 458 break; 459 460 case '--testdox-text': { 461 $this->arguments['testdoxTextFile'] = $option[1]; 462 } 463 break; 464 465 case '--no-configuration': { 466 $this->arguments['useDefaultConfiguration'] = FALSE; 467 } 468 break; 469 470 case '--no-globals-backup': { 471 $this->arguments['backupGlobals'] = FALSE; 472 } 473 break; 474 475 case '--static-backup': { 476 $this->arguments['backupStaticAttributes'] = TRUE; 477 } 478 break; 479 480 case 'v': 481 case '--verbose': { 482 $this->arguments['verbose'] = TRUE; 483 } 484 break; 485 486 case '--version': { 487 PHPUnit_TextUI_TestRunner::printVersionString(); 488 exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); 489 } 490 break; 491 492 case '--strict': { 493 $this->arguments['strict'] = TRUE; 494 } 495 break; 496 497 default: { 498 $optionName = str_replace('--', '', $option[0]); 499 500 if (isset($this->longOptions[$optionName])) { 501 $handler = $this->longOptions[$optionName]; 502 } 503 504 else if (isset($this->longOptions[$optionName . '='])) { 505 $handler = $this->longOptions[$optionName . '=']; 506 } 507 508 if (isset($handler) && is_callable(array($this, $handler))) { 509 $this->$handler($option[1]); 510 } 511 } 512 } 513 } 514 515 $this->handleCustomTestSuite(); 516 517 if (!isset($this->arguments['test'])) { 518 if (count($this->options[1]) > 2) { 519 $this->showMessage( 520 'More than two positional arguments provided.', 521 FALSE 522 ); 523 $this->showHelp(); 524 exit(PHPUnit_TextUI_TestRunner::FAILURE_EXIT); 525 } 526 527 if (isset($this->options[1][0])) { 528 $this->arguments['test'] = $this->options[1][0]; 529 } 530 531 if (isset($this->options[1][1])) { 532 $this->arguments['testFile'] = $this->options[1][1]; 533 } else { 534 $this->arguments['testFile'] = ''; 535 } 536 537 if (isset($this->arguments['test']) && 538 is_file($this->arguments['test']) && 539 substr($this->arguments['test'], -5, 5) != '.phpt') { 540 $this->arguments['testFile'] = realpath($this->arguments['test']); 541 $this->arguments['test'] = substr($this->arguments['test'], 0, strrpos($this->arguments['test'], '.')); 542 } 543 } 544 545 if (!isset($this->arguments['testSuffixes'])) { 546 $this->arguments['testSuffixes'] = array('Test.php', '.phpt'); 547 } 548 549 if (isset($includePath)) { 550 ini_set( 551 'include_path', 552 $includePath . PATH_SEPARATOR . ini_get('include_path') 553 ); 554 } 555 556 if (isset($this->arguments['bootstrap'])) { 557 $this->handleBootstrap($this->arguments['bootstrap']); 558 } 559 560 if (isset($this->arguments['printer']) && 561 is_string($this->arguments['printer'])) { 562 $this->arguments['printer'] = $this->handlePrinter($this->arguments['printer']); 563 } 564 565 if ($this->arguments['loader'] !== NULL) { 566 $this->arguments['loader'] = $this->handleLoader($this->arguments['loader']); 567 } 568 569 if (isset($this->arguments['configuration']) && 570 is_dir($this->arguments['configuration'])) { 571 $configurationFile = $this->arguments['configuration'] . 572 '/phpunit.xml'; 573 574 if (file_exists($configurationFile)) { 575 $this->arguments['configuration'] = realpath( 576 $configurationFile 577 ); 578 } 579 580 else if (file_exists($configurationFile . '.dist')) { 581 $this->arguments['configuration'] = realpath( 582 $configurationFile . '.dist' 583 ); 584 } 585 } 586 587 else if (!isset($this->arguments['configuration']) && 588 $this->arguments['useDefaultConfiguration']) { 589 if (file_exists('phpunit.xml')) { 590 $this->arguments['configuration'] = realpath('phpunit.xml'); 591 } else if (file_exists('phpunit.xml.dist')) { 592 $this->arguments['configuration'] = realpath( 593 'phpunit.xml.dist' 594 ); 595 } 596 } 597 598 if (isset($this->arguments['configuration'])) { 599 try { 600 $configuration = PHPUnit_Util_Configuration::getInstance( 601 $this->arguments['configuration'] 602 ); 603 } 604 605 catch (Exception $e) { 606 print $e->getMessage() . "\n"; 607 exit(PHPUnit_TextUI_TestRunner::FAILURE_EXIT); 608 } 609 610 $phpunit = $configuration->getPHPUnitConfiguration(); 611 612 $configuration->handlePHPConfiguration(); 613 614 if (!isset($this->arguments['bootstrap']) && isset($phpunit['bootstrap'])) { 615 $this->handleBootstrap($phpunit['bootstrap']); 616 } 617 618 if (isset($phpunit['printerClass'])) { 619 if (isset($phpunit['printerFile'])) { 620 $file = $phpunit['printerFile']; 621 } else { 622 $file = ''; 623 } 624 625 $this->arguments['printer'] = $this->handlePrinter( 626 $phpunit['printerClass'], $file 627 ); 628 } 629 630 if (isset($phpunit['testSuiteLoaderClass'])) { 631 if (isset($phpunit['testSuiteLoaderFile'])) { 632 $file = $phpunit['testSuiteLoaderFile']; 633 } else { 634 $file = ''; 635 } 636 637 $this->arguments['loader'] = $this->handleLoader( 638 $phpunit['testSuiteLoaderClass'], $file 639 ); 640 } 641 642 $logging = $configuration->getLoggingConfiguration(); 643 644 if (isset($logging['coverage-html']) || isset($logging['coverage-clover']) || isset($logging['coverage-text']) ) { 645 if (!extension_loaded('tokenizer')) { 646 $this->showExtensionNotLoadedMessage( 647 'tokenizer', 'No code coverage will be generated.' 648 ); 649 } 650 651 else if (!extension_loaded('Xdebug')) { 652 $this->showExtensionNotLoadedMessage( 653 'Xdebug', 'No code coverage will be generated.' 654 ); 655 } 656 } 657 658 $browsers = $configuration->getSeleniumBrowserConfiguration(); 659 660 if (!empty($browsers) && 661 class_exists('PHPUnit_Extensions_SeleniumTestCase')) { 662 PHPUnit_Extensions_SeleniumTestCase::$browsers = $browsers; 663 } 664 665 if (!isset($this->arguments['test'])) { 666 $testSuite = $configuration->getTestSuiteConfiguration(isset($this->arguments['testsuite']) ? $this->arguments['testsuite'] : null); 667 668 if ($testSuite !== NULL) { 669 $this->arguments['test'] = $testSuite; 670 } 671 } 672 } 673 674 if (isset($this->arguments['test']) && is_string($this->arguments['test']) && substr($this->arguments['test'], -5, 5) == '.phpt') { 675 $test = new PHPUnit_Extensions_PhptTestCase($this->arguments['test']); 676 677 $this->arguments['test'] = new PHPUnit_Framework_TestSuite; 678 $this->arguments['test']->addTest($test); 679 } 680 681 if (!isset($this->arguments['test']) || 682 (isset($this->arguments['testDatabaseLogRevision']) && !isset($this->arguments['testDatabaseDSN']))) { 683 $this->showHelp(); 684 exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT); 685 } 686 } 687 688 /** 689 * Handles the loading of the PHPUnit_Runner_TestSuiteLoader implementation. 690 * 691 * @param string $loaderClass 692 * @param string $loaderFile 693 * @return PHPUnit_Runner_TestSuiteLoader 694 */ 695 protected function handleLoader($loaderClass, $loaderFile = '') 696 { 697 if (!class_exists($loaderClass, FALSE)) { 698 if ($loaderFile == '') { 699 $loaderFile = PHPUnit_Util_Filesystem::classNameToFilename( 700 $loaderClass 701 ); 702 } 703 704 $loaderFile = stream_resolve_include_path($loaderFile); 705 706 if ($loaderFile) { 707 require $loaderFile; 708 } 709 } 710 711 if (class_exists($loaderClass, FALSE)) { 712 $class = new ReflectionClass($loaderClass); 713 714 if ($class->implementsInterface('PHPUnit_Runner_TestSuiteLoader') && 715 $class->isInstantiable()) { 716 $loader = $class->newInstance(); 717 } 718 } 719 720 if (!isset($loader)) { 721 PHPUnit_TextUI_TestRunner::showError( 722 sprintf( 723 'Could not use "%s" as loader.', 724 725 $loaderClass 726 ) 727 ); 728 } 729 730 return $loader; 731 } 732 733 /** 734 * Handles the loading of the PHPUnit_Util_Printer implementation. 735 * 736 * @param string $printerClass 737 * @param string $printerFile 738 * @return PHPUnit_Util_Printer 739 */ 740 protected function handlePrinter($printerClass, $printerFile = '') 741 { 742 if (!class_exists($printerClass, FALSE)) { 743 if ($printerFile == '') { 744 $printerFile = PHPUnit_Util_Filesystem::classNameToFilename( 745 $printerClass 746 ); 747 } 748 749 $printerFile = stream_resolve_include_path($printerFile); 750 751 if ($printerFile) { 752 require $printerFile; 753 } 754 } 755 756 if (class_exists($printerClass, FALSE)) { 757 $class = new ReflectionClass($printerClass); 758 759 if ($class->implementsInterface('PHPUnit_Framework_TestListener') && 760 $class->isSubclassOf('PHPUnit_Util_Printer') && 761 $class->isInstantiable()) { 762 $printer = $class->newInstance(); 763 } 764 } 765 766 if (!isset($printer)) { 767 PHPUnit_TextUI_TestRunner::showError( 768 sprintf( 769 'Could not use "%s" as printer.', 770 771 $printerClass 772 ) 773 ); 774 } 775 776 return $printer; 777 } 778 779 /** 780 * Loads a bootstrap file. 781 * 782 * @param string $filename 783 */ 784 protected function handleBootstrap($filename) 785 { 786 try { 787 PHPUnit_Util_Fileloader::checkAndLoad($filename); 788 } 789 790 catch (PHPUnit_Framework_Exception $e) { 791 PHPUnit_TextUI_TestRunner::showError($e->getMessage()); 792 } 793 } 794 795 /** 796 * @param string $message 797 * @since Method available since Release 3.6.0 798 */ 799 protected function showExtensionNotLoadedMessage($extension, $message = '') 800 { 801 if (isset($this->missingExtensions[$extension])) { 802 return; 803 } 804 805 if (!empty($message)) { 806 $message = ' ' . $message; 807 } 808 809 $this->showMessage( 810 'The ' . $extension . ' extension is not loaded.' . $message . "\n", 811 FALSE 812 ); 813 814 $this->missingExtensions[$extension] = TRUE; 815 } 816 817 /** 818 * Shows a message. 819 * 820 * @param string $message 821 * @param boolean $exit 822 */ 823 protected function showMessage($message, $exit = TRUE) 824 { 825 PHPUnit_TextUI_TestRunner::printVersionString(); 826 print $message . "\n"; 827 828 if ($exit) { 829 exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT); 830 } else { 831 print "\n"; 832 } 833 } 834 835 /** 836 * Show the help message. 837 */ 838 protected function showHelp() 839 { 840 PHPUnit_TextUI_TestRunner::printVersionString(); 841 842 print <<<EOT 843Usage: phpunit [switches] UnitTest [UnitTest.php] 844 phpunit [switches] <directory> 845 846 --log-junit <file> Log test execution in JUnit XML format to file. 847 --log-tap <file> Log test execution in TAP format to file. 848 --log-json <file> Log test execution in JSON format. 849 850 --coverage-clover <file> Generate code coverage report in Clover XML format. 851 --coverage-html <dir> Generate code coverage report in HTML format. 852 --coverage-php <file> Serialize PHP_CodeCoverage object to file. 853 --coverage-text=<file> Generate code coverage report in text format. 854 Default to writing to the standard output. 855 856 --testdox-html <file> Write agile documentation in HTML format to file. 857 --testdox-text <file> Write agile documentation in Text format to file. 858 859 --filter <pattern> Filter which tests to run. 860 --testsuite <pattern> Filter which testsuite to run. 861 --group ... Only runs tests from the specified group(s). 862 --exclude-group ... Exclude tests from the specified group(s). 863 --list-groups List available test groups. 864 --test-suffix ... Only search for test in files with specified 865 suffix(es). Default: Test.php,.phpt 866 867 --loader <loader> TestSuiteLoader implementation to use. 868 --printer <printer> TestSuiteListener implementation to use. 869 --repeat <times> Runs the test(s) repeatedly. 870 871 --tap Report test execution progress in TAP format. 872 --testdox Report test execution progress in TestDox format. 873 874 --colors Use colors in output. 875 --stderr Write to STDERR instead of STDOUT. 876 --stop-on-error Stop execution upon first error. 877 --stop-on-failure Stop execution upon first error or failure. 878 --stop-on-skipped Stop execution upon first skipped test. 879 --stop-on-incomplete Stop execution upon first incomplete test. 880 --strict Run tests in strict mode. 881 -v|--verbose Output more verbose information. 882 --debug Display debugging information during test execution. 883 884 --process-isolation Run each test in a separate PHP process. 885 --no-globals-backup Do not backup and restore \$GLOBALS for each test. 886 --static-backup Backup and restore static attributes for each test. 887 888 --bootstrap <file> A "bootstrap" PHP file that is run before the tests. 889 -c|--configuration <file> Read configuration from XML file. 890 --no-configuration Ignore default configuration file (phpunit.xml). 891 --include-path <path(s)> Prepend PHP's include_path with given path(s). 892 -d key[=value] Sets a php.ini value. 893 894 -h|--help Prints this usage information. 895 --version Prints the version and exits. 896 897EOT; 898 } 899 900 /** 901 * Custom callback for test suite discovery. 902 */ 903 protected function handleCustomTestSuite() 904 { 905 } 906} 907