From 268d5b2b4237c0abf76c4aa9633ad8580be01e1e Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Tue, 27 Apr 2021 11:24:27 +0200 Subject: [PATCH] Add support to write coverage text to file (#609) * Add support to write coverage text to file * Fixed tests * Fixed tests better =) * Make static analyzers happy * Fixed last (?) test * More fixes... * All green locally * Added an extra test * cs * Support coverage text to file from XML configuration Co-authored-by: Filippo Tessarotto --- phpstan-baseline.neon | 2 +- src/Runners/PHPUnit/BaseRunner.php | 9 +++++++-- src/Runners/PHPUnit/Options.php | 21 ++++++++++++-------- test/TestBase.php | 4 ++-- test/Unit/Runners/PHPUnit/BaseRunnerTest.php | 21 +++++++++++++++++++- test/Unit/Runners/PHPUnit/OptionsTest.php | 10 ++++++---- 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 16c38e22..d98346c8 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -100,7 +100,7 @@ parameters: path: src/Runners/PHPUnit/Options.php - - message: "#^Parameter \\#10 \\$coverageText of class ParaTest\\\\Runners\\\\PHPUnit\\\\Options constructor expects bool, array\\\\|bool\\|int\\|string\\|null given\\.$#" + message: "#^Parameter \\#10 \\$coverageText of class ParaTest\\\\Runners\\\\PHPUnit\\\\Options constructor expects string|null, array\\\\|int\\|string\\|true\\|null given\\.$#" count: 1 path: src/Runners/PHPUnit/Options.php diff --git a/src/Runners/PHPUnit/BaseRunner.php b/src/Runners/PHPUnit/BaseRunner.php index 340ddebb..bda64ab9 100644 --- a/src/Runners/PHPUnit/BaseRunner.php +++ b/src/Runners/PHPUnit/BaseRunner.php @@ -13,6 +13,7 @@ use function array_reverse; use function assert; +use function file_put_contents; use function mt_srand; use function shuffle; use function sprintf; @@ -204,8 +205,12 @@ final protected function logCoverage(): void $reporter->html($coverageHtml); } - if ($this->options->coverageText()) { - $this->output->write($reporter->text()); + if (($coverageText = $this->options->coverageText()) !== null) { + if ($coverageText === '') { + $this->output->write($reporter->text()); + } else { + file_put_contents($coverageText, $reporter->text()); + } } if (($coverageXml = $this->options->coverageXml()) !== null) { diff --git a/src/Runners/PHPUnit/Options.php b/src/Runners/PHPUnit/Options.php index db32199a..e74f28d8 100644 --- a/src/Runners/PHPUnit/Options.php +++ b/src/Runners/PHPUnit/Options.php @@ -199,7 +199,7 @@ final class Options private $coverageHtml; /** @var string|null */ private $coveragePhp; - /** @var bool */ + /** @var string|null */ private $coverageText; /** @var string|null */ private $coverageXml; @@ -240,7 +240,7 @@ private function __construct( ?string $coverageHtml, ?string $coveragePhp, int $coverageTestLimit, - bool $coverageText, + ?string $coverageText, ?string $coverageXml, string $cwd, array $excludeGroup, @@ -321,7 +321,7 @@ public static function fromConsoleInput(InputInterface $input, string $cwd): sel assert($options['coverage-crap4j'] === null || is_string($options['coverage-crap4j'])); assert($options['coverage-html'] === null || is_string($options['coverage-html'])); assert($options['coverage-php'] === null || is_string($options['coverage-php'])); - assert(is_bool($options['coverage-text'])); + assert($options['coverage-text'] === false || $options['coverage-text'] === null || is_string($options['coverage-text'])); assert($options['coverage-xml'] === null || is_string($options['coverage-xml'])); assert($options['filter'] === null || is_string($options['filter'])); assert(is_bool($options['functional'])); @@ -456,6 +456,10 @@ public static function fromConsoleInput(InputInterface $input, string $cwd): sel $codeCoverage = $configuration->codeCoverage(); + if ($options['coverage-text'] === false && $codeCoverage->hasText()) { + $options['coverage-text'] = $codeCoverage->text()->target()->path(); + } + if ($options['coverage-clover'] === null && $codeCoverage->hasClover()) { $options['coverage-clover'] = $codeCoverage->clover()->target()->path(); } @@ -526,7 +530,7 @@ public static function fromConsoleInput(InputInterface $input, string $cwd): sel $options['coverage-html'], $options['coverage-php'], (int) $options['coverage-test-limit'], - $options['coverage-text'], + $options['coverage-text'] === false ? null : $options['coverage-text'] ?? '', $options['coverage-xml'], $cwd, $excludeGroup, @@ -567,7 +571,7 @@ public function hasCoverage(): bool || $this->coverageCobertura !== null || $this->coverageCrap4j !== null || $this->coverageHtml !== null - || $this->coverageText + || $this->coverageText !== null || $this->coveragePhp !== null || $this->coverageXml !== null; } @@ -641,8 +645,9 @@ public static function setInputDefinition(InputDefinition $inputDefinition): voi new InputOption( 'coverage-text', null, - InputOption::VALUE_NONE, - 'Generate code coverage report in text format.' + InputOption::VALUE_OPTIONAL, + 'Generate code coverage report in text format.', + false ), new InputOption( 'coverage-xml', @@ -1058,7 +1063,7 @@ public function coveragePhp(): ?string return $this->coveragePhp; } - public function coverageText(): bool + public function coverageText(): ?string { return $this->coverageText; } diff --git a/test/TestBase.php b/test/TestBase.php index c0666c70..d51a2e93 100644 --- a/test/TestBase.php +++ b/test/TestBase.php @@ -25,7 +25,7 @@ abstract class TestBase extends PHPUnit\Framework\TestCase { /** @var class-string */ protected $runnerClass = Runner::class; - /** @var array */ + /** @var array */ protected $bareOptions = []; final protected function setUp(): void @@ -43,7 +43,7 @@ protected function setUpTest(): void } /** - * @param array $argv + * @param array $argv */ final protected function createOptionsFromArgv(array $argv, ?string $cwd = null): Options { diff --git a/test/Unit/Runners/PHPUnit/BaseRunnerTest.php b/test/Unit/Runners/PHPUnit/BaseRunnerTest.php index 67106127..4a1e8dd6 100644 --- a/test/Unit/Runners/PHPUnit/BaseRunnerTest.php +++ b/test/Unit/Runners/PHPUnit/BaseRunnerTest.php @@ -29,7 +29,7 @@ protected function setUpTest(): void '--coverage-crap4j' => TMP_DIR . DS . 'coverage.crap4j', '--coverage-html' => TMP_DIR . DS . 'coverage.html', '--coverage-php' => TMP_DIR . DS . 'coverage.php', - '--coverage-text' => true, + '--coverage-text' => null, '--coverage-xml' => TMP_DIR . DS . 'coverage.xml', '--bootstrap' => BOOTSTRAP, '--whitelist' => $this->fixture('failing_tests'), @@ -70,6 +70,25 @@ public function testGeneratesCoverageTypes(): void static::assertStringContainsString('Generating code coverage', $runnerResult->getOutput()); } + public function testGeneateTextCoverageToFile(): void + { + $file = TMP_DIR . DS . 'coverage.txt'; + $this->bareOptions = [ + '--path' => $this->fixture('failing_tests'), + '--coverage-text' => $file, + '--bootstrap' => BOOTSTRAP, + '--whitelist' => $this->fixture('failing_tests'), + ]; + + static::assertFileDoesNotExist($file); + $this->bareOptions['--configuration'] = $this->fixture('phpunit-fully-configured.xml'); + $runnerResult = $this->runRunner(); + + static::assertFileExists($file); + static::assertStringNotContainsString('Code Coverage Report:', $runnerResult->getOutput()); + static::assertStringContainsString('Generating code coverage', $runnerResult->getOutput()); + } + public function testRunningTestsShouldLeaveNoTempFiles(): void { // Needed for one line coverage on early exit CS Fix :\ diff --git a/test/Unit/Runners/PHPUnit/OptionsTest.php b/test/Unit/Runners/PHPUnit/OptionsTest.php index a3c852c9..3a341d24 100644 --- a/test/Unit/Runners/PHPUnit/OptionsTest.php +++ b/test/Unit/Runners/PHPUnit/OptionsTest.php @@ -237,7 +237,7 @@ public function testDefaultOptions(): void static::assertNull($options->coverageHtml()); static::assertNull($options->coveragePhp()); static::assertSame(0, $options->coverageTestLimit()); - static::assertFalse($options->coverageText()); + static::assertNull($options->coverageText()); static::assertNull($options->coverageXml()); static::assertSame(__DIR__, $options->cwd()); static::assertEmpty($options->excludeGroup()); @@ -281,7 +281,7 @@ public function testProvidedOptions(): void '--coverage-html' => 'COVERAGE-HTML', '--coverage-php' => 'COVERAGE-PHP', '--coverage-test-limit' => 3, - '--coverage-text' => true, + '--coverage-text' => null, '--coverage-xml' => 'COVERAGE-XML', '--exclude-group' => 'EXCLUDE-GROUP', '--filter' => 'FILTER', @@ -318,7 +318,7 @@ public function testProvidedOptions(): void static::assertSame('COVERAGE-HTML', $options->coverageHtml()); static::assertSame('COVERAGE-PHP', $options->coveragePhp()); static::assertSame(3, $options->coverageTestLimit()); - static::assertTrue($options->coverageText()); + static::assertSame('', $options->coverageText()); static::assertSame('COVERAGE-XML', $options->coverageXml()); static::assertSame(__DIR__, $options->cwd()); static::assertSame(['EXCLUDE-GROUP'], $options->excludeGroup()); @@ -389,6 +389,8 @@ public function testGatherOptionsFromConfiguration(): void static::assertStringContainsString('coverage.php', $options->coveragePhp()); static::assertNotNull($options->coverageXml()); static::assertStringContainsString('xml-coverage', $options->coverageXml()); + static::assertNotNull($options->coverageText()); + static::assertStringContainsString('coverage.txt', $options->coverageText()); static::assertNotNull($options->logJunit()); static::assertStringContainsString('junit.xml', $options->logJunit()); @@ -403,7 +405,7 @@ public function testNoCoverageOptionDisablesCoverageOptions(): void '--coverage-crap4j' => 'COVERAGE-CRAP4J', '--coverage-html' => 'COVERAGE-HTML', '--coverage-php' => 'COVERAGE-PHP', - '--coverage-text' => true, + '--coverage-text' => false, '--coverage-xml' => 'COVERAGE-XML', '--no-coverage' => true, ];