Skip to content

Commit

Permalink
Show ignored mutants on progress and summary (#1612)
Browse files Browse the repository at this point in the history
* Show ignored mutants count in metrics and logs

* Fix Exclude_Mutations_By_Regex e2e test

* Fix syntax error in YieldValue e2e test
  • Loading branch information
sidz committed Dec 13, 2021
1 parent 616b406 commit 17a3d98
Show file tree
Hide file tree
Showing 58 changed files with 289 additions and 60 deletions.
7 changes: 1 addition & 6 deletions infection.json
Expand Up @@ -12,11 +12,6 @@
}
},
"mutators": {
"@default": true,
"MethodCallRemoval": {
"ignore": [
"Infection\\Finder\\SourceFilesFinder::__construct::63"
]
}
"@default": true
}
}
7 changes: 6 additions & 1 deletion src/Console/OutputFormatter/DotFormatter.php
Expand Up @@ -68,7 +68,8 @@ public function start(int $mutationCount): void
. '<with-error>E</with-error>: fatal error, '
. '<with-syntax-error>X</with-syntax-error>: syntax error, '
. '<timeout>T</timeout>: timed out, '
. '<skipped>S</skipped>: skipped',
. '<skipped>S</skipped>: skipped, '
. '<ignored>I</ignored>: ignored',
'',
]);
}
Expand Down Expand Up @@ -105,6 +106,10 @@ public function advance(MutantExecutionResult $executionResult, int $mutationCou
case DetectionStatus::SYNTAX_ERROR:
$this->output->write('<with-syntax-error>X</with-syntax-error>');

break;
case DetectionStatus::IGNORED:
$this->output->write('<ignored>I</ignored>');

break;
}

Expand Down
11 changes: 3 additions & 8 deletions src/Console/OutputFormatterStyleConfigurator.php
Expand Up @@ -60,17 +60,12 @@ private static function configureMutantStyle(OutputFormatterInterface $formatter
{
$formatter->setStyle('with-error', new OutputFormatterStyle('green'));
$formatter->setStyle('with-syntax-error', new OutputFormatterStyle('red', null, ['bold']));
$formatter->setStyle(
'uncovered',
new OutputFormatterStyle('blue', null, ['bold'])
);
$formatter->setStyle('uncovered', new OutputFormatterStyle('blue', null, ['bold']));
$formatter->setStyle('timeout', new OutputFormatterStyle('yellow'));
$formatter->setStyle(
'escaped',
new OutputFormatterStyle('red', null, ['bold'])
);
$formatter->setStyle('escaped', new OutputFormatterStyle('red', null, ['bold']));
$formatter->setStyle('killed', new OutputFormatterStyle('green'));
$formatter->setStyle('skipped', new OutputFormatterStyle('magenta'));
$formatter->setStyle('ignored', new OutputFormatterStyle('white'));
$formatter->setStyle('code', new OutputFormatterStyle('white'));
}

Expand Down
Expand Up @@ -147,6 +147,7 @@ private function showMetrics(): void
$this->output->writeln(['', '']);
$this->output->writeln('<options=bold>' . $this->metricsCalculator->getTotalMutantsCount() . '</options=bold> mutations were generated:');
$this->output->writeln('<options=bold>' . $this->getPadded($this->metricsCalculator->getKilledCount()) . '</options=bold> mutants were killed');
$this->output->writeln('<options=bold>' . $this->getPadded($this->metricsCalculator->getIgnoredCount()) . '</options=bold> mutants were configured to be ignored');
$this->output->writeln('<options=bold>' . $this->getPadded($this->metricsCalculator->getNotTestedCount()) . '</options=bold> mutants were not covered by tests');
$this->output->writeln('<options=bold>' . $this->getPadded($this->metricsCalculator->getEscapedCount()) . '</options=bold> covered mutants were not detected');
$this->output->writeln('<options=bold>' . $this->getPadded($this->metricsCalculator->getErrorCount()) . '</options=bold> errors were encountered');
Expand Down
5 changes: 5 additions & 0 deletions src/Logger/DebugFileLogger.php
Expand Up @@ -104,6 +104,11 @@ public function getLogLines(): array
'Skipped',
$separateSections
);
$logs[] = $this->getResultsLine(
$this->resultsCollector->getIgnoredExecutionResults(),
'Ignored',
$separateSections
);

if (!$this->onlyCoveredMode) {
$logs[] = $this->getResultsLine(
Expand Down
4 changes: 3 additions & 1 deletion src/Logger/JsonLogger.php
Expand Up @@ -76,6 +76,7 @@ public function getLogLines(): array
'errorCount' => $this->metricsCalculator->getErrorCount(),
'syntaxErrorCount' => $this->metricsCalculator->getSyntaxErrorCount(),
'skippedCount' => $this->metricsCalculator->getSkippedCount(),
'ignoredCount' => $this->metricsCalculator->getIgnoredCount(),
'timeOutCount' => $this->metricsCalculator->getTimedOutCount(),
'msi' => $this->metricsCalculator->getMutationScoreIndicator(),
'mutationCodeCoverage' => $this->metricsCalculator->getCoverageRate(),
Expand All @@ -87,6 +88,7 @@ public function getLogLines(): array
'errored' => $this->getResultsLine($this->resultsCollector->getErrorExecutionResults()),
'syntaxErrors' => $this->getResultsLine($this->resultsCollector->getSyntaxErrorExecutionResults()),
'uncovered' => $this->onlyCoveredMode ? [] : $this->getResultsLine($this->resultsCollector->getNotCoveredExecutionResults()),
'ignored' => $this->getResultsLine($this->resultsCollector->getIgnoredExecutionResults()),
];

return [json_encode($data, JSON_THROW_ON_ERROR)];
Expand All @@ -101,7 +103,7 @@ private function getResultsLine(array $executionResults): array
{
$mutatorRows = [];

foreach ($executionResults as $index => $mutantProcess) {
foreach ($executionResults as $mutantProcess) {
$mutatorRows[] = [
'mutator' => [
'mutatorName' => $mutantProcess->getMutatorName(),
Expand Down
3 changes: 2 additions & 1 deletion src/Logger/PerMutatorLogger.php
Expand Up @@ -73,7 +73,7 @@ public function getLogLines(): array
$calculatorPerMutator = $this->createMetricsPerMutators();

$table = [
['Mutator', 'Mutations', 'Killed', 'Escaped', 'Errors', 'Syntax Errors', 'Timed Out', 'Skipped', 'MSI (%s)', 'Covered MSI (%s)'],
['Mutator', 'Mutations', 'Killed', 'Escaped', 'Errors', 'Syntax Errors', 'Timed Out', 'Skipped', 'Ignored', 'MSI (%s)', 'Covered MSI (%s)'],
];

foreach ($calculatorPerMutator as $mutatorName => $calculator) {
Expand All @@ -88,6 +88,7 @@ public function getLogLines(): array
(string) $calculator->getSyntaxErrorCount(),
(string) $calculator->getTimedOutCount(),
(string) $calculator->getSkippedCount(),
(string) $calculator->getIgnoredCount(),
self::formatScore($calculator->getMutationScoreIndicator()),
self::formatScore($calculator->getCoveredCodeMutationScoreIndicator()),
];
Expand Down
1 change: 1 addition & 0 deletions src/Logger/SummaryFileLogger.php
Expand Up @@ -63,6 +63,7 @@ public function getLogLines(): array
'Escaped: ' . $this->metricsCalculator->getEscapedCount(),
'Timed Out: ' . $this->metricsCalculator->getTimedOutCount(),
'Skipped: ' . $this->metricsCalculator->getSkippedCount(),
'Ignored: ' . $this->metricsCalculator->getIgnoredCount(),
'Not Covered: ' . $this->metricsCalculator->getNotTestedCount(),
'',
];
Expand Down
7 changes: 6 additions & 1 deletion src/Metrics/MetricsCalculator.php
Expand Up @@ -113,6 +113,11 @@ public function getSkippedCount(): int
return $this->countByStatus[DetectionStatus::SKIPPED];
}

public function getIgnoredCount(): int
{
return $this->countByStatus[DetectionStatus::IGNORED];
}

public function getEscapedCount(): int
{
return $this->countByStatus[DetectionStatus::ESCAPED];
Expand All @@ -135,7 +140,7 @@ public function getTotalMutantsCount(): int

public function getTestedMutantsCount(): int
{
return $this->getTotalMutantsCount() - $this->getSkippedCount();
return $this->getTotalMutantsCount() - $this->getSkippedCount() - $this->getIgnoredCount();
}

/**
Expand Down
10 changes: 9 additions & 1 deletion src/Metrics/ResultsCollector.php
Expand Up @@ -73,7 +73,7 @@ public function collect(MutantExecutionResult ...$executionResults): void
if (!array_key_exists($detectionStatus, $this->resultsByStatus)) {
throw new InvalidArgumentException(sprintf(
'Unknown execution result process result code "%s"',
$executionResult->getDetectionStatus()
$detectionStatus
));
}

Expand Down Expand Up @@ -145,6 +145,14 @@ public function getNotCoveredExecutionResults(): array
return $this->getResultListForStatus(DetectionStatus::NOT_COVERED)->getSortedExecutionResults();
}

/**
* @return MutantExecutionResult[]
*/
public function getIgnoredExecutionResults(): array
{
return $this->getResultListForStatus(DetectionStatus::IGNORED)->getSortedExecutionResults();
}

private function getResultListForStatus(string $detectionStatus): SortableMutantExecutionResults
{
return $this->resultsByStatus[$detectionStatus];
Expand Down
4 changes: 4 additions & 0 deletions src/Metrics/TargetDetectionStatusesProvider.php
Expand Up @@ -130,6 +130,8 @@ private function findRequired(): Generator
if (!$this->onlyCoveredMode) {
yield DetectionStatus::NOT_COVERED;
}

yield DetectionStatus::IGNORED;
}

// Follows the logic in TextFileLogger
Expand All @@ -151,6 +153,8 @@ private function findRequired(): Generator
if (!$this->onlyCoveredMode) {
yield DetectionStatus::NOT_COVERED;
}

yield DetectionStatus::IGNORED;
}
}
}
2 changes: 2 additions & 0 deletions src/Mutant/DetectionStatus.php
Expand Up @@ -51,6 +51,7 @@ final class DetectionStatus
public const SKIPPED = 'skipped';
public const SYNTAX_ERROR = 'syntax error';
public const NOT_COVERED = 'not covered';
public const IGNORED = 'ignored';

public const ALL = [
self::KILLED,
Expand All @@ -60,5 +61,6 @@ final class DetectionStatus
self::SKIPPED,
self::SYNTAX_ERROR,
self::NOT_COVERED,
self::IGNORED,
];
}
5 changes: 5 additions & 0 deletions src/Mutant/MutantExecutionResult.php
Expand Up @@ -108,6 +108,11 @@ public static function createFromTimeSkippedMutant(Mutant $mutant): self
return self::createFromMutant($mutant, DetectionStatus::SKIPPED);
}

public static function createFromIgnoredMutant(Mutant $mutant): self
{
return self::createFromMutant($mutant, DetectionStatus::IGNORED);
}

public function getProcessCommandLine(): string
{
return $this->processCommandLine;
Expand Down
15 changes: 6 additions & 9 deletions src/Process/Runner/MutationTestingRunner.php
Expand Up @@ -35,7 +35,6 @@

namespace Infection\Process\Runner;

use function array_key_exists;
use Infection\Differ\DiffSourceCodeMatcher;
use Infection\Event\EventDispatcher\EventDispatcher;
use Infection\Event\MutantProcessWasFinished;
Expand Down Expand Up @@ -107,12 +106,12 @@ public function run(iterable $mutations, string $testFrameworkExtraOptions): voi
->filter(function (Mutant $mutant): bool {
$mutatorName = $mutant->getMutation()->getMutatorName();

if (!array_key_exists($mutatorName, $this->ignoreSourceCodeMutatorsMap)) {
return true;
}

foreach ($this->ignoreSourceCodeMutatorsMap[$mutatorName] as $sourceCodeRegex) {
foreach ($this->ignoreSourceCodeMutatorsMap[$mutatorName] ?? [] as $sourceCodeRegex) {
if ($this->diffSourceCodeMatcher->matches($mutant->getDiff()->get(), $sourceCodeRegex)) {
$this->eventDispatcher->dispatch(new MutantProcessWasFinished(
MutantExecutionResult::createFromIgnoredMutant($mutant)
));

return false;
}
}
Expand Down Expand Up @@ -146,9 +145,7 @@ public function run(iterable $mutations, string $testFrameworkExtraOptions): voi
->cast(function (Mutant $mutant) use ($testFrameworkExtraOptions): ProcessBearer {
$this->fileSystem->dumpFile($mutant->getFilePath(), $mutant->getMutatedCode()->get());

$process = $this->processFactory->createProcessForMutant($mutant, $testFrameworkExtraOptions);

return $process;
return $this->processFactory->createProcessForMutant($mutant, $testFrameworkExtraOptions);
})
;

Expand Down
1 change: 1 addition & 0 deletions tests/e2e/Config_Bootstrap/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Custom_tmp_dir/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Empty_Path/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Example_Test/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
3 changes: 2 additions & 1 deletion tests/e2e/Exclude_Mutations_By_Regex/expected-output.txt
@@ -1,9 +1,10 @@
Total: 0
Total: 4

Killed: 0
Errored: 0
Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 4
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Exclude_by_file_name/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Exec_Path/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 1
1 change: 1 addition & 0 deletions tests/e2e/Ignore_All_Mutations/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Ignore_MSI_Zero_Mutations/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Memory_Limit/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
3 changes: 3 additions & 0 deletions tests/e2e/Multiline_Statement/expected-output.txt
Expand Up @@ -61,5 +61,8 @@ Timed Out mutants:
Skipped mutants:
================

Ignored mutants:
================

Not Covered mutants:
====================
3 changes: 3 additions & 0 deletions tests/e2e/Output_Stream/expected-output.txt
Expand Up @@ -25,5 +25,8 @@ Timed Out mutants:
Skipped mutants:
================

Ignored mutants:
================

Not Covered mutants:
====================
1 change: 1 addition & 0 deletions tests/e2e/PCOV_Directory/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PCOV_PHPUnit8/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PHPUnit93/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PHPUnit_Custom_Config_Dir/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PHPUnit_Hidden_Dependency/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PHPUnit_XSD_Validation/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PSR_0_Autoloader/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PestTestFramework/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 2
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/PhpUnit_Depends_Order/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0
1 change: 1 addition & 0 deletions tests/e2e/Phpunit_Bat_Wrapper/expected-output.txt
Expand Up @@ -6,4 +6,5 @@ Syntax Errors: 0
Escaped: 0
Timed Out: 0
Skipped: 0
Ignored: 0
Not Covered: 0

0 comments on commit 17a3d98

Please sign in to comment.