Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the initial test suite to be skipped #1042

Merged
merged 3 commits into from
Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/Command/InfectionCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ protected function configure(): void
InputOption::VALUE_REQUIRED,
'Extra php options for the initial test runner. Will be ignored if --coverage option presented.'
)
->addOption(
'skip-initial-tests',
null,
InputOption::VALUE_NONE,
'Skips the initial test runs - requires the coverage to be provided via the --coverage option.'
)
->addOption(
'ignore-msi-with-no-mutations',
null,
Expand Down Expand Up @@ -240,6 +246,10 @@ private function startUp(): void

$coverageChecker = $this->container->getCoverageRequirementChecker();

if ($coverageChecker->hasSkipInitialTestsWithoutCoverageOption()) {
throw CoverageDoesNotExistException::mustAlreadyExist();
}

if (!$coverageChecker->hasDebuggerOrCoverageOption()) {
throw CoverageDoesNotExistException::unableToGenerate();
}
Expand Down Expand Up @@ -296,6 +306,7 @@ private function initContainer(InputInterface $input): void
$input->getOption('no-progress'),
$coverage === '' ? null : $coverage,
$initialTestsPhpOptions === '' ? null : $initialTestsPhpOptions,
(bool) $input->getOption('skip-initial-tests'),
$input->getOption('ignore-msi-with-no-mutations'),
$minMsi === null ? null : (float) $minMsi,
$minCoveredMsi === null ? null : (float) $minCoveredMsi,
Expand Down
8 changes: 8 additions & 0 deletions src/Configuration/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class Configuration
private $testFrameworkExtraOptions;
private $coveragePath;
private $skipCoverage;
private $skipInitialTests;
private $debug;
private $onlyCovered;
private $formatter;
Expand Down Expand Up @@ -102,6 +103,7 @@ public function __construct(
string $testFrameworkExtraOptions,
string $coveragePath,
bool $skipCoverage,
bool $skipInitialTests,
bool $debug,
bool $onlyCovered,
string $formatter,
Expand Down Expand Up @@ -134,6 +136,7 @@ public function __construct(
$this->testFrameworkExtraOptions = $testFrameworkExtraOptions;
$this->coveragePath = $coveragePath;
$this->skipCoverage = $skipCoverage;
$this->skipInitialTests = $skipInitialTests;
$this->debug = $debug;
$this->onlyCovered = $onlyCovered;
$this->formatter = $formatter;
Expand Down Expand Up @@ -223,6 +226,11 @@ public function shouldSkipCoverage(): bool
return $this->skipCoverage;
}

public function shouldSkipInitialTests(): bool
{
return $this->skipInitialTests;
}

public function isDebugEnabled(): bool
{
return $this->debug;
Expand Down
2 changes: 2 additions & 0 deletions src/Configuration/ConfigurationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public function create(
SchemaConfiguration $schema,
?string $existingCoveragePath,
?string $initialTestsPhpOptions,
bool $skipInitialTests,
string $logVerbosity,
bool $debug,
bool $onlyCovered,
Expand Down Expand Up @@ -140,6 +141,7 @@ public function create(
self::retrieveTestFrameworkExtraOptions($testFrameworkExtraOptions, $schema),
self::retrieveCoveragePath($coverageBasePath, $testFramework),
$skipCoverage,
$skipInitialTests,
$debug,
$onlyCovered,
$formatter,
Expand Down
9 changes: 9 additions & 0 deletions src/Console/ConsoleOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,13 @@ public function logNotInControlOfExitCodes(): void
'It is your responsibility to disable xdebug/phpdbg unless needed.',
]);
}

public function logSkippingInitialTests(): void
{
$this->io->warning([
'Skipping the initial test run can be very dangerous.',
'It is your responsibility to ensure the tests are in a passing state to begin.',
'If this is not done then mutations may report as caught when they are not.',
]);
}
}
6 changes: 5 additions & 1 deletion src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ public static function create(): self
$config = $container->getConfiguration();

return new CoverageRequirementChecker(
$config->getCoveragePath() !== '',
$config->shouldSkipCoverage(),
maks-rafalko marked this conversation as resolved.
Show resolved Hide resolved
$config->shouldSkipInitialTests(),
$config->getInitialTestsPhpOptions() ?? ''
);
},
Expand Down Expand Up @@ -421,6 +422,7 @@ public function withDynamicParameters(
bool $noProgress,
?string $existingCoveragePath,
?string $initialTestsPhpOptions,
bool $skipInitialTests,
bool $ignoreMsiWithNoMutations,
?float $minMsi,
?float $minCoveredMsi,
Expand Down Expand Up @@ -450,6 +452,7 @@ static function (self $container) use ($configFile): SchemaConfiguration {
static function (self $container) use (
$existingCoveragePath,
$initialTestsPhpOptions,
$skipInitialTests,
$logVerbosity,
$debug,
$onlyCovered,
Expand All @@ -468,6 +471,7 @@ static function (self $container) use (
$container->getSchemaConfiguration(),
$existingCoveragePath,
$initialTestsPhpOptions,
$skipInitialTests,
$logVerbosity,
$debug,
$onlyCovered,
Expand Down
26 changes: 24 additions & 2 deletions src/Engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ public function execute(int $threads): bool

private function runInitialTestSuite(): void
{
if ($this->config->shouldSkipInitialTests()) {
$this->consoleOutput->logSkippingInitialTests();
$this->assertCodeCoverageExists($this->config->getTestFramework());

return;
}

$initialTestSuitProcess = $this->initialTestsRunner->run(
$this->config->getTestFrameworkExtraOptions(),
$this->config->shouldSkipCoverage(),
Expand All @@ -122,7 +129,7 @@ private function runInitialTestSuite(): void
throw InitialTestsFailed::fromProcessAndAdapter($initialTestSuitProcess, $this->adapter);
}

$this->assertCodeCoverageExists($initialTestSuitProcess, $this->config->getTestFramework());
$this->assertCodeCoverageProduced($initialTestSuitProcess, $this->config->getTestFramework());

$this->memoryLimitApplier->applyMemoryLimitFromProcess($initialTestSuitProcess, $this->adapter);
}
Expand Down Expand Up @@ -170,7 +177,22 @@ private function checkMetrics(): bool
return true;
}

private function assertCodeCoverageExists(Process $initialTestsProcess, string $testFrameworkKey): void
private function assertCodeCoverageExists(string $testFrameworkKey): void
{
$coverageDir = $this->config->getCoveragePath();

$coverageIndexFilePath = $coverageDir . '/' . PhpUnitXmlCoverageFactory::COVERAGE_INDEX_FILE_NAME;

if (!file_exists($coverageIndexFilePath)) {
throw CoverageDoesNotExistException::with(
$coverageIndexFilePath,
$testFrameworkKey,
dirname($coverageIndexFilePath, 2)
);
}
}

private function assertCodeCoverageProduced(Process $initialTestsProcess, string $testFrameworkKey): void
{
$coverageDir = $this->config->getCoveragePath();

Expand Down
9 changes: 8 additions & 1 deletion src/Process/Coverage/CoverageRequirementChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@
final class CoverageRequirementChecker
{
private $skipCoverage;
private $skipInitialTests;
private $initialTestPhpOptions;

public function __construct(bool $skipCoverage, string $initialTestPhpOptions)
public function __construct(bool $skipCoverage, bool $skipInitialTests, string $initialTestPhpOptions)
{
$this->skipCoverage = $skipCoverage;
$this->skipInitialTests = $skipInitialTests;
$this->initialTestPhpOptions = $initialTestPhpOptions;
}

Expand All @@ -65,6 +67,11 @@ public function hasDebuggerOrCoverageOption(): bool
|| $this->isPcovIncludedInInitialTestPhpOptions();
}

public function hasSkipInitialTestsWithoutCoverageOption(): bool
{
return $this->skipInitialTests && !$this->skipCoverage;
}

private function isXdebugIncludedInInitialTestPhpOptions(): bool
{
return (bool) preg_match(
Expand Down
5 changes: 5 additions & 0 deletions src/TestFramework/Coverage/CoverageDoesNotExistException.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ public static function unableToGenerate(): self
self::INFECTION_USAGE_SUGGESTION
);
}

public static function mustAlreadyExist(): self
{
return new self('When skipping the initial test suite run, existing code coverage must be provided using --coverage');
}
}
3 changes: 3 additions & 0 deletions tests/e2e/Skip_Initial_Tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Provide existing coverage files

* Ensure the initial test suite is not run
23 changes: 23 additions & 0 deletions tests/e2e/Skip_Initial_Tests/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"config": {
"platform": {
"php": "7.2.9"
}
},
"require-dev": {
"phpunit/phpunit": "^6.5",
"phpspec/phpspec": "^4.3",
"leanphp/phpspec-code-coverage": "^4.0"
},
"autoload": {
"psr-4": {
"spec\\": "spec/",
"ProvideExistingCoverage\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"ProvideExistingCoverage\\Test\\": "tests/"
}
}
}
44 changes: 44 additions & 0 deletions tests/e2e/Skip_Initial_Tests/expected-output_phpspec.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Total: 8
Killed mutants:
===============


Errors mutants:
===============


Escaped mutants:
================


Timed Out mutants:
==================


Not Covered mutants:
====================


Mutator: PublicVisibility
Line 7

Mutator: Plus
Line 9

Mutator: TrueValue
Line 12

Mutator: PublicVisibility
Line 12

Mutator: FalseValue
Line 14

Mutator: NotIdentical
Line 14

Mutator: TrueValue
Line 15

Mutator: FalseValue
Line 18
44 changes: 44 additions & 0 deletions tests/e2e/Skip_Initial_Tests/expected-output_phpunit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Total: 8
Killed mutants:
===============


Mutator: PublicVisibility
Line 7

Mutator: Plus
Line 9

Mutator: TrueValue
Line 12

Mutator: PublicVisibility
Line 12

Mutator: FalseValue
Line 14

Mutator: NotIdentical
Line 14

Mutator: TrueValue
Line 15

Errors mutants:
===============


Escaped mutants:
================


Timed Out mutants:
==================


Not Covered mutants:
====================


Mutator: FalseValue
Line 18