Revision 150 | Zur aktuellen Revision | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
<?php declare(strict_types=1);/** This file is part of PHPUnit.** (c) Sebastian Bergmann <sebastian@phpunit.de>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace PHPUnit\TextUI;use const PHP_EOL;use const PHP_SAPI;use const PHP_VERSION;use function array_diff;use function array_map;use function array_merge;use function assert;use function class_exists;use function count;use function dirname;use function file_put_contents;use function htmlspecialchars;use function is_array;use function is_int;use function is_string;use function mt_srand;use function range;use function realpath;use function sort;use function sprintf;use function time;use PHPUnit\Framework\Exception;use PHPUnit\Framework\TestResult;use PHPUnit\Framework\TestSuite;use PHPUnit\Runner\AfterLastTestHook;use PHPUnit\Runner\BaseTestRunner;use PHPUnit\Runner\BeforeFirstTestHook;use PHPUnit\Runner\DefaultTestResultCache;use PHPUnit\Runner\Extension\ExtensionHandler;use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator;use PHPUnit\Runner\Filter\Factory;use PHPUnit\Runner\Filter\IncludeGroupFilterIterator;use PHPUnit\Runner\Filter\NameFilterIterator;use PHPUnit\Runner\Hook;use PHPUnit\Runner\NullTestResultCache;use PHPUnit\Runner\ResultCacheExtension;use PHPUnit\Runner\StandardTestSuiteLoader;use PHPUnit\Runner\TestHook;use PHPUnit\Runner\TestListenerAdapter;use PHPUnit\Runner\TestSuiteLoader;use PHPUnit\Runner\TestSuiteSorter;use PHPUnit\Runner\Version;use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\FilterMapper;use PHPUnit\TextUI\XmlConfiguration\Configuration;use PHPUnit\TextUI\XmlConfiguration\Loader;use PHPUnit\TextUI\XmlConfiguration\PhpHandler;use PHPUnit\Util\Filesystem;use PHPUnit\Util\Log\JUnit;use PHPUnit\Util\Log\TeamCity;use PHPUnit\Util\Printer;use PHPUnit\Util\TestDox\CliTestDoxPrinter;use PHPUnit\Util\TestDox\HtmlResultPrinter;use PHPUnit\Util\TestDox\TextResultPrinter;use PHPUnit\Util\TestDox\XmlResultPrinter;use PHPUnit\Util\XdebugFilterScriptGenerator;use PHPUnit\Util\Xml\SchemaDetector;use ReflectionClass;use ReflectionException;use SebastianBergmann\CodeCoverage\CodeCoverage;use SebastianBergmann\CodeCoverage\Driver\Selector;use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException;use SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter;use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport;use SebastianBergmann\CodeCoverage\Report\Cobertura as CoberturaReport;use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport;use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport;use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport;use SebastianBergmann\CodeCoverage\Report\Text as TextReport;use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport;use SebastianBergmann\Comparator\Comparator;use SebastianBergmann\Environment\Runtime;use SebastianBergmann\Invoker\Invoker;use SebastianBergmann\Timer\Timer;/*** @internal This class is not covered by the backward compatibility promise for PHPUnit*/final class TestRunner extends BaseTestRunner{public const SUCCESS_EXIT = 0;public const FAILURE_EXIT = 1;public const EXCEPTION_EXIT = 2;/*** @var CodeCoverageFilter*/private $codeCoverageFilter;/*** @var TestSuiteLoader*/private $loader;/*** @var ResultPrinter*/private $printer;/*** @var bool*/private $messagePrinted = false;/*** @var Hook[]*/private $extensions = [];/*** @var Timer*/private $timer;public function __construct(TestSuiteLoader $loader = null, CodeCoverageFilter $filter = null){if ($filter === null) {$filter = new CodeCoverageFilter;}$this->codeCoverageFilter = $filter;$this->loader = $loader;$this->timer = new Timer;}/*** @throws \PHPUnit\Runner\Exception* @throws \PHPUnit\TextUI\XmlConfiguration\Exception* @throws Exception*/public function run(TestSuite $suite, array $arguments = [], array $warnings = [], bool $exit = true): TestResult{if (isset($arguments['configuration'])) {$GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] = $arguments['configuration'];}$this->handleConfiguration($arguments);$warnings = array_merge($warnings, $arguments['warnings']);if (is_int($arguments['columns']) && $arguments['columns'] < 16) {$arguments['columns'] = 16;$tooFewColumnsRequested = true;}if (isset($arguments['bootstrap'])) {$GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap'];}if ($arguments['backupGlobals'] === true) {$suite->setBackupGlobals(true);}if ($arguments['backupStaticAttributes'] === true) {$suite->setBackupStaticAttributes(true);}if ($arguments['beStrictAboutChangesToGlobalState'] === true) {$suite->setBeStrictAboutChangesToGlobalState(true);}if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) {mt_srand($arguments['randomOrderSeed']);}if ($arguments['cacheResult']) {if (!isset($arguments['cacheResultFile'])) {if (isset($arguments['configurationObject'])) {assert($arguments['configurationObject'] instanceof Configuration);$cacheLocation = $arguments['configurationObject']->filename();} else {$cacheLocation = $_SERVER['PHP_SELF'];}$arguments['cacheResultFile'] = null;$cacheResultFile = realpath($cacheLocation);if ($cacheResultFile !== false) {$arguments['cacheResultFile'] = dirname($cacheResultFile);}}$cache = new DefaultTestResultCache($arguments['cacheResultFile']);$this->addExtension(new ResultCacheExtension($cache));}if ($arguments['executionOrder'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['executionOrderDefects'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['resolveDependencies']) {$cache = $cache ?? new NullTestResultCache;$cache->load();$sorter = new TestSuiteSorter($cache);$sorter->reorderTestsInSuite($suite, $arguments['executionOrder'], $arguments['resolveDependencies'], $arguments['executionOrderDefects']);$originalExecutionOrder = $sorter->getOriginalExecutionOrder();unset($sorter);}if (is_int($arguments['repeat']) && $arguments['repeat'] > 0) {$_suite = new TestSuite;/* @noinspection PhpUnusedLocalVariableInspection */foreach (range(1, $arguments['repeat']) as $step) {$_suite->addTest($suite);}$suite = $_suite;unset($_suite);}$result = $this->createTestResult();$listener = new TestListenerAdapter;$listenerNeeded = false;foreach ($this->extensions as $extension) {if ($extension instanceof TestHook) {$listener->add($extension);$listenerNeeded = true;}}if ($listenerNeeded) {$result->addListener($listener);}unset($listener, $listenerNeeded);if ($arguments['convertDeprecationsToExceptions']) {$result->convertDeprecationsToExceptions(true);}if (!$arguments['convertErrorsToExceptions']) {$result->convertErrorsToExceptions(false);}if (!$arguments['convertNoticesToExceptions']) {$result->convertNoticesToExceptions(false);}if (!$arguments['convertWarningsToExceptions']) {$result->convertWarningsToExceptions(false);}if ($arguments['stopOnError']) {$result->stopOnError(true);}if ($arguments['stopOnFailure']) {$result->stopOnFailure(true);}if ($arguments['stopOnWarning']) {$result->stopOnWarning(true);}if ($arguments['stopOnIncomplete']) {$result->stopOnIncomplete(true);}if ($arguments['stopOnRisky']) {$result->stopOnRisky(true);}if ($arguments['stopOnSkipped']) {$result->stopOnSkipped(true);}if ($arguments['stopOnDefect']) {$result->stopOnDefect(true);}if ($arguments['registerMockObjectsFromTestArgumentsRecursively']) {$result->setRegisterMockObjectsFromTestArgumentsRecursively(true);}if ($this->printer === null) {if (isset($arguments['printer'])) {if ($arguments['printer'] instanceof ResultPrinter) {$this->printer = $arguments['printer'];} elseif (is_string($arguments['printer']) && class_exists($arguments['printer'], false)) {try {$reflector = new ReflectionClass($arguments['printer']);if ($reflector->implementsInterface(ResultPrinter::class)) {$this->printer = $this->createPrinter($arguments['printer'], $arguments);}// @codeCoverageIgnoreStart} catch (ReflectionException $e) {throw new Exception($e->getMessage(),$e->getCode(),$e);}// @codeCoverageIgnoreEnd}} else {$this->printer = $this->createPrinter(DefaultResultPrinter::class, $arguments);}}if (isset($originalExecutionOrder) && $this->printer instanceof CliTestDoxPrinter) {assert($this->printer instanceof CliTestDoxPrinter);$this->printer->setOriginalExecutionOrder($originalExecutionOrder);$this->printer->setShowProgressAnimation(!$arguments['noInteraction']);}$this->write(Version::getVersionString() . "\n");foreach ($arguments['listeners'] as $listener) {$result->addListener($listener);}$result->addListener($this->printer);$coverageFilterFromConfigurationFile = false;$coverageFilterFromOption = false;$codeCoverageReports = 0;if (isset($arguments['testdoxHTMLFile'])) {$result->addListener(new HtmlResultPrinter($arguments['testdoxHTMLFile'],$arguments['testdoxGroups'],$arguments['testdoxExcludeGroups']));}if (isset($arguments['testdoxTextFile'])) {$result->addListener(new TextResultPrinter($arguments['testdoxTextFile'],$arguments['testdoxGroups'],$arguments['testdoxExcludeGroups']));}if (isset($arguments['testdoxXMLFile'])) {$result->addListener(new XmlResultPrinter($arguments['testdoxXMLFile']));}if (isset($arguments['teamcityLogfile'])) {$result->addListener(new TeamCity($arguments['teamcityLogfile']));}if (isset($arguments['junitLogfile'])) {$result->addListener(new JUnit($arguments['junitLogfile'],$arguments['reportUselessTests']));}if (isset($arguments['coverageClover'])) {$codeCoverageReports++;}if (isset($arguments['coverageCobertura'])) {$codeCoverageReports++;}if (isset($arguments['coverageCrap4J'])) {$codeCoverageReports++;}if (isset($arguments['coverageHtml'])) {$codeCoverageReports++;}if (isset($arguments['coveragePHP'])) {$codeCoverageReports++;}if (isset($arguments['coverageText'])) {$codeCoverageReports++;}if (isset($arguments['coverageXml'])) {$codeCoverageReports++;}if ($codeCoverageReports > 0 || isset($arguments['xdebugFilterFile'])) {if (isset($arguments['coverageFilter'])) {if (!is_array($arguments['coverageFilter'])) {$coverageFilterDirectories = [$arguments['coverageFilter']];} else {$coverageFilterDirectories = $arguments['coverageFilter'];}foreach ($coverageFilterDirectories as $coverageFilterDirectory) {$this->codeCoverageFilter->includeDirectory($coverageFilterDirectory);}$coverageFilterFromOption = true;}if (isset($arguments['configurationObject'])) {assert($arguments['configurationObject'] instanceof Configuration);$codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage();if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) {$coverageFilterFromConfigurationFile = true;(new FilterMapper)->map($this->codeCoverageFilter,$codeCoverageConfiguration);}}}if ($codeCoverageReports > 0) {try {if (isset($codeCoverageConfiguration) &&($codeCoverageConfiguration->pathCoverage() || (isset($arguments['pathCoverage']) && $arguments['pathCoverage'] === true))) {$codeCoverageDriver = (new Selector)->forLineAndPathCoverage($this->codeCoverageFilter);} else {$codeCoverageDriver = (new Selector)->forLineCoverage($this->codeCoverageFilter);}$codeCoverage = new CodeCoverage($codeCoverageDriver,$this->codeCoverageFilter);if (isset($codeCoverageConfiguration) && $codeCoverageConfiguration->hasCacheDirectory()) {$codeCoverage->cacheStaticAnalysis($codeCoverageConfiguration->cacheDirectory()->path());}if (isset($arguments['coverageCacheDirectory'])) {$codeCoverage->cacheStaticAnalysis($arguments['coverageCacheDirectory']);}$codeCoverage->excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(Comparator::class);if ($arguments['strictCoverage']) {$codeCoverage->enableCheckForUnintentionallyCoveredCode();}if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {if ($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']) {$codeCoverage->ignoreDeprecatedCode();} else {$codeCoverage->doNotIgnoreDeprecatedCode();}}if (isset($arguments['disableCodeCoverageIgnore'])) {if ($arguments['disableCodeCoverageIgnore']) {$codeCoverage->disableAnnotationsForIgnoringCode();} else {$codeCoverage->enableAnnotationsForIgnoringCode();}}if (isset($arguments['configurationObject'])) {$codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage();if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) {if ($codeCoverageConfiguration->includeUncoveredFiles()) {$codeCoverage->includeUncoveredFiles();} else {$codeCoverage->excludeUncoveredFiles();}if ($codeCoverageConfiguration->processUncoveredFiles()) {$codeCoverage->processUncoveredFiles();} else {$codeCoverage->doNotProcessUncoveredFiles();}}}if ($this->codeCoverageFilter->isEmpty()) {if (!$coverageFilterFromConfigurationFile && !$coverageFilterFromOption) {$warnings[] = 'No filter is configured, code coverage will not be processed';} else {$warnings[] = 'Incorrect filter configuration, code coverage will not be processed';}unset($codeCoverage);}} catch (CodeCoverageException $e) {$warnings[] = $e->getMessage();}}if ($arguments['verbose']) {if (PHP_SAPI === 'phpdbg') {$this->writeMessage('Runtime', 'PHPDBG ' . PHP_VERSION);} else {$runtime = 'PHP ' . PHP_VERSION;if (isset($codeCoverageDriver)) {$runtime .= ' with ' . $codeCoverageDriver->nameAndVersion();}$this->writeMessage('Runtime', $runtime);}if (isset($arguments['configurationObject'])) {assert($arguments['configurationObject'] instanceof Configuration);$this->writeMessage('Configuration',$arguments['configurationObject']->filename());}foreach ($arguments['loadedExtensions'] as $extension) {$this->writeMessage('Extension',$extension);}foreach ($arguments['notLoadedExtensions'] as $extension) {$this->writeMessage('Extension',$extension);}}if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) {$this->writeMessage('Random Seed',(string) $arguments['randomOrderSeed']);}if (isset($tooFewColumnsRequested)) {$warnings[] = 'Less than 16 columns requested, number of columns set to 16';}if ((new Runtime)->discardsComments()) {$warnings[] = 'opcache.save_comments=0 set; annotations will not work';}if (isset($arguments['conflictBetweenPrinterClassAndTestdox'])) {$warnings[] = 'Directives printerClass and testdox are mutually exclusive';}$warnings = array_merge($warnings, $suite->warnings());sort($warnings);foreach ($warnings as $warning) {$this->writeMessage('Warning', $warning);}if (isset($arguments['configurationObject'])) {assert($arguments['configurationObject'] instanceof Configuration);if ($arguments['configurationObject']->hasValidationErrors()) {if ((new SchemaDetector)->detect($arguments['configurationObject']->filename())->detected()) {$this->writeMessage('Warning', 'Your XML configuration validates against a deprecated schema.');$this->writeMessage('Suggestion', 'Migrate your XML configuration using "--migrate-configuration"!');} else {$this->write("\n Warning - The configuration file did not pass validation!\n The following problems have been detected:\n");$this->write($arguments['configurationObject']->validationErrors());$this->write("\n Test results may not be as expected.\n\n");}}}if (isset($arguments['xdebugFilterFile'], $codeCoverageConfiguration)) {$this->write(PHP_EOL . 'Please note that --dump-xdebug-filter and --prepend are deprecated and will be removed in PHPUnit 10.' . PHP_EOL);$script = (new XdebugFilterScriptGenerator)->generate($codeCoverageConfiguration);if ($arguments['xdebugFilterFile'] !== 'php://stdout' && $arguments['xdebugFilterFile'] !== 'php://stderr' && !Filesystem::createDirectory(dirname($arguments['xdebugFilterFile']))) {$this->write(sprintf('Cannot write Xdebug filter script to %s ' . PHP_EOL, $arguments['xdebugFilterFile']));exit(self::EXCEPTION_EXIT);}file_put_contents($arguments['xdebugFilterFile'], $script);$this->write(sprintf('Wrote Xdebug filter script to %s ' . PHP_EOL . PHP_EOL, $arguments['xdebugFilterFile']));exit(self::SUCCESS_EXIT);}$this->write("\n");if (isset($codeCoverage)) {$result->setCodeCoverage($codeCoverage);}$result->beStrictAboutTestsThatDoNotTestAnything($arguments['reportUselessTests']);$result->beStrictAboutOutputDuringTests($arguments['disallowTestOutput']);$result->beStrictAboutTodoAnnotatedTests($arguments['disallowTodoAnnotatedTests']);$result->beStrictAboutResourceUsageDuringSmallTests($arguments['beStrictAboutResourceUsageDuringSmallTests']);if ($arguments['enforceTimeLimit'] === true && !(new Invoker)->canInvokeWithTimeout()) {$this->writeMessage('Error', 'PHP extension pcntl is required for enforcing time limits');}$result->enforceTimeLimit($arguments['enforceTimeLimit']);$result->setDefaultTimeLimit($arguments['defaultTimeLimit']);$result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']);$result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']);$result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']);if (isset($arguments['forceCoversAnnotation']) && $arguments['forceCoversAnnotation'] === true) {$result->forceCoversAnnotation();}$this->processSuiteFilters($suite, $arguments);$suite->setRunTestInSeparateProcess($arguments['processIsolation']);foreach ($this->extensions as $extension) {if ($extension instanceof BeforeFirstTestHook) {$extension->executeBeforeFirstTest();}}$suite->run($result);foreach ($this->extensions as $extension) {if ($extension instanceof AfterLastTestHook) {$extension->executeAfterLastTest();}}$result->flushListeners();$this->printer->printResult($result);if (isset($codeCoverage)) {if (isset($arguments['coverageClover'])) {$this->codeCoverageGenerationStart('Clover XML');try {$writer = new CloverReport;$writer->process($codeCoverage, $arguments['coverageClover']);$this->codeCoverageGenerationSucceeded();unset($writer);} catch (CodeCoverageException $e) {$this->codeCoverageGenerationFailed($e);}}if (isset($arguments['coverageCobertura'])) {$this->codeCoverageGenerationStart('Cobertura XML');try {$writer = new CoberturaReport;$writer->process($codeCoverage, $arguments['coverageCobertura']);$this->codeCoverageGenerationSucceeded();unset($writer);} catch (CodeCoverageException $e) {$this->codeCoverageGenerationFailed($e);}}if (isset($arguments['coverageCrap4J'])) {$this->codeCoverageGenerationStart('Crap4J XML');try {$writer = new Crap4jReport($arguments['crap4jThreshold']);$writer->process($codeCoverage, $arguments['coverageCrap4J']);$this->codeCoverageGenerationSucceeded();unset($writer);} catch (CodeCoverageException $e) {$this->codeCoverageGenerationFailed($e);}}if (isset($arguments['coverageHtml'])) {$this->codeCoverageGenerationStart('HTML');try {$writer = new HtmlReport($arguments['reportLowUpperBound'],$arguments['reportHighLowerBound'],sprintf(' and <a href="https://phpunit.de/">PHPUnit %s</a>',Version::id()));$writer->process($codeCoverage, $arguments['coverageHtml']);$this->codeCoverageGenerationSucceeded();unset($writer);} catch (CodeCoverageException $e) {$this->codeCoverageGenerationFailed($e);}}if (isset($arguments['coveragePHP'])) {$this->codeCoverageGenerationStart('PHP');try {$writer = new PhpReport;$writer->process($codeCoverage, $arguments['coveragePHP']);$this->codeCoverageGenerationSucceeded();unset($writer);} catch (CodeCoverageException $e) {$this->codeCoverageGenerationFailed($e);}}if (isset($arguments['coverageText'])) {if ($arguments['coverageText'] === 'php://stdout') {$outputStream = $this->printer;$colors = $arguments['colors'] && $arguments['colors'] !== DefaultResultPrinter::COLOR_NEVER;} else {$outputStream = new Printer($arguments['coverageText']);$colors = false;}$processor = new TextReport($arguments['reportLowUpperBound'],$arguments['reportHighLowerBound'],$arguments['coverageTextShowUncoveredFiles'],$arguments['coverageTextShowOnlySummary']);$outputStream->write($processor->process($codeCoverage, $colors));}if (isset($arguments['coverageXml'])) {$this->codeCoverageGenerationStart('PHPUnit XML');try {$writer = new XmlReport(Version::id());$writer->process($codeCoverage, $arguments['coverageXml']);$this->codeCoverageGenerationSucceeded();unset($writer);} catch (CodeCoverageException $e) {$this->codeCoverageGenerationFailed($e);}}}if ($exit) {if (isset($arguments['failOnEmptyTestSuite']) && $arguments['failOnEmptyTestSuite'] === true && count($result) === 0) {exit(self::FAILURE_EXIT);}if ($result->wasSuccessfulIgnoringWarnings()) {if ($arguments['failOnRisky'] && !$result->allHarmless()) {exit(self::FAILURE_EXIT);}if ($arguments['failOnWarning'] && $result->warningCount() > 0) {exit(self::FAILURE_EXIT);}if ($arguments['failOnIncomplete'] && $result->notImplementedCount() > 0) {exit(self::FAILURE_EXIT);}if ($arguments['failOnSkipped'] && $result->skippedCount() > 0) {exit(self::FAILURE_EXIT);}exit(self::SUCCESS_EXIT);}if ($result->errorCount() > 0) {exit(self::EXCEPTION_EXIT);}if ($result->failureCount() > 0) {exit(self::FAILURE_EXIT);}}return $result;}/*** Returns the loader to be used.*/public function getLoader(): TestSuiteLoader{if ($this->loader === null) {$this->loader = new StandardTestSuiteLoader;}return $this->loader;}public function addExtension(Hook $extension): void{$this->extensions[] = $extension;}/*** Override to define how to handle a failed loading of* a test suite.*/protected function runFailed(string $message): void{$this->write($message . PHP_EOL);exit(self::FAILURE_EXIT);}private function createTestResult(): TestResult{return new TestResult;}private function write(string $buffer): void{if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {$buffer = htmlspecialchars($buffer);}if ($this->printer !== null) {$this->printer->write($buffer);} else {print $buffer;}}/*** @throws \PHPUnit\TextUI\XmlConfiguration\Exception* @throws Exception*/private function handleConfiguration(array &$arguments): void{if (!isset($arguments['configurationObject']) && isset($arguments['configuration'])) {$arguments['configurationObject'] = (new Loader)->load($arguments['configuration']);}if (!isset($arguments['warnings'])) {$arguments['warnings'] = [];}$arguments['debug'] = $arguments['debug'] ?? false;$arguments['filter'] = $arguments['filter'] ?? false;$arguments['listeners'] = $arguments['listeners'] ?? [];if (isset($arguments['configurationObject'])) {(new PhpHandler)->handle($arguments['configurationObject']->php());$codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage();if (!isset($arguments['noCoverage'])) {if (!isset($arguments['coverageClover']) && $codeCoverageConfiguration->hasClover()) {$arguments['coverageClover'] = $codeCoverageConfiguration->clover()->target()->path();}if (!isset($arguments['coverageCobertura']) && $codeCoverageConfiguration->hasCobertura()) {$arguments['coverageCobertura'] = $codeCoverageConfiguration->cobertura()->target()->path();}if (!isset($arguments['coverageCrap4J']) && $codeCoverageConfiguration->hasCrap4j()) {$arguments['coverageCrap4J'] = $codeCoverageConfiguration->crap4j()->target()->path();if (!isset($arguments['crap4jThreshold'])) {$arguments['crap4jThreshold'] = $codeCoverageConfiguration->crap4j()->threshold();}}if (!isset($arguments['coverageHtml']) && $codeCoverageConfiguration->hasHtml()) {$arguments['coverageHtml'] = $codeCoverageConfiguration->html()->target()->path();if (!isset($arguments['reportLowUpperBound'])) {$arguments['reportLowUpperBound'] = $codeCoverageConfiguration->html()->lowUpperBound();}if (!isset($arguments['reportHighLowerBound'])) {$arguments['reportHighLowerBound'] = $codeCoverageConfiguration->html()->highLowerBound();}}if (!isset($arguments['coveragePHP']) && $codeCoverageConfiguration->hasPhp()) {$arguments['coveragePHP'] = $codeCoverageConfiguration->php()->target()->path();}if (!isset($arguments['coverageText']) && $codeCoverageConfiguration->hasText()) {$arguments['coverageText'] = $codeCoverageConfiguration->text()->target()->path();$arguments['coverageTextShowUncoveredFiles'] = $codeCoverageConfiguration->text()->showUncoveredFiles();$arguments['coverageTextShowOnlySummary'] = $codeCoverageConfiguration->text()->showOnlySummary();}if (!isset($arguments['coverageXml']) && $codeCoverageConfiguration->hasXml()) {$arguments['coverageXml'] = $codeCoverageConfiguration->xml()->target()->path();}}$phpunitConfiguration = $arguments['configurationObject']->phpunit();$arguments['backupGlobals'] = $arguments['backupGlobals'] ?? $phpunitConfiguration->backupGlobals();$arguments['backupStaticAttributes'] = $arguments['backupStaticAttributes'] ?? $phpunitConfiguration->backupStaticAttributes();$arguments['beStrictAboutChangesToGlobalState'] = $arguments['beStrictAboutChangesToGlobalState'] ?? $phpunitConfiguration->beStrictAboutChangesToGlobalState();$arguments['cacheResult'] = $arguments['cacheResult'] ?? $phpunitConfiguration->cacheResult();$arguments['colors'] = $arguments['colors'] ?? $phpunitConfiguration->colors();$arguments['convertDeprecationsToExceptions'] = $arguments['convertDeprecationsToExceptions'] ?? $phpunitConfiguration->convertDeprecationsToExceptions();$arguments['convertErrorsToExceptions'] = $arguments['convertErrorsToExceptions'] ?? $phpunitConfiguration->convertErrorsToExceptions();$arguments['convertNoticesToExceptions'] = $arguments['convertNoticesToExceptions'] ?? $phpunitConfiguration->convertNoticesToExceptions();$arguments['convertWarningsToExceptions'] = $arguments['convertWarningsToExceptions'] ?? $phpunitConfiguration->convertWarningsToExceptions();$arguments['processIsolation'] = $arguments['processIsolation'] ?? $phpunitConfiguration->processIsolation();$arguments['stopOnDefect'] = $arguments['stopOnDefect'] ?? $phpunitConfiguration->stopOnDefect();$arguments['stopOnError'] = $arguments['stopOnError'] ?? $phpunitConfiguration->stopOnError();$arguments['stopOnFailure'] = $arguments['stopOnFailure'] ?? $phpunitConfiguration->stopOnFailure();$arguments['stopOnWarning'] = $arguments['stopOnWarning'] ?? $phpunitConfiguration->stopOnWarning();$arguments['stopOnIncomplete'] = $arguments['stopOnIncomplete'] ?? $phpunitConfiguration->stopOnIncomplete();$arguments['stopOnRisky'] = $arguments['stopOnRisky'] ?? $phpunitConfiguration->stopOnRisky();$arguments['stopOnSkipped'] = $arguments['stopOnSkipped'] ?? $phpunitConfiguration->stopOnSkipped();$arguments['failOnEmptyTestSuite'] = $arguments['failOnEmptyTestSuite'] ?? $phpunitConfiguration->failOnEmptyTestSuite();$arguments['failOnIncomplete'] = $arguments['failOnIncomplete'] ?? $phpunitConfiguration->failOnIncomplete();$arguments['failOnRisky'] = $arguments['failOnRisky'] ?? $phpunitConfiguration->failOnRisky();$arguments['failOnSkipped'] = $arguments['failOnSkipped'] ?? $phpunitConfiguration->failOnSkipped();$arguments['failOnWarning'] = $arguments['failOnWarning'] ?? $phpunitConfiguration->failOnWarning();$arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? $phpunitConfiguration->enforceTimeLimit();$arguments['defaultTimeLimit'] = $arguments['defaultTimeLimit'] ?? $phpunitConfiguration->defaultTimeLimit();$arguments['timeoutForSmallTests'] = $arguments['timeoutForSmallTests'] ?? $phpunitConfiguration->timeoutForSmallTests();$arguments['timeoutForMediumTests'] = $arguments['timeoutForMediumTests'] ?? $phpunitConfiguration->timeoutForMediumTests();$arguments['timeoutForLargeTests'] = $arguments['timeoutForLargeTests'] ?? $phpunitConfiguration->timeoutForLargeTests();$arguments['reportUselessTests'] = $arguments['reportUselessTests'] ?? $phpunitConfiguration->beStrictAboutTestsThatDoNotTestAnything();$arguments['strictCoverage'] = $arguments['strictCoverage'] ?? $phpunitConfiguration->beStrictAboutCoversAnnotation();$arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] = $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] ?? $codeCoverageConfiguration->ignoreDeprecatedCodeUnits();$arguments['disallowTestOutput'] = $arguments['disallowTestOutput'] ?? $phpunitConfiguration->beStrictAboutOutputDuringTests();$arguments['disallowTodoAnnotatedTests'] = $arguments['disallowTodoAnnotatedTests'] ?? $phpunitConfiguration->beStrictAboutTodoAnnotatedTests();$arguments['beStrictAboutResourceUsageDuringSmallTests'] = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? $phpunitConfiguration->beStrictAboutResourceUsageDuringSmallTests();$arguments['verbose'] = $arguments['verbose'] ?? $phpunitConfiguration->verbose();$arguments['reverseDefectList'] = $arguments['reverseDefectList'] ?? $phpunitConfiguration->reverseDefectList();$arguments['forceCoversAnnotation'] = $arguments['forceCoversAnnotation'] ?? $phpunitConfiguration->forceCoversAnnotation();$arguments['disableCodeCoverageIgnore'] = $arguments['disableCodeCoverageIgnore'] ?? $codeCoverageConfiguration->disableCodeCoverageIgnore();$arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? $phpunitConfiguration->registerMockObjectsFromTestArgumentsRecursively();$arguments['noInteraction'] = $arguments['noInteraction'] ?? $phpunitConfiguration->noInteraction();$arguments['executionOrder'] = $arguments['executionOrder'] ?? $phpunitConfiguration->executionOrder();$arguments['resolveDependencies'] = $arguments['resolveDependencies'] ?? $phpunitConfiguration->resolveDependencies();if (!isset($arguments['bootstrap']) && $phpunitConfiguration->hasBootstrap()) {$arguments['bootstrap'] = $phpunitConfiguration->bootstrap();}if (!isset($arguments['cacheResultFile']) && $phpunitConfiguration->hasCacheResultFile()) {$arguments['cacheResultFile'] = $phpunitConfiguration->cacheResultFile();}if (!isset($arguments['executionOrderDefects'])) {$arguments['executionOrderDefects'] = $phpunitConfiguration->defectsFirst() ? TestSuiteSorter::ORDER_DEFECTS_FIRST : TestSuiteSorter::ORDER_DEFAULT;}if ($phpunitConfiguration->conflictBetweenPrinterClassAndTestdox()) {$arguments['conflictBetweenPrinterClassAndTestdox'] = true;}$groupCliArgs = [];if (!empty($arguments['groups'])) {$groupCliArgs = $arguments['groups'];}$groupConfiguration = $arguments['configurationObject']->groups();if (!isset($arguments['groups']) && $groupConfiguration->hasInclude()) {$arguments['groups'] = $groupConfiguration->include()->asArrayOfStrings();}if (!isset($arguments['excludeGroups']) && $groupConfiguration->hasExclude()) {$arguments['excludeGroups'] = array_diff($groupConfiguration->exclude()->asArrayOfStrings(), $groupCliArgs);}if (!isset($this->arguments['noExtensions'])) {$extensionHandler = new ExtensionHandler;foreach ($arguments['configurationObject']->extensions() as $extension) {$extensionHandler->registerExtension($extension, $this);}foreach ($arguments['configurationObject']->listeners() as $listener) {$arguments['listeners'][] = $extensionHandler->createTestListenerInstance($listener);}unset($extensionHandler);}foreach ($arguments['unavailableExtensions'] as $extension) {$arguments['warnings'][] = sprintf('Extension "%s" is not available',$extension);}$loggingConfiguration = $arguments['configurationObject']->logging();if (!isset($arguments['noLogging'])) {if ($loggingConfiguration->hasText()) {$arguments['listeners'][] = new DefaultResultPrinter($loggingConfiguration->text()->target()->path(),true);}if (!isset($arguments['teamcityLogfile']) && $loggingConfiguration->hasTeamCity()) {$arguments['teamcityLogfile'] = $loggingConfiguration->teamCity()->target()->path();}if (!isset($arguments['junitLogfile']) && $loggingConfiguration->hasJunit()) {$arguments['junitLogfile'] = $loggingConfiguration->junit()->target()->path();}if (!isset($arguments['testdoxHTMLFile']) && $loggingConfiguration->hasTestDoxHtml()) {$arguments['testdoxHTMLFile'] = $loggingConfiguration->testDoxHtml()->target()->path();}if (!isset($arguments['testdoxTextFile']) && $loggingConfiguration->hasTestDoxText()) {$arguments['testdoxTextFile'] = $loggingConfiguration->testDoxText()->target()->path();}if (!isset($arguments['testdoxXMLFile']) && $loggingConfiguration->hasTestDoxXml()) {$arguments['testdoxXMLFile'] = $loggingConfiguration->testDoxXml()->target()->path();}}$testdoxGroupConfiguration = $arguments['configurationObject']->testdoxGroups();if (!isset($arguments['testdoxGroups']) && $testdoxGroupConfiguration->hasInclude()) {$arguments['testdoxGroups'] = $testdoxGroupConfiguration->include()->asArrayOfStrings();}if (!isset($arguments['testdoxExcludeGroups']) && $testdoxGroupConfiguration->hasExclude()) {$arguments['testdoxExcludeGroups'] = $testdoxGroupConfiguration->exclude()->asArrayOfStrings();}}$extensionHandler = new ExtensionHandler;foreach ($arguments['extensions'] as $extension) {$extensionHandler->registerExtension($extension, $this);}unset($extensionHandler);$arguments['backupGlobals'] = $arguments['backupGlobals'] ?? null;$arguments['backupStaticAttributes'] = $arguments['backupStaticAttributes'] ?? null;$arguments['beStrictAboutChangesToGlobalState'] = $arguments['beStrictAboutChangesToGlobalState'] ?? null;$arguments['beStrictAboutResourceUsageDuringSmallTests'] = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? false;$arguments['cacheResult'] = $arguments['cacheResult'] ?? true;$arguments['colors'] = $arguments['colors'] ?? DefaultResultPrinter::COLOR_DEFAULT;$arguments['columns'] = $arguments['columns'] ?? 80;$arguments['convertDeprecationsToExceptions'] = $arguments['convertDeprecationsToExceptions'] ?? false;$arguments['convertErrorsToExceptions'] = $arguments['convertErrorsToExceptions'] ?? true;$arguments['convertNoticesToExceptions'] = $arguments['convertNoticesToExceptions'] ?? true;$arguments['convertWarningsToExceptions'] = $arguments['convertWarningsToExceptions'] ?? true;$arguments['crap4jThreshold'] = $arguments['crap4jThreshold'] ?? 30;$arguments['disallowTestOutput'] = $arguments['disallowTestOutput'] ?? false;$arguments['disallowTodoAnnotatedTests'] = $arguments['disallowTodoAnnotatedTests'] ?? false;$arguments['defaultTimeLimit'] = $arguments['defaultTimeLimit'] ?? 0;$arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? false;$arguments['excludeGroups'] = $arguments['excludeGroups'] ?? [];$arguments['executionOrder'] = $arguments['executionOrder'] ?? TestSuiteSorter::ORDER_DEFAULT;$arguments['executionOrderDefects'] = $arguments['executionOrderDefects'] ?? TestSuiteSorter::ORDER_DEFAULT;$arguments['failOnIncomplete'] = $arguments['failOnIncomplete'] ?? false;$arguments['failOnRisky'] = $arguments['failOnRisky'] ?? false;$arguments['failOnSkipped'] = $arguments['failOnSkipped'] ?? false;$arguments['failOnWarning'] = $arguments['failOnWarning'] ?? false;$arguments['groups'] = $arguments['groups'] ?? [];$arguments['noInteraction'] = $arguments['noInteraction'] ?? false;$arguments['processIsolation'] = $arguments['processIsolation'] ?? false;$arguments['randomOrderSeed'] = $arguments['randomOrderSeed'] ?? time();$arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? false;$arguments['repeat'] = $arguments['repeat'] ?? false;$arguments['reportHighLowerBound'] = $arguments['reportHighLowerBound'] ?? 90;$arguments['reportLowUpperBound'] = $arguments['reportLowUpperBound'] ?? 50;$arguments['reportUselessTests'] = $arguments['reportUselessTests'] ?? true;$arguments['reverseList'] = $arguments['reverseList'] ?? false;$arguments['resolveDependencies'] = $arguments['resolveDependencies'] ?? true;$arguments['stopOnError'] = $arguments['stopOnError'] ?? false;$arguments['stopOnFailure'] = $arguments['stopOnFailure'] ?? false;$arguments['stopOnIncomplete'] = $arguments['stopOnIncomplete'] ?? false;$arguments['stopOnRisky'] = $arguments['stopOnRisky'] ?? false;$arguments['stopOnSkipped'] = $arguments['stopOnSkipped'] ?? false;$arguments['stopOnWarning'] = $arguments['stopOnWarning'] ?? false;$arguments['stopOnDefect'] = $arguments['stopOnDefect'] ?? false;$arguments['strictCoverage'] = $arguments['strictCoverage'] ?? false;$arguments['testdoxExcludeGroups'] = $arguments['testdoxExcludeGroups'] ?? [];$arguments['testdoxGroups'] = $arguments['testdoxGroups'] ?? [];$arguments['timeoutForLargeTests'] = $arguments['timeoutForLargeTests'] ?? 60;$arguments['timeoutForMediumTests'] = $arguments['timeoutForMediumTests'] ?? 10;$arguments['timeoutForSmallTests'] = $arguments['timeoutForSmallTests'] ?? 1;$arguments['verbose'] = $arguments['verbose'] ?? false;if ($arguments['reportLowUpperBound'] > $arguments['reportHighLowerBound']) {$arguments['reportLowUpperBound'] = 50;$arguments['reportHighLowerBound'] = 90;}}private function processSuiteFilters(TestSuite $suite, array $arguments): void{if (!$arguments['filter'] &&empty($arguments['groups']) &&empty($arguments['excludeGroups']) &&empty($arguments['testsCovering']) &&empty($arguments['testsUsing'])) {return;}$filterFactory = new Factory;if (!empty($arguments['excludeGroups'])) {$filterFactory->addFilter(new ReflectionClass(ExcludeGroupFilterIterator::class),$arguments['excludeGroups']);}if (!empty($arguments['groups'])) {$filterFactory->addFilter(new ReflectionClass(IncludeGroupFilterIterator::class),$arguments['groups']);}if (!empty($arguments['testsCovering'])) {$filterFactory->addFilter(new ReflectionClass(IncludeGroupFilterIterator::class),array_map(static function (string $name): string{return '__phpunit_covers_' . $name;},$arguments['testsCovering']));}if (!empty($arguments['testsUsing'])) {$filterFactory->addFilter(new ReflectionClass(IncludeGroupFilterIterator::class),array_map(static function (string $name): string{return '__phpunit_uses_' . $name;},$arguments['testsUsing']));}if ($arguments['filter']) {$filterFactory->addFilter(new ReflectionClass(NameFilterIterator::class),$arguments['filter']);}$suite->injectFilter($filterFactory);}private function writeMessage(string $type, string $message): void{if (!$this->messagePrinted) {$this->write("\n");}$this->write(sprintf("%-15s%s\n",$type . ':',$message));$this->messagePrinted = true;}private function createPrinter(string $class, array $arguments): ResultPrinter{$object = new $class((isset($arguments['stderr']) && $arguments['stderr'] === true) ? 'php://stderr' : null,$arguments['verbose'],$arguments['colors'],$arguments['debug'],$arguments['columns'],$arguments['reverseList']);assert($object instanceof ResultPrinter);return $object;}private function codeCoverageGenerationStart(string $format): void{$this->write(sprintf("\nGenerating code coverage report in %s format ... ",$format));$this->timer->start();}private function codeCoverageGenerationSucceeded(): void{$this->write(sprintf("done [%s]\n",$this->timer->stop()->asString()));}private function codeCoverageGenerationFailed(\Exception $e): void{$this->write(sprintf("failed [%s]\n%s\n",$this->timer->stop()->asString(),$e->getMessage()));}}