Skip to content

Commit

Permalink
Initial work on #4321
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Jun 3, 2023
1 parent a8283e4 commit 62c8095
Show file tree
Hide file tree
Showing 21 changed files with 298 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .psalm/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,8 @@
)]]></code>
<code><![CDATA[OutputFacade::printerFor($configuration->logfileJunit())]]></code>
<code><![CDATA[OutputFacade::printerFor($configuration->logfileJunit())]]></code>
<code><![CDATA[OutputFacade::printerFor($configuration->logfileXml())]]></code>
<code><![CDATA[OutputFacade::printerFor($configuration->logfileXml())]]></code>
<code>atLeastVersion</code>
<code>build</code>
<code>configurationFile</code>
Expand All @@ -588,6 +590,7 @@
<code>logEventsVerboseText</code>
<code>logfileJunit</code>
<code>logfileTeamcity</code>
<code>logfileXml</code>
</MissingThrowsDocblock>
<UnresolvableInclude>
<code>include_once $filename</code>
Expand Down
1 change: 1 addition & 0 deletions phpunit.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@
</xs:group>
<xs:group name="loggingGroup">
<xs:all>
<xs:element name="xml" type="logToFileType" minOccurs="0" />
<xs:element name="junit" type="logToFileType" minOccurs="0" />
<xs:element name="teamcity" type="logToFileType" minOccurs="0" />
<xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" />
Expand Down
28 changes: 28 additions & 0 deletions src/Logging/Xml/Subscriber/Subscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Logging\Xml;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
abstract class Subscriber
{
private readonly XmlLogger $logger;

public function __construct(XmlLogger $logger)
{
$this->logger = $logger;
}

protected function logger(): XmlLogger
{
return $this->logger;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Logging\Xml;

use PHPUnit\Event\TestRunner\ExecutionFinished;
use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class TestRunnerExecutionFinishedSubscriber extends Subscriber implements ExecutionFinishedSubscriber
{
public function notify(ExecutionFinished $event): void
{
$this->logger()->flush();
}
}
52 changes: 52 additions & 0 deletions src/Logging/Xml/XmlLogger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Logging\Xml;

use PHPUnit\Event\EventFacadeIsSealedException;
use PHPUnit\Event\Facade;
use PHPUnit\Event\UnknownSubscriberTypeException;
use PHPUnit\TextUI\Output\Printer;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class XmlLogger
{
private readonly Printer $printer;

/**
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
*/
public function __construct(Printer $printer, Facade $facade)
{
$this->printer = $printer;

$this->registerSubscribers($facade);
}

public function flush(): void
{
$this->printer->print('todo');

$this->printer->flush();
}

/**
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
*/
private function registerSubscribers(Facade $facade): void
{
$facade->registerSubscribers(
new TestRunnerExecutionFinishedSubscriber($this),
);
}
}
8 changes: 8 additions & 0 deletions src/TextUI/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use PHPUnit\Logging\TestDox\HtmlRenderer as TestDoxHtmlRenderer;
use PHPUnit\Logging\TestDox\PlainTextRenderer as TestDoxTextRenderer;
use PHPUnit\Logging\TestDox\TestResultCollector as TestDoxResultCollector;
use PHPUnit\Logging\Xml\XmlLogger;
use PHPUnit\Metadata\Api\CodeCoverage as CodeCoverageMetadataApi;
use PHPUnit\Runner\CodeCoverage;
use PHPUnit\Runner\Extension\ExtensionBootstrapper;
Expand Down Expand Up @@ -540,6 +541,13 @@ private function registerLogfileWriters(Configuration $configuration): void
);
}

if ($configuration->hasLogfileXml()) {
new XmlLogger(
OutputFacade::printerFor($configuration->logfileXml()),
EventFacade::instance(),
);
}

if ($configuration->hasLogfileJunit()) {
new JunitXmlLogger(
OutputFacade::printerFor($configuration->logfileJunit()),
Expand Down
8 changes: 8 additions & 0 deletions src/TextUI/Configuration/Cli/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ final class Builder
'list-tests-xml=',
'log-junit=',
'log-teamcity=',
'log-xml=',
'migrate-configuration',
'no-configuration',
'no-coverage',
Expand Down Expand Up @@ -203,6 +204,7 @@ public function fromParameters(array $parameters): Configuration
$includePath = null;
$iniSettings = [];
$junitLogfile = null;
$xmlLogfile = null;
$listGroups = false;
$listSuites = false;
$listTests = false;
Expand Down Expand Up @@ -444,6 +446,11 @@ public function fromParameters(array $parameters): Configuration

break;

case '--log-xml':
$xmlLogfile = $option[1];

break;

case '--order-by':
foreach (explode(',', $option[1]) as $order) {
switch ($order) {
Expand Down Expand Up @@ -853,6 +860,7 @@ public function fromParameters(array $parameters): Configuration
$help,
$includePath,
$iniSettings,
$xmlLogfile,
$junitLogfile,
$listGroups,
$listSuites,
Expand Down
24 changes: 23 additions & 1 deletion src/TextUI/Configuration/Cli/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ final class Configuration
private readonly bool $help;
private readonly ?string $includePath;
private readonly ?array $iniSettings;
private readonly ?string $xmlLogfile;
private readonly ?string $junitLogfile;
private readonly bool $listGroups;
private readonly bool $listSuites;
Expand Down Expand Up @@ -118,7 +119,7 @@ final class Configuration
/**
* @psalm-param ?non-empty-list<string> $testSuffixes
*/
public function __construct(?string $argument, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, ?string $cacheResultFile, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, ?string $coverageCacheDirectory, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnDeprecation, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $printerTestDox)
public function __construct(?string $argument, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, ?string $cacheResultFile, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, ?string $coverageCacheDirectory, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnDeprecation, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, bool $help, ?string $includePath, ?array $iniSettings, ?string $xmlLogfile, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $printerTestDox)
{
$this->argument = $argument;
$this->atLeastVersion = $atLeastVersion;
Expand Down Expand Up @@ -178,6 +179,7 @@ public function __construct(?string $argument, ?string $atLeastVersion, ?bool $b
$this->help = $help;
$this->includePath = $includePath;
$this->iniSettings = $iniSettings;
$this->xmlLogfile = $xmlLogfile;
$this->junitLogfile = $junitLogfile;
$this->listGroups = $listGroups;
$this->listSuites = $listSuites;
Expand Down Expand Up @@ -1301,6 +1303,26 @@ public function iniSettings(): array
return $this->iniSettings;
}

/**
* @psalm-assert-if-true !null $this->xmlLogfile
*/
public function hasXmlLogfile(): bool
{
return $this->xmlLogfile !== null;
}

/**
* @throws Exception
*/
public function xmlLogfile(): string
{
if (!$this->hasXmlLogfile()) {
throw new Exception;
}

return $this->xmlLogfile;
}

/**
* @psalm-assert-if-true !null $this->junitLogfile
*/
Expand Down
24 changes: 23 additions & 1 deletion src/TextUI/Configuration/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ final class Configuration
private readonly ?string $logfileJunit;
private readonly ?string $logfileTestdoxHtml;
private readonly ?string $logfileTestdoxText;
private readonly ?string $logfileXml;
private readonly ?string $logEventsText;
private readonly ?string $logEventsVerboseText;
private readonly ?array $testsCovering;
Expand All @@ -132,7 +133,7 @@ final class Configuration
* @psalm-param non-empty-list<string> $testSuffixes
* @psalm-param list<array{className: class-string, parameters: array<string, string>}> $extensionBootstrappers
*/
public function __construct(?string $cliArgument, ?string $configurationFile, ?string $bootstrap, bool $cacheResult, ?string $cacheDirectory, ?string $coverageCacheDirectory, Source $source, string $testResultCacheFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4j, int $coverageCrap4jThreshold, ?string $coverageHtml, int $coverageHtmlLowUpperBound, int $coverageHtmlHighLowerBound, string $coverageHtmlColorSuccessLow, string $coverageHtmlColorSuccessMedium, string $coverageHtmlColorSuccessHigh, string $coverageHtmlColorWarning, string $coverageHtmlColorDanger, ?string $coverageHtmlCustomCssFile, ?string $coveragePhp, ?string $coverageText, bool $coverageTextShowUncoveredFiles, bool $coverageTextShowOnlySummary, ?string $coverageXml, bool $pathCoverage, bool $ignoreDeprecatedCodeUnitsFromCodeCoverage, bool $disableCodeCoverageIgnore, bool $failOnDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnDeprecation, bool $stopOnError, bool $stopOnFailure, bool $stopOnIncomplete, bool $stopOnNotice, bool $stopOnRisky, bool $stopOnSkipped, bool $stopOnWarning, bool $outputToStandardErrorStream, int|string $columns, bool $noExtensions, ?string $pharExtensionDirectory, array $extensionBootstrappers, bool $backupGlobals, bool $backupStaticProperties, bool $beStrictAboutChangesToGlobalState, bool $colors, bool $processIsolation, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, bool $reportUselessTests, bool $strictCoverage, bool $disallowTestOutput, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $reverseDefectList, bool $requireCoverageMetadata, bool $registerMockObjectsFromTestArgumentsRecursively, bool $noProgress, bool $noResults, bool $noOutput, int $executionOrder, int $executionOrderDefects, bool $resolveDependencies, ?string $logfileTeamcity, ?string $logfileJunit, ?string $logfileTestdoxHtml, ?string $logfileTestdoxText, ?string $logEventsText, ?string $logEventsVerboseText, bool $teamCityOutput, bool $testDoxOutput, ?array $testsCovering, ?array $testsUsing, ?string $filter, ?array $groups, ?array $excludeGroups, int $randomOrderSeed, bool $includeUncoveredFiles, TestSuiteCollection $testSuite, string $includeTestSuite, string $excludeTestSuite, ?string $defaultTestSuite, array $testSuffixes, Php $php)
public function __construct(?string $cliArgument, ?string $configurationFile, ?string $bootstrap, bool $cacheResult, ?string $cacheDirectory, ?string $coverageCacheDirectory, Source $source, string $testResultCacheFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4j, int $coverageCrap4jThreshold, ?string $coverageHtml, int $coverageHtmlLowUpperBound, int $coverageHtmlHighLowerBound, string $coverageHtmlColorSuccessLow, string $coverageHtmlColorSuccessMedium, string $coverageHtmlColorSuccessHigh, string $coverageHtmlColorWarning, string $coverageHtmlColorDanger, ?string $coverageHtmlCustomCssFile, ?string $coveragePhp, ?string $coverageText, bool $coverageTextShowUncoveredFiles, bool $coverageTextShowOnlySummary, ?string $coverageXml, bool $pathCoverage, bool $ignoreDeprecatedCodeUnitsFromCodeCoverage, bool $disableCodeCoverageIgnore, bool $failOnDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnDeprecation, bool $stopOnError, bool $stopOnFailure, bool $stopOnIncomplete, bool $stopOnNotice, bool $stopOnRisky, bool $stopOnSkipped, bool $stopOnWarning, bool $outputToStandardErrorStream, int|string $columns, bool $noExtensions, ?string $pharExtensionDirectory, array $extensionBootstrappers, bool $backupGlobals, bool $backupStaticProperties, bool $beStrictAboutChangesToGlobalState, bool $colors, bool $processIsolation, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, bool $reportUselessTests, bool $strictCoverage, bool $disallowTestOutput, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $reverseDefectList, bool $requireCoverageMetadata, bool $registerMockObjectsFromTestArgumentsRecursively, bool $noProgress, bool $noResults, bool $noOutput, int $executionOrder, int $executionOrderDefects, bool $resolveDependencies, ?string $logfileTeamcity, ?string $logfileJunit, ?string $logfileTestdoxHtml, ?string $logfileTestdoxText, ?string $logfileXml, ?string $logEventsText, ?string $logEventsVerboseText, bool $teamCityOutput, bool $testDoxOutput, ?array $testsCovering, ?array $testsUsing, ?string $filter, ?array $groups, ?array $excludeGroups, int $randomOrderSeed, bool $includeUncoveredFiles, TestSuiteCollection $testSuite, string $includeTestSuite, string $excludeTestSuite, ?string $defaultTestSuite, array $testSuffixes, Php $php)
{
$this->cliArgument = $cliArgument;
$this->configurationFile = $configurationFile;
Expand Down Expand Up @@ -216,6 +217,7 @@ public function __construct(?string $cliArgument, ?string $configurationFile, ?s
$this->logfileJunit = $logfileJunit;
$this->logfileTestdoxHtml = $logfileTestdoxHtml;
$this->logfileTestdoxText = $logfileTestdoxText;
$this->logfileXml = $logfileXml;
$this->logEventsText = $logEventsText;
$this->logEventsVerboseText = $logEventsVerboseText;
$this->teamCityOutput = $teamCityOutput;
Expand Down Expand Up @@ -1001,6 +1003,26 @@ public function logfileTestdoxText(): string
return $this->logfileTestdoxText;
}

/**
* @psalm-assert-if-true !null $this->logfileXml
*/
public function hasLogfileXml(): bool
{
return $this->logfileXml !== null;
}

/**
* @throws LoggingNotConfiguredException
*/
public function logfileXml(): string
{
if (!$this->hasLogfileXml()) {
throw new LoggingNotConfiguredException;
}

return $this->logfileXml;
}

/**
* @psalm-assert-if-true !null $this->logEventsText
*/
Expand Down
Loading

0 comments on commit 62c8095

Please sign in to comment.