diff --git a/src/Plugins/Coverage.php b/src/Plugins/Coverage.php index 712f5de5..ed7b1214 100644 --- a/src/Plugins/Coverage.php +++ b/src/Plugins/Coverage.php @@ -23,6 +23,8 @@ final class Coverage implements AddsOutput, HandlesArguments private const string EXACTLY_OPTION = 'exactly'; + private const string ONLY_COVERED_OPTION = 'only-covered'; + /** * Whether it should show the coverage or not. */ @@ -43,6 +45,11 @@ final class Coverage implements AddsOutput, HandlesArguments */ public ?float $coverageExactly = null; + /** + * Whether it should show only covered files. + */ + public bool $showOnlyCovered = false; + /** * Creates a new Plugin instance. */ @@ -57,7 +64,7 @@ public function __construct(private readonly OutputInterface $output) public function handleArguments(array $originals): array { $arguments = [...[''], ...array_values(array_filter($originals, function (string $original): bool { - foreach ([self::COVERAGE_OPTION, self::MIN_OPTION, self::EXACTLY_OPTION] as $option) { + foreach ([self::COVERAGE_OPTION, self::MIN_OPTION, self::EXACTLY_OPTION, self::ONLY_COVERED_OPTION] as $option) { if ($original === sprintf('--%s', $option)) { return true; } @@ -80,6 +87,7 @@ public function handleArguments(array $originals): array $inputs[] = new InputOption(self::COVERAGE_OPTION, null, InputOption::VALUE_NONE); $inputs[] = new InputOption(self::MIN_OPTION, null, InputOption::VALUE_REQUIRED); $inputs[] = new InputOption(self::EXACTLY_OPTION, null, InputOption::VALUE_REQUIRED); + $inputs[] = new InputOption(self::ONLY_COVERED_OPTION, null, InputOption::VALUE_NONE); $input = new ArgvInput($arguments, new InputDefinition($inputs)); if ((bool) $input->getOption(self::COVERAGE_OPTION)) { @@ -120,6 +128,10 @@ public function handleArguments(array $originals): array $this->coverageExactly = (float) $exactlyOption; } + if ((bool) $input->getOption(self::ONLY_COVERED_OPTION)) { + $this->showOnlyCovered = true; + } + if ($_SERVER['COLLISION_PRINTER_COMPACT'] ?? false) { $this->compact = true; } @@ -144,7 +156,7 @@ public function addOutput(int $exitCode): int exit(1); } - $coverage = \Pest\Support\Coverage::report($this->output, $this->compact); + $coverage = \Pest\Support\Coverage::report($this->output, $this->compact, $this->showOnlyCovered); $exitCode = (int) ($coverage < $this->coverageMin); if ($exitCode === 0 && $this->coverageExactly !== null) { diff --git a/src/Plugins/Help.php b/src/Plugins/Help.php index 096f2914..54baf705 100644 --- a/src/Plugins/Help.php +++ b/src/Plugins/Help.php @@ -160,6 +160,12 @@ private function getContent(): array ], [ 'arg' => '--coverage --min', 'desc' => 'Set the minimum required coverage percentage, and fail if not met', + ], [ + 'arg' => '--coverage --exactly', + 'desc' => 'Set the exact required coverage percentage, and fail if not met', + ], [ + 'arg' => '--coverage --only-covered', + 'desc' => 'Hide files with 0% coverage from the code coverage report', ], ...$content['Code Coverage']]; $content['Mutation Testing'] = [[ diff --git a/src/Support/Coverage.php b/src/Support/Coverage.php index 955bbfc4..a36dd8ed 100644 --- a/src/Support/Coverage.php +++ b/src/Support/Coverage.php @@ -74,7 +74,7 @@ public static function usingXdebug(): bool * Reports the code coverage report to the * console and returns the result in float. */ - public static function report(OutputInterface $output, bool $compact = false): float + public static function report(OutputInterface $output, bool $compact = false, bool $showOnlyCovered = false): float { if (! file_exists($reportPath = self::getPath())) { if (self::usingXdebug()) { @@ -109,6 +109,10 @@ public static function report(OutputInterface $output, bool $compact = false): f $basename, ]); + if ($showOnlyCovered && $file->percentageOfExecutedLines()->asFloat() === 0.0) { + continue; + } + $percentage = $file->numberOfExecutableLines() === 0 ? '100.0' : number_format($file->percentageOfExecutedLines()->asFloat(), 1, '.', '');