diff --git a/src/Actions/AddsDefaults.php b/src/Actions/AddsDefaults.php index 9a177a46..f16b8879 100644 --- a/src/Actions/AddsDefaults.php +++ b/src/Actions/AddsDefaults.php @@ -30,7 +30,7 @@ final class AddsDefaults } if ($arguments[self::PRINTER] === \PHPUnit\Util\Log\TeamCity::class) { - $arguments[self::PRINTER] = new TeamCity($arguments['verbose'] ?? false, $arguments['colors'] ?? DefaultResultPrinter::COLOR_ALWAYS); + $arguments[self::PRINTER] = new TeamCity(null, $arguments['verbose'] ?? false, $arguments['colors'] ?? DefaultResultPrinter::COLOR_ALWAYS); } // Load our junit logger instead. diff --git a/src/Logging/TeamCity.php b/src/Logging/TeamCity.php index 63cf7245..97db03e0 100644 --- a/src/Logging/TeamCity.php +++ b/src/Logging/TeamCity.php @@ -17,6 +17,7 @@ use PHPUnit\Runner\PhptTestCase; use PHPUnit\TextUI\DefaultResultPrinter; use function round; use function str_replace; +use function strlen; use Throwable; final class TeamCity extends DefaultResultPrinter @@ -45,11 +46,14 @@ final class TeamCity extends DefaultResultPrinter */ protected $outputStack = []; - public function __construct(bool $verbose, string $colors) + /** + * @param resource|string|null $out + */ + public function __construct($out, bool $verbose, string $colors) { - parent::__construct(null, $verbose, $colors, false, 80, false); + parent::__construct($out, $verbose, $colors, false, 80, false); $this->phpunitTeamCity = new \PHPUnit\Util\Log\TeamCity( - null, + $out, $verbose, $colors, false, @@ -76,7 +80,7 @@ final class TeamCity extends DefaultResultPrinter /** @phpstan-ignore-next-line */ public function startTestSuite(TestSuite $suite): void { - if (str_starts_with($suite->getName(), 'P\\')) { + if (static::isPestTestSuite($suite)) { $this->writeWithColor('fg-white, bold', ' ' . substr_replace($suite->getName(), '', 0, 2) . ' '); } @@ -116,7 +120,7 @@ final class TeamCity extends DefaultResultPrinter { $suiteName = $suite->getName(); - if (str_starts_with($suiteName, 'P\\')) { + if (static::isPestTestSuite($suite)) { $this->writeNewLine(); } @@ -348,4 +352,14 @@ final class TeamCity extends DefaultResultPrinter return in_array(Testable::class, $uses, true); } + + /** + * Verify that the given test suite is a valid Pest suite. + * + * @param TestSuite $suite + */ + private static function isPestTestSuite(TestSuite $suite): bool + { + return strncmp($suite->getName(), 'P\\', strlen('P\\')) === 0; + } } diff --git a/tests/Visual/JUnit.php b/tests/Visual/JUnit.php new file mode 100644 index 00000000..a12d561f --- /dev/null +++ b/tests/Visual/JUnit.php @@ -0,0 +1,29 @@ +startTestSuite(new TestSuite()); + $junit->startTest($this); + $junit->addError($this, new Exception(), 0); + $junit->addFailure($this, new AssertionFailedError(), 0); + $junit->addWarning($this, new Warning(), 0); + $junit->addIncompleteTest($this, new Exception(), 0); + $junit->addRiskyTest($this, new Exception(), 0); + $junit->addSkippedTest($this, new Exception(), 0); + $junit->endTest($this, 0); + $junit->endTestSuite(new TestSuite()); + $this->expectNotToPerformAssertions(); +}); + +afterEach(function () { + unlink(__DIR__ . '/junit.html'); +}); diff --git a/tests/Visual/TeamCity.php b/tests/Visual/TeamCity.php new file mode 100644 index 00000000..1681f1ac --- /dev/null +++ b/tests/Visual/TeamCity.php @@ -0,0 +1,32 @@ +toBeTrue(); + $teamCity->startTestSuite(new TestSuite()); + $teamCity->startTest($this); + $teamCity->addError($this, new Exception('Don\'t worry about this error. Its purposeful.'), 0); + $teamCity->addFailure($this, new AssertionFailedError('Don\'t worry about this error. Its purposeful.'), 0); + $teamCity->addWarning($this, new Warning(), 0); + $teamCity->addIncompleteTest($this, new Exception(), 0); + $teamCity->addRiskyTest($this, new Exception(), 0); + $teamCity->addSkippedTest($this, new Exception(), 0); + $teamCity->endTest($this, 0); + $teamCity->printResult(new TestResult()); + $teamCity->endTestSuite(new TestSuite()); +}); + +afterEach(function () { + unlink(__DIR__ . '/output.txt'); +});