diff --git a/doc/nomenclature.md b/doc/nomenclature.md
index 752d8720f..205656090 100644
--- a/doc/nomenclature.md
+++ b/doc/nomenclature.md
@@ -2,9 +2,58 @@
## Table of Contents
+- [A](#a)
+ - [AST][ast]
+- [M](#m)
+ - [Mutagenesis][mutagenesis]
+ - [Mutant][mutant]
+ - [Mutation][mutation]
+ - [Mutator][mutator]
+- [S](#s)
+ - [Subject][subject]
- [T](#t)
- - [Tracer][tracer]
- - [Trace][trace]
+ - [Tracer][tracer]
+ - [Trace][trace]
+
+
+## A
+
+### AST
+
+Acronym for [Abstract Syntax Tree][ast-definition]. It is a tree representation of the abstract
+syntactic structure of code. It is what Infection parses the code into in order to operate on it.
+
+
+## M
+
+### Mutagenesis
+
+Process of creating a mutant from the original program.
+
+
+### Mutant
+
+New program that differs from the original by applying a mutation.
+
+
+### Mutation
+
+The result of applying a mutator to the AST of a subject and represents a change to be applied.
+
+
+### Mutator
+
+Define a possible transformation, which applied to the AST of a subject will result in a mutation.
+
+In the Mutation Testing literature, mutators are also known as "mutant operator",
+"mutagenic operator", "mutagen" and "mutation rule".
+
+
+## S
+
+### Subject
+
+An addressable piece of code to be targeted for mutation testing.
## T
@@ -23,5 +72,12 @@ Artifact produced by a tracer: provides the piece of source code and its associa
+[ast]: #ast
+[ast-definition]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
+[mutagenesis]: #mutagenesis
+[mutant]: #mutant
+[mutation]: #mutation
+[mutator]: #mutator
+[subject]: #subject
[tracer]: #tracer
[trace]: #trace
diff --git a/src/Container.php b/src/Container.php
index e36d923a0..3389b345a 100644
--- a/src/Container.php
+++ b/src/Container.php
@@ -64,7 +64,7 @@
use Infection\Metrics\MinMsiChecker;
use Infection\Mutant\MutantCodeFactory;
use Infection\Mutant\MutantExecutionResultFactory;
-use Infection\Mutant\MutantFactory;
+use Infection\Mutant\MutationFactory;
use Infection\Mutation\FileMutationGenerator;
use Infection\Mutation\MutationAttributeKeys;
use Infection\Mutation\MutationGenerator;
@@ -225,8 +225,8 @@ public static function create(): self
MutantCodeFactory::class => static function (self $container): MutantCodeFactory {
return new MutantCodeFactory($container->getPrinter());
},
- MutantFactory::class => static function (self $container): MutantFactory {
- return new MutantFactory(
+ MutationFactory::class => static function (self $container): MutationFactory {
+ return new MutationFactory(
$container->getConfiguration()->getTmpDir(),
$container->getDiffer(),
$container->getPrinter(),
@@ -399,7 +399,8 @@ public static function create(): self
return new FileMutationGenerator(
$container->getFileParser(),
$container->getNodeTraverserFactory(),
- $container->getLineRangeCalculator()
+ $container->getLineRangeCalculator(),
+ $container->getMutationFactory()
);
},
LoggerFactory::class => static function (self $container): LoggerFactory {
@@ -454,7 +455,6 @@ public static function create(): self
MutationTestingRunner::class => static function (self $container): MutationTestingRunner {
return new MutationTestingRunner(
$container->getMutantProcessFactory(),
- $container->getMutantFactory(),
$container->getProcessRunner(),
$container->getEventDispatcher(),
$container->getConfiguration()->isDryRun()
@@ -655,9 +655,9 @@ public function getMutantCodeFactory(): MutantCodeFactory
return $this->get(MutantCodeFactory::class);
}
- public function getMutantFactory(): MutantFactory
+ public function getMutationFactory(): MutationFactory
{
- return $this->get(MutantFactory::class);
+ return $this->get(MutationFactory::class);
}
public function getDiffer(): Differ
diff --git a/src/Engine.php b/src/Engine.php
index c2fb03a53..532692374 100644
--- a/src/Engine.php
+++ b/src/Engine.php
@@ -157,12 +157,15 @@ private function runMutationAnalysis(): void
: []
);
- $actualExtraOptions = $this->config->getTestFrameworkExtraOptions();
+ $extraOptions = $this->config->getTestFrameworkExtraOptions();
- $filteredExtraOptionsForMutant = $this->adapter instanceof ProvidesInitialRunOnlyOptions
- ? $this->testFrameworkExtraOptionsFilter->filterForMutantProcess($actualExtraOptions, $this->adapter->getInitialRunOnlyOptions())
- : $actualExtraOptions;
+ $mutationExtraOptions = $this->adapter instanceof ProvidesInitialRunOnlyOptions
+ ? $this->testFrameworkExtraOptionsFilter->filterForMutantProcess(
+ $extraOptions,
+ $this->adapter->getInitialRunOnlyOptions()
+ )
+ : $extraOptions;
- $this->mutationTestingRunner->run($mutations, $filteredExtraOptionsForMutant);
+ $this->mutationTestingRunner->run($mutations, $mutationExtraOptions);
}
}
diff --git a/src/Event/Subscriber/MutationTestingConsoleLoggerSubscriber.php b/src/Event/Subscriber/MutationTestingConsoleLoggerSubscriber.php
index 57c835297..ab02f56d9 100644
--- a/src/Event/Subscriber/MutationTestingConsoleLoggerSubscriber.php
+++ b/src/Event/Subscriber/MutationTestingConsoleLoggerSubscriber.php
@@ -138,7 +138,7 @@ private function showMutations(array $executionResults, string $headlinePrefix):
),
]);
- $this->output->writeln($this->diffColorizer->colorize($executionResult->getMutantDiff()));
+ $this->output->writeln($this->diffColorizer->colorize($executionResult->getMutationDiff()));
}
}
diff --git a/src/Logger/TextFileLogger.php b/src/Logger/TextFileLogger.php
index 03d8ee62b..5ae03179d 100644
--- a/src/Logger/TextFileLogger.php
+++ b/src/Logger/TextFileLogger.php
@@ -138,7 +138,7 @@ private function getResultsLine(
$lines[] = self::getMutatorLine($index, $executionResult);
$lines[] = '';
- $lines[] = Str::trimLineReturns($executionResult->getMutantDiff());
+ $lines[] = Str::trimLineReturns($executionResult->getMutationDiff());
if ($this->debugMode) {
$lines[] = '';
diff --git a/src/Mutant/Mutant.php b/src/Mutant/Mutant.php
deleted file mode 100644
index ca0562fb5..000000000
--- a/src/Mutant/Mutant.php
+++ /dev/null
@@ -1,96 +0,0 @@
-mutantFilePath = $mutantFilePath;
- $this->mutation = $mutation;
- $this->mutatedCode = $mutatedCode;
- $this->diff = $diff;
- }
-
- public function getFilePath(): string
- {
- return $this->mutantFilePath;
- }
-
- public function getMutation(): Mutation
- {
- return $this->mutation;
- }
-
- public function getMutatedCode(): string
- {
- return $this->mutatedCode;
- }
-
- public function getDiff(): string
- {
- return $this->diff;
- }
-
- public function isCoveredByTest(): bool
- {
- return $this->mutation->isCoveredByTest();
- }
-
- /**
- * @return TestLocation[]
- */
- public function getTests(): array
- {
- return $this->mutation->getAllTests();
- }
-}
diff --git a/src/Mutant/MutantCodeFactory.php b/src/Mutant/MutantCodeFactory.php
index ac0035b66..9ec08113b 100644
--- a/src/Mutant/MutantCodeFactory.php
+++ b/src/Mutant/MutantCodeFactory.php
@@ -35,9 +35,10 @@
namespace Infection\Mutant;
-use Infection\Mutation\Mutation;
+use Infection\PhpParser\MutatedNode;
use Infection\PhpParser\Visitor\CloneVisitor;
use Infection\PhpParser\Visitor\MutatorVisitor;
+use PhpParser\Node;
use PhpParser\NodeTraverser;
use PhpParser\PrettyPrinterAbstract;
@@ -54,14 +55,23 @@ public function __construct(PrettyPrinterAbstract $prettyPrinter)
$this->printer = $prettyPrinter;
}
- public function createCode(Mutation $mutation): string
- {
+ /**
+ * @param array $attributes
+ * @param Node[] $originalFileAst
+ * @param class-string $mutatedNodeClass
+ */
+ public function createCode(
+ array $attributes,
+ array $originalFileAst,
+ string $mutatedNodeClass,
+ MutatedNode $mutatedNode
+ ): string {
$traverser = new NodeTraverser();
$traverser->addVisitor(new CloneVisitor());
- $traverser->addVisitor(new MutatorVisitor($mutation));
+ $traverser->addVisitor(new MutatorVisitor($attributes, $mutatedNodeClass, $mutatedNode));
- $mutatedStatements = $traverser->traverse($mutation->getOriginalFileAst());
+ $mutatedStatements = $traverser->traverse($originalFileAst);
return $this->printer->prettyPrintFile($mutatedStatements);
}
diff --git a/src/Mutant/MutantExecutionResult.php b/src/Mutant/MutantExecutionResult.php
index 8f36841aa..05e4a5b61 100644
--- a/src/Mutant/MutantExecutionResult.php
+++ b/src/Mutant/MutantExecutionResult.php
@@ -36,6 +36,7 @@
namespace Infection\Mutant;
use function array_keys;
+use Infection\Mutation\Mutation;
use Infection\Mutator\ProfileList;
use Webmozart\Assert\Assert;
@@ -48,7 +49,7 @@ class MutantExecutionResult
private $processCommandLine;
private $processOutput;
private $detectionStatus;
- private $mutantDiff;
+ private $mutationDiff;
private $mutatorName;
private $originalFilePath;
private $originalStartingLine;
@@ -57,7 +58,7 @@ public function __construct(
string $processCommandLine,
string $processOutput,
string $detectionStatus,
- string $mutantDiff,
+ string $mutationDiff,
string $mutatorName,
string $originalFilePath,
int $originalStartingLine
@@ -68,22 +69,20 @@ public function __construct(
$this->processCommandLine = $processCommandLine;
$this->processOutput = $processOutput;
$this->detectionStatus = $detectionStatus;
- $this->mutantDiff = $mutantDiff;
+ $this->mutationDiff = $mutationDiff;
$this->mutatorName = $mutatorName;
$this->originalFilePath = $originalFilePath;
$this->originalStartingLine = $originalStartingLine;
}
- public static function createFromNonCoveredMutant(Mutant $mutant): self
+ public static function createFromNonCoveredByTestsMutation(Mutation $mutation): self
{
- $mutation = $mutant->getMutation();
-
return new self(
'',
'',
DetectionStatus::NOT_COVERED,
- $mutant->getDiff(),
- $mutant->getMutation()->getMutatorName(),
+ $mutation->getDiff(),
+ $mutation->getMutatorName(),
$mutation->getOriginalFilePath(),
$mutation->getOriginalStartingLine()
);
@@ -104,9 +103,9 @@ public function getDetectionStatus(): string
return $this->detectionStatus;
}
- public function getMutantDiff(): string
+ public function getMutationDiff(): string
{
- return $this->mutantDiff;
+ return $this->mutationDiff;
}
public function getMutatorName(): string
diff --git a/src/Mutant/MutantExecutionResultFactory.php b/src/Mutant/MutantExecutionResultFactory.php
index 53a9dd7d5..8198485a5 100644
--- a/src/Mutant/MutantExecutionResultFactory.php
+++ b/src/Mutant/MutantExecutionResultFactory.php
@@ -57,14 +57,13 @@ public function __construct(TestFrameworkAdapter $testFrameworkAdapter)
public function createFromProcess(MutantProcess $mutantProcess): MutantExecutionResult
{
$process = $mutantProcess->getProcess();
- $mutant = $mutantProcess->getMutant();
- $mutation = $mutant->getMutation();
+ $mutation = $mutantProcess->getMutation();
return new MutantExecutionResult(
$process->getCommandLine(),
$this->retrieveProcessOutput($process),
$this->retrieveDetectionStatus($mutantProcess),
- $mutant->getDiff(),
+ $mutation->getDiff(),
$mutation->getMutatorName(),
$mutation->getOriginalFilePath(),
$mutation->getOriginalStartingLine()
@@ -86,7 +85,7 @@ private function retrieveProcessOutput(Process $process): string
private function retrieveDetectionStatus(MutantProcess $mutantProcess): string
{
- if (!$mutantProcess->getMutant()->isCoveredByTest()) {
+ if (!$mutantProcess->getMutation()->isCoveredByTest()) {
return DetectionStatus::NOT_COVERED;
}
diff --git a/src/Mutant/MutantFactory.php b/src/Mutant/MutationFactory.php
similarity index 52%
rename from src/Mutant/MutantFactory.php
rename to src/Mutant/MutationFactory.php
index 4614467ff..c9f47b508 100644
--- a/src/Mutant/MutantFactory.php
+++ b/src/Mutant/MutationFactory.php
@@ -35,17 +35,25 @@
namespace Infection\Mutant;
+use function array_intersect_key;
+use function implode;
+use Infection\AbstractTestFramework\Coverage\TestLocation;
use Infection\Differ\Differ;
use Infection\Mutation\Mutation;
+use Infection\Mutation\MutationAttributeKeys;
+use Infection\PhpParser\MutatedNode;
+use function md5;
use PhpParser\Node;
use PhpParser\PrettyPrinterAbstract;
+use function Safe\array_flip;
use function Safe\sprintf;
+use Webmozart\Assert\Assert;
/**
* @internal
* @final
*/
-class MutantFactory
+class MutationFactory
{
private $tmpDir;
private $differ;
@@ -55,7 +63,7 @@ class MutantFactory
* @var string[]
*/
private $printedFileCache = [];
- private $mutantCodeFactory;
+ private $codeFactory;
public function __construct(
string $tmpDir,
@@ -66,35 +74,103 @@ public function __construct(
$this->tmpDir = $tmpDir;
$this->differ = $differ;
$this->printer = $printer;
- $this->mutantCodeFactory = $mutantCodeFactory;
+ $this->codeFactory = $mutantCodeFactory;
}
- public function create(Mutation $mutation): Mutant
- {
- $mutantFilePath = sprintf(
- '%s/mutant.%s.infection.php',
+ /**
+ * @param Node[] $originalFileAst
+ * @param array $attributes
+ * @param class-string $mutatedNodeClass
+ * @param TestLocation[] $tests
+ */
+ public function create(
+ string $originalFilePath,
+ array $originalFileAst,
+ string $mutatorName,
+ array $attributes,
+ string $mutatedNodeClass,
+ MutatedNode $mutatedNode,
+ int $mutationByMutatorIndex,
+ array $tests
+ ): Mutation {
+ foreach (MutationAttributeKeys::ALL as $key) {
+ Assert::keyExists($attributes, $key);
+ }
+
+ $attributes = array_intersect_key($attributes, array_flip(MutationAttributeKeys::ALL));
+
+ $hash = self::createHash(
+ $originalFilePath,
+ $mutatorName,
+ $attributes,
+ $mutationByMutatorIndex
+ );
+
+ $mutationFilePath = sprintf(
+ '%s/mutation.%s.infection.php',
$this->tmpDir,
- $mutation->getHash()
+ $hash
);
- $mutatedCode = $this->mutantCodeFactory->createCode($mutation);
+ $mutatedCode = $this->codeFactory->createCode(
+ $attributes,
+ $originalFileAst,
+ $mutatedNodeClass,
+ $mutatedNode
+ );
- return new Mutant(
- $mutantFilePath,
- $mutation,
+ return new Mutation(
+ $originalFilePath,
+ $mutatorName,
+ (int) $attributes[MutationAttributeKeys::START_LINE],
+ $tests,
+ $hash,
+ $mutationFilePath,
$mutatedCode,
- $this->createMutantDiff($mutation, $mutatedCode)
+ $this->createMutationDiff(
+ $originalFilePath,
+ $originalFileAst,
+ $mutatedCode
+ )
);
}
- private function createMutantDiff(Mutation $mutation, string $mutantCode): string
- {
+ /**
+ * @param array $attributes
+ */
+ private static function createHash(
+ string $originalFilePath,
+ string $mutatorName,
+ array $attributes,
+ int $mutationByMutatorIndex
+ ): string {
+ $hashKeys = [
+ $originalFilePath,
+ $mutatorName,
+ $mutationByMutatorIndex,
+ ];
+
+ foreach ($attributes as $attribute) {
+ $hashKeys[] = $attribute;
+ }
+
+ return md5(implode('_', $hashKeys));
+ }
+
+ /**
+ * @param Node[] $originalFileAst
+ */
+ private function createMutationDiff(
+ string $originalFilePath,
+ array $originalFileAst,
+ string $mutationCode
+ ): string {
$originalPrettyPrintedFile = $this->getOriginalPrettyPrintedFile(
- $mutation->getOriginalFilePath(),
- $mutation->getOriginalFileAst()
+ $originalFilePath,
+ $originalFileAst
);
- return $this->differ->diff($originalPrettyPrintedFile, $mutantCode);
+ return $this->differ->diff($originalPrettyPrintedFile, $mutationCode);
}
/**
diff --git a/src/Mutation/FileMutationGenerator.php b/src/Mutation/FileMutationGenerator.php
index aebae30fc..7cd117cc6 100644
--- a/src/Mutation/FileMutationGenerator.php
+++ b/src/Mutation/FileMutationGenerator.php
@@ -35,6 +35,7 @@
namespace Infection\Mutation;
+use Infection\Mutant\MutationFactory;
use Infection\Mutator\Mutator;
use Infection\Mutator\NodeMutationGenerator;
use Infection\PhpParser\FileParser;
@@ -55,15 +56,18 @@ class FileMutationGenerator
private $parser;
private $traverserFactory;
private $lineRangeCalculator;
+ private $mutationFactory;
public function __construct(
FileParser $parser,
NodeTraverserFactory $traverserFactory,
- LineRangeCalculator $lineRangeCalculator
+ LineRangeCalculator $lineRangeCalculator,
+ MutationFactory $mutationFactory
) {
$this->parser = $parser;
$this->traverserFactory = $traverserFactory;
$this->lineRangeCalculator = $lineRangeCalculator;
+ $this->mutationFactory = $mutationFactory;
}
/**
@@ -98,7 +102,8 @@ public function generate(
$initialStatements,
$trace,
$onlyCovered,
- $this->lineRangeCalculator
+ $this->lineRangeCalculator,
+ $this->mutationFactory
)
);
diff --git a/src/Mutation/Mutation.php b/src/Mutation/Mutation.php
index 2e68913bd..5d1a93110 100644
--- a/src/Mutation/Mutation.php
+++ b/src/Mutation/Mutation.php
@@ -35,16 +35,10 @@
namespace Infection\Mutation;
-use function array_intersect_key;
use function array_keys;
use function count;
-use function implode;
use Infection\AbstractTestFramework\Coverage\TestLocation;
use Infection\Mutator\ProfileList;
-use Infection\PhpParser\MutatedNode;
-use function md5;
-use PhpParser\Node;
-use function Safe\array_flip;
use Webmozart\Assert\Assert;
/**
@@ -55,49 +49,38 @@ class Mutation
{
private $originalFilePath;
private $mutatorName;
- private $mutatedNodeClass;
- private $mutatedNode;
- private $mutationByMutatorIndex;
- private $attributes;
- private $originalFileAst;
+ private $originalStartingLine;
private $tests;
private $coveredByTests;
+ private $mutationHash;
+ private $mutationFilePath;
+ private $mutatedCode;
+ private $diff;
/**
- * @var string|null
- */
- private $hash;
-
- /**
- * @param Node[] $originalFileAst
- * @param array $attributes
* @param TestLocation[] $tests
*/
public function __construct(
string $originalFilePath,
- array $originalFileAst,
string $mutatorName,
- array $attributes,
- string $mutatedNodeClass,
- MutatedNode $mutatedNode,
- int $mutationByMutatorIndex,
- array $tests
+ int $originalStartingLine,
+ array $tests,
+ string $mutationHash,
+ string $mutationFilePath,
+ string $mutatedCode,
+ string $diff
) {
Assert::oneOf($mutatorName, array_keys(ProfileList::ALL_MUTATORS));
- foreach (MutationAttributeKeys::ALL as $key) {
- Assert::keyExists($attributes, $key);
- }
-
$this->originalFilePath = $originalFilePath;
- $this->originalFileAst = $originalFileAst;
$this->mutatorName = $mutatorName;
- $this->attributes = array_intersect_key($attributes, array_flip(MutationAttributeKeys::ALL));
- $this->mutatedNodeClass = $mutatedNodeClass;
- $this->mutatedNode = $mutatedNode;
- $this->mutationByMutatorIndex = $mutationByMutatorIndex;
+ $this->originalStartingLine = $originalStartingLine;
$this->tests = $tests;
$this->coveredByTests = count($tests) > 0;
+ $this->mutationHash = $mutationHash;
+ $this->mutationFilePath = $mutationFilePath;
+ $this->mutatedCode = $mutatedCode;
+ $this->diff = $diff;
}
public function getOriginalFilePath(): string
@@ -105,43 +88,16 @@ public function getOriginalFilePath(): string
return $this->originalFilePath;
}
- /**
- * @return Node[]
- */
- public function getOriginalFileAst(): array
- {
- return $this->originalFileAst;
- }
-
public function getMutatorName(): string
{
return $this->mutatorName;
}
- /**
- * @return (string|int|float)[]
- */
- public function getAttributes(): array
- {
- return $this->attributes;
- }
-
public function getOriginalStartingLine(): int
{
- return (int) $this->attributes['startLine'];
- }
-
- public function getMutatedNodeClass(): string
- {
- return $this->mutatedNodeClass;
- }
-
- public function getMutatedNode(): MutatedNode
- {
- return $this->mutatedNode;
+ return $this->originalStartingLine;
}
- // TODO: hasTest()?
public function isCoveredByTest(): bool
{
return $this->coveredByTests;
@@ -157,21 +113,21 @@ public function getAllTests(): array
public function getHash(): string
{
- return $this->hash ?? $this->hash = $this->createHash();
+ return $this->mutationHash;
}
- private function createHash(): string
+ public function getFilePath(): string
{
- $hashKeys = [
- $this->originalFilePath,
- $this->mutatorName,
- $this->mutationByMutatorIndex,
- ];
+ return $this->mutationFilePath;
+ }
- foreach ($this->attributes as $attribute) {
- $hashKeys[] = $attribute;
- }
+ public function getMutatedCode(): string
+ {
+ return $this->mutatedCode;
+ }
- return md5(implode('_', $hashKeys));
+ public function getDiff(): string
+ {
+ return $this->diff;
}
}
diff --git a/src/Mutator/NodeMutationGenerator.php b/src/Mutator/NodeMutationGenerator.php
index d624425bd..c191d7df6 100644
--- a/src/Mutator/NodeMutationGenerator.php
+++ b/src/Mutator/NodeMutationGenerator.php
@@ -37,6 +37,7 @@
use function count;
use function get_class;
+use Infection\Mutant\MutationFactory;
use Infection\Mutation\Mutation;
use Infection\PhpParser\MutatedNode;
use Infection\PhpParser\Visitor\ReflectionVisitor;
@@ -61,6 +62,7 @@ class NodeMutationGenerator
private $trace;
private $onlyCovered;
private $lineRangeCalculator;
+ private $mutationFactory;
/**
* @param Mutator[] $mutators
@@ -72,7 +74,8 @@ public function __construct(
array $fileNodes,
Trace $trace,
bool $onlyCovered,
- LineRangeCalculator $lineRangeCalculator
+ LineRangeCalculator $lineRangeCalculator,
+ MutationFactory $mutationFactory
) {
Assert::allIsInstanceOf($mutators, Mutator::class);
@@ -82,6 +85,7 @@ public function __construct(
$this->trace = $trace;
$this->onlyCovered = $onlyCovered;
$this->lineRangeCalculator = $lineRangeCalculator;
+ $this->mutationFactory = $mutationFactory;
}
/**
@@ -135,7 +139,7 @@ private function generateForMutator(Node $node, Mutator $mutator): iterable
$mutationByMutatorIndex = 0;
foreach ($mutator->mutate($node) as $mutatedNode) {
- yield new Mutation(
+ yield $this->mutationFactory->create(
$this->filePath,
$this->fileNodes,
$mutator->getName(),
diff --git a/src/PhpParser/Visitor/MutatorVisitor.php b/src/PhpParser/Visitor/MutatorVisitor.php
index 411225d4d..01732054f 100644
--- a/src/PhpParser/Visitor/MutatorVisitor.php
+++ b/src/PhpParser/Visitor/MutatorVisitor.php
@@ -38,6 +38,7 @@
use function array_key_exists;
use function get_class;
use Infection\Mutation\Mutation;
+use Infection\PhpParser\MutatedNode;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
@@ -46,11 +47,22 @@
*/
final class MutatorVisitor extends NodeVisitorAbstract
{
- private $mutation;
+ private $attributes;
+ private $mutatedNodeClass;
+ private $mutatedNode;
- public function __construct(Mutation $mutation)
- {
- $this->mutation = $mutation;
+ /**
+ * @param array $attributes
+ * @param class-string $mutatedNodeClass
+ */
+ public function __construct(
+ array $attributes,
+ string $mutatedNodeClass,
+ MutatedNode $mutatedNode
+ ) {
+ $this->attributes = $attributes;
+ $this->mutatedNodeClass = $mutatedNodeClass;
+ $this->mutatedNode = $mutatedNode;
}
public function leaveNode(Node $node)
@@ -61,13 +73,13 @@ public function leaveNode(Node $node)
return null;
}
- $mutatedAttributes = $this->mutation->getAttributes();
+ $mutatedAttributes = $this->attributes;
$samePosition = $attributes['startTokenPos'] === $mutatedAttributes['startTokenPos']
&& $attributes['endTokenPos'] === $mutatedAttributes['endTokenPos'];
- if ($samePosition && $this->mutation->getMutatedNodeClass() === get_class($node)) {
- return $this->mutation->getMutatedNode()->unwrap();
+ if ($samePosition && $this->mutatedNodeClass === get_class($node)) {
+ return $this->mutatedNode->unwrap();
// TODO STOP TRAVERSING
// TODO check all built-in visitors, in particular FirstFindingVisitor
// TODO beforeTraverse - FirstFindingVisitor
diff --git a/src/Process/Factory/MutantProcessFactory.php b/src/Process/Factory/MutantProcessFactory.php
index 27081a8e0..469791c67 100644
--- a/src/Process/Factory/MutantProcessFactory.php
+++ b/src/Process/Factory/MutantProcessFactory.php
@@ -38,8 +38,8 @@
use Infection\AbstractTestFramework\TestFrameworkAdapter;
use Infection\Event\EventDispatcher\EventDispatcher;
use Infection\Event\MutantProcessWasFinished;
-use Infection\Mutant\Mutant;
use Infection\Mutant\MutantExecutionResultFactory;
+use Infection\Mutation\Mutation;
use Infection\Process\MutantProcess;
use function method_exists;
use Symfony\Component\Process\Process;
@@ -68,14 +68,14 @@ public function __construct(
$this->resultFactory = $resultFactory;
}
- public function createProcessForMutant(Mutant $mutant, string $testFrameworkExtraOptions = ''): MutantProcess
+ public function createProcessForMutation(Mutation $mutation, string $testFrameworkExtraOptions = ''): MutantProcess
{
$process = new Process(
$this->testFrameworkAdapter->getMutantCommandLine(
- $mutant->getTests(),
- $mutant->getFilePath(),
- $mutant->getMutation()->getHash(),
- $mutant->getMutation()->getOriginalFilePath(),
+ $mutation->getAllTests(),
+ $mutation->getFilePath(),
+ $mutation->getHash(),
+ $mutation->getOriginalFilePath(),
$testFrameworkExtraOptions
)
);
@@ -87,7 +87,7 @@ public function createProcessForMutant(Mutant $mutant, string $testFrameworkExtr
$process->inheritEnvironmentVariables();
}
- $mutantProcess = new MutantProcess($process, $mutant);
+ $mutantProcess = new MutantProcess($process, $mutation);
$eventDispatcher = $this->eventDispatcher;
$resultFactory = $this->resultFactory;
diff --git a/src/Process/MutantProcess.php b/src/Process/MutantProcess.php
index d6bbde333..a01b2f994 100644
--- a/src/Process/MutantProcess.php
+++ b/src/Process/MutantProcess.php
@@ -36,7 +36,7 @@
namespace Infection\Process;
use Closure;
-use Infection\Mutant\Mutant;
+use Infection\Mutation\Mutation;
use Infection\Process\Runner\ProcessBearer;
use Symfony\Component\Process\Process;
@@ -47,7 +47,7 @@
class MutantProcess implements ProcessBearer
{
private $process;
- private $mutant;
+ private $mutation;
private $callback;
/**
@@ -55,10 +55,10 @@ class MutantProcess implements ProcessBearer
*/
private $timedOut = false;
- public function __construct(Process $process, Mutant $mutant)
+ public function __construct(Process $process, Mutation $mutation)
{
$this->process = $process;
- $this->mutant = $mutant;
+ $this->mutation = $mutation;
$this->callback = static function (): void {};
}
@@ -67,9 +67,9 @@ public function getProcess(): Process
return $this->process;
}
- public function getMutant(): Mutant
+ public function getMutation(): Mutation
{
- return $this->mutant;
+ return $this->mutation;
}
public function markAsTimedOut(): void
diff --git a/src/Process/Runner/MutationTestingRunner.php b/src/Process/Runner/MutationTestingRunner.php
index 7e07bac00..6458641e7 100644
--- a/src/Process/Runner/MutationTestingRunner.php
+++ b/src/Process/Runner/MutationTestingRunner.php
@@ -40,9 +40,7 @@
use Infection\Event\MutationTestingWasFinished;
use Infection\Event\MutationTestingWasStarted;
use Infection\IterableCounter;
-use Infection\Mutant\Mutant;
use Infection\Mutant\MutantExecutionResult;
-use Infection\Mutant\MutantFactory;
use Infection\Mutation\Mutation;
use Infection\Process\Factory\MutantProcessFactory;
use function Pipeline\take;
@@ -54,7 +52,6 @@
final class MutationTestingRunner
{
private $processFactory;
- private $mutantFactory;
private $processRunner;
private $eventDispatcher;
private $fileSystem;
@@ -62,14 +59,12 @@ final class MutationTestingRunner
public function __construct(
MutantProcessFactory $processFactory,
- MutantFactory $mutantFactory,
ProcessRunner $processRunner,
EventDispatcher $eventDispatcher,
Filesystem $fileSystem,
bool $runConcurrently
) {
$this->processFactory = $processFactory;
- $this->mutantFactory = $mutantFactory;
$this->processRunner = $processRunner;
$this->eventDispatcher = $eventDispatcher;
$this->fileSystem = $fileSystem;
@@ -81,29 +76,28 @@ public function __construct(
*/
public function run(iterable $mutations, string $testFrameworkExtraOptions): void
{
- $numberOfMutants = IterableCounter::bufferAndCountIfNeeded($mutations, $this->runConcurrently);
- $this->eventDispatcher->dispatch(new MutationTestingWasStarted($numberOfMutants));
+ $numberOfMutations = IterableCounter::bufferAndCountIfNeeded($mutations, $this->runConcurrently);
+ $this->eventDispatcher->dispatch(new MutationTestingWasStarted($numberOfMutations));
$processes = take($mutations)
- ->map(function (Mutation $mutation): Mutant {
- return $this->mutantFactory->create($mutation);
- })
- ->filter(function (Mutant $mutant) {
- // It's a proxy call to Mutation, can be done one stage up
- if ($mutant->isCoveredByTest()) {
+ ->filter(function (Mutation $mutation) {
+ if ($mutation->isCoveredByTest()) {
return true;
}
$this->eventDispatcher->dispatch(new MutantProcessWasFinished(
- MutantExecutionResult::createFromNonCoveredMutant($mutant)
+ MutantExecutionResult::createFromNonCoveredByTestsMutation($mutation)
));
return false;
})
- ->map(function (Mutant $mutant) use ($testFrameworkExtraOptions): ProcessBearer {
- $this->fileSystem->dumpFile($mutant->getFilePath(), $mutant->getMutatedCode());
+ ->map(function (Mutation $mutation) use ($testFrameworkExtraOptions): ProcessBearer {
+ $this->fileSystem->dumpFile($mutation->getFilePath(), $mutation->getMutatedCode());
- $process = $this->processFactory->createProcessForMutant($mutant, $testFrameworkExtraOptions);
+ $process = $this->processFactory->createProcessForMutation(
+ $mutation,
+ $testFrameworkExtraOptions
+ );
return $process;
})
diff --git a/src/TestFramework/AbstractTestFrameworkAdapter.php b/src/TestFramework/AbstractTestFrameworkAdapter.php
index 599196ca9..09cf0ba05 100644
--- a/src/TestFramework/AbstractTestFrameworkAdapter.php
+++ b/src/TestFramework/AbstractTestFrameworkAdapter.php
@@ -98,7 +98,7 @@ public function getInitialTestRunCommandLine(
}
/**
- * Returns array of arguments to pass them into the Mutant Symfony Process
+ * Returns array of arguments to pass them into the Mutant Symfony's process
*
* @param TestLocation[] $tests
*
diff --git a/src/TestFramework/Config/MutationConfigBuilder.php b/src/TestFramework/Config/MutationConfigBuilder.php
index 15daf7fc8..62124a302 100644
--- a/src/TestFramework/Config/MutationConfigBuilder.php
+++ b/src/TestFramework/Config/MutationConfigBuilder.php
@@ -58,8 +58,11 @@ abstract public function build(
string $mutationOriginalFilePath
): string;
- protected function getInterceptorFileContent(string $interceptorPath, string $originalFilePath, string $mutantFilePath): string
- {
+ protected function getInterceptorFileContent(
+ string $interceptorPath,
+ string $originalFilePath,
+ string $mutantFilePath
+ ): string {
$infectionPhar = '';
if (strpos(__FILE__, 'phar:') === 0) {
diff --git a/src/TestFramework/PhpUnit/Config/Builder/MutationConfigBuilder.php b/src/TestFramework/PhpUnit/Config/Builder/MutationConfigBuilder.php
index 063a8ba04..623b45e0e 100644
--- a/src/TestFramework/PhpUnit/Config/Builder/MutationConfigBuilder.php
+++ b/src/TestFramework/PhpUnit/Config/Builder/MutationConfigBuilder.php
@@ -78,7 +78,6 @@ public function __construct(
) {
$this->tmpDir = $tmpDir;
$this->projectDir = $projectDir;
-
$this->originalXmlConfigContent = $originalXmlConfigContent;
$this->configManipulator = $configManipulator;
$this->jUnitTestCaseSorter = $jUnitTestCaseSorter;
diff --git a/src/TestFramework/TestFrameworkExtraOptionsFilter.php b/src/TestFramework/TestFrameworkExtraOptionsFilter.php
index 417d5ff4e..926462b97 100644
--- a/src/TestFramework/TestFrameworkExtraOptionsFilter.php
+++ b/src/TestFramework/TestFrameworkExtraOptionsFilter.php
@@ -47,14 +47,17 @@ final class TestFrameworkExtraOptionsFilter
{
/**
* @param string[] $initialRunOnlyOptions
- *
- * @throws \Safe\Exceptions\PcreException
- * @throws \Safe\Exceptions\StringsException
*/
- public function filterForMutantProcess(string $actualExtraOptions, array $initialRunOnlyOptions): string
- {
+ public function filterForMutantProcess(
+ string $actualExtraOptions,
+ array $initialRunOnlyOptions
+ ): string {
foreach ($initialRunOnlyOptions as $initialRunOnlyOption) {
- $actualExtraOptions = preg_replace(sprintf('/%s[\=| ](?:\"[^\"]*\"|\'[^\']*\'|[^\ ]*)/', $initialRunOnlyOption), '', $actualExtraOptions);
+ $actualExtraOptions = preg_replace(
+ sprintf('/%s[\=| ](?:\"[^\"]*\"|\'[^\']*\'|[^\ ]*)/', $initialRunOnlyOption),
+ '',
+ $actualExtraOptions
+ );
Assert::notNull($actualExtraOptions);
}
diff --git a/tests/phpunit/AutoReview/ContainerTest.php b/tests/phpunit/AutoReview/ContainerTest.php
index fbf1569fb..949aa0c2c 100644
--- a/tests/phpunit/AutoReview/ContainerTest.php
+++ b/tests/phpunit/AutoReview/ContainerTest.php
@@ -98,6 +98,7 @@ static function (string $path): string {
__DIR__ . '/ContainerTest.php',
__DIR__ . '/../ContainerTest.php',
__DIR__ . '/../SingletonContainer.php',
+ __DIR__ . '/../Mutation/FileMutationGeneratorTest.php',
]
);
diff --git a/tests/phpunit/AutoReview/Event/SubscriberTest.php b/tests/phpunit/AutoReview/Event/SubscriberTest.php
index 6ca6660f8..394659077 100644
--- a/tests/phpunit/AutoReview/Event/SubscriberTest.php
+++ b/tests/phpunit/AutoReview/Event/SubscriberTest.php
@@ -109,7 +109,10 @@ private function assertIsSubscriptionMethod(string $subscriberClass, ReflectionM
$this->assertSame(
$expectedSubscriptionMethodName,
$method->getName(),
- 'Expected the subscription method to follow the project naming convention'
+ sprintf(
+ 'Expected the subscription method of "%s" to follow the project naming convention',
+ $subscriberClass
+ )
);
}
}
diff --git a/tests/phpunit/Event/MutantProcessWasFinishedTest.php b/tests/phpunit/Event/MutantProcessWasFinishedTest.php
index c773bb9ac..63dab4023 100644
--- a/tests/phpunit/Event/MutantProcessWasFinishedTest.php
+++ b/tests/phpunit/Event/MutantProcessWasFinishedTest.php
@@ -41,7 +41,7 @@
final class MutantProcessWasFinishedTest extends TestCase
{
- public function test_it_exposes_its_mutant_process(): void
+ public function test_it_exposes_its_execution_result(): void
{
$executionResultMock = $this->createMock(MutantExecutionResult::class);
diff --git a/tests/phpunit/Fixtures/SimpleMutation.php b/tests/phpunit/Fixtures/SimpleMutation.php
index 061461498..926c451ec 100644
--- a/tests/phpunit/Fixtures/SimpleMutation.php
+++ b/tests/phpunit/Fixtures/SimpleMutation.php
@@ -5,54 +5,50 @@
namespace Infection\Tests\Fixtures;
use Infection\Mutation\Mutation;
-use Infection\Mutator\Mutator;
+use Infection\Mutation\MutationAttributeKeys;
use Infection\PhpParser\MutatedNode;
use PhpParser\Node;
class SimpleMutation extends Mutation
{
- /**
- * @var Mutator
- */
- private $mutator;
-
- /**
- * @var Node[]
- */
private $originalFileAst;
-
- /**
- * @var MutatedNode
- */
private $mutatedNode;
- /**
- * @var array
- */
private $attributes;
- /**
- * @var string
- */
private $mutatedNodeClass;
+ /**
+ * @param Node[] $originalFileAst
+ * @param class-string $mutatorName
+ * @param array $attributes
+ * @param class-string $mutatedNodeClass
+ */
public function __construct(
array $originalFileAst,
- Mutator $mutator,
- $mutatedNode,
+ string $mutatorName,
+ MutatedNode $mutatedNode,
array $attributes,
string $mutatedNodeClass
) {
+ parent::__construct(
+ '/path/to/Foo.php',
+ $mutatorName,
+ (int) $attributes[MutationAttributeKeys::START_LINE],
+ [],
+ 'hash',
+ '/path/to/MutatedFoo.php',
+ 'mutatedCode',
+ 'diff'
+ );
+
$this->originalFileAst = $originalFileAst;
- $this->mutator = $mutator;
$this->mutatedNode = $mutatedNode;
$this->attributes = $attributes;
$this->mutatedNodeClass = $mutatedNodeClass;
}
- public function getMutator(): Mutator
- {
- return $this->mutator;
- }
-
+ /**
+ * @return Node[]
+ */
public function getOriginalFileAst(): array
{
return $this->originalFileAst;
@@ -63,6 +59,9 @@ public function getMutatedNode(): MutatedNode
return $this->mutatedNode;
}
+ /**
+ * @return array
+ */
public function getAttributes(): array
{
return $this->attributes;
diff --git a/tests/phpunit/Fixtures/SimpleMutationsCollectorVisitor.php b/tests/phpunit/Fixtures/SimpleMutationsCollectorVisitor.php
index 33e053386..71c0937a6 100644
--- a/tests/phpunit/Fixtures/SimpleMutationsCollectorVisitor.php
+++ b/tests/phpunit/Fixtures/SimpleMutationsCollectorVisitor.php
@@ -14,10 +14,8 @@
*/
final class SimpleMutationsCollectorVisitor extends NodeVisitorAbstract
{
- /**
- * @var Mutator[]
- */
private $mutator;
+ private $fileAst;
/**
* @var SimpleMutation[]
@@ -25,10 +23,9 @@ final class SimpleMutationsCollectorVisitor extends NodeVisitorAbstract
private $mutations = [];
/**
- * @var Node[]
+ * @param Mutator $mutator
+ * @param Node[] $fileAst
*/
- private $fileAst;
-
public function __construct(Mutator $mutator, array $fileAst)
{
$this->mutator = $mutator;
@@ -46,7 +43,7 @@ public function leaveNode(Node $node)
foreach ($this->mutator->mutate($node) as $mutatedNode) {
$this->mutations[] = new SimpleMutation(
$this->fileAst,
- $this->mutator,
+ $this->mutator->getName(),
MutatedNode::wrap($mutatedNode),
$node->getAttributes(),
get_class($node)
diff --git a/tests/phpunit/Fixtures/TestFramework/DummyTestFrameworkAdapter.php b/tests/phpunit/Fixtures/TestFramework/DummyTestFrameworkAdapter.php
index 7f2d982a7..fcf94fd83 100644
--- a/tests/phpunit/Fixtures/TestFramework/DummyTestFrameworkAdapter.php
+++ b/tests/phpunit/Fixtures/TestFramework/DummyTestFrameworkAdapter.php
@@ -23,12 +23,22 @@ public function hasJUnitReport(): bool
return false;
}
- public function getInitialTestRunCommandLine(string $extraOptions, array $phpExtraArgs, bool $skipCoverage): array
+ public function getInitialTestRunCommandLine(
+ string $extraOptions,
+ array $phpExtraArgs,
+ bool $skipCoverage
+ ): array
{
return ['/bin/dummy'];
}
- public function getMutantCommandLine(array $coverageTests, string $mutatedFilePath, string $mutationHash, string $mutationOriginalFilePath, string $extraOptions): array
+ public function getMutantCommandLine(
+ array $coverageTests,
+ string $mutatedFilePath,
+ string $mutationHash,
+ string $mutationOriginalFilePath,
+ string $extraOptions
+ ): array
{
return ['/bin/dummy'];
}
diff --git a/tests/phpunit/Metrics/MetricsCalculatorTest.php b/tests/phpunit/Metrics/MetricsCalculatorTest.php
index 3d635ebc9..d76e467dd 100644
--- a/tests/phpunit/Metrics/MetricsCalculatorTest.php
+++ b/tests/phpunit/Metrics/MetricsCalculatorTest.php
@@ -74,27 +74,27 @@ public function test_it_collects_all_values(): void
{
$calculator = new MetricsCalculator(2);
- $expectedKilledResults = $this->addMutantExecutionResult(
+ $expectedKilledResults = $this->addMutationExecutionResult(
$calculator,
DetectionStatus::KILLED,
7
);
- $expectedErrorResults = $this->addMutantExecutionResult(
+ $expectedErrorResults = $this->addMutationExecutionResult(
$calculator,
DetectionStatus::ERROR,
2
);
- $expectedEscapedResults = $this->addMutantExecutionResult(
+ $expectedEscapedResults = $this->addMutationExecutionResult(
$calculator,
DetectionStatus::ESCAPED,
2
);
- $expectedTimedOutResults = $this->addMutantExecutionResult(
+ $expectedTimedOutResults = $this->addMutationExecutionResult(
$calculator,
DetectionStatus::TIMED_OUT,
2
);
- $expectedNotCoveredResults = $this->addMutantExecutionResult(
+ $expectedNotCoveredResults = $this->addMutationExecutionResult(
$calculator,
DetectionStatus::NOT_COVERED,
1
@@ -139,7 +139,7 @@ public function test_its_metrics_are_properly_updated_when_adding_a_new_process(
$this->assertSame(0.0, $calculator->getCoverageRate());
$this->assertSame(0.0, $calculator->getCoveredCodeMutationScoreIndicator());
- $expectedKilledResults = $this->addMutantExecutionResult(
+ $expectedKilledResults = $this->addMutationExecutionResult(
$calculator,
DetectionStatus::KILLED,
1
@@ -156,7 +156,7 @@ public function test_its_metrics_are_properly_updated_when_adding_a_new_process(
/**
* @return MutantExecutionResult[]
*/
- private function addMutantExecutionResult(
+ private function addMutationExecutionResult(
MetricsCalculator $calculator,
string $detectionStatus,
int $count
diff --git a/tests/phpunit/Mutant/MutantCodeFactoryTest.php b/tests/phpunit/Mutant/MutantCodeFactoryTest.php
index 450443df3..2bbf47d5b 100644
--- a/tests/phpunit/Mutant/MutantCodeFactoryTest.php
+++ b/tests/phpunit/Mutant/MutantCodeFactoryTest.php
@@ -36,10 +36,7 @@
namespace Infection\Tests\Mutant;
use Infection\Mutant\MutantCodeFactory;
-use Infection\Mutation\Mutation;
-use Infection\Mutator\Arithmetic\Plus;
use Infection\PhpParser\MutatedNode;
-use Infection\Tests\Mutator\MutatorName;
use Infection\Tests\SingletonContainer;
use PhpParser\Node;
use PHPUnit\Framework\TestCase;
@@ -58,27 +55,51 @@ protected function setUp(): void
/**
* @dataProvider mutationProvider
+ *
+ * @param array $attributes
+ * @param Node[] $originalFileAst
+ * @param class-string $mutatedNodeClass
*/
- public function test_it_creates_the_mutant_code_from_the_given_mutation(
- Mutation $mutation,
- string $expectedMutantCode
+ public function test_it_creates_the_mutation_code_from_the_given_nodes(
+ array $attributes,
+ array $originalFileAst,
+ string $mutatedNodeClass,
+ MutatedNode $mutatedNode,
+ string $expectedMutationCode
): void {
- $mutantCode = $this->codeFactory->createCode($mutation);
+ $mutationCode = $this->codeFactory->createCode(
+ $attributes,
+ $originalFileAst,
+ $mutatedNodeClass,
+ $mutatedNode
+ );
- $this->assertSame($expectedMutantCode, $mutantCode);
+ $this->assertSame($expectedMutationCode, $mutationCode);
}
/**
* @dataProvider mutationProvider
+ *
+ * @param array $attributes
+ * @param Node[] $originalFileAst
+ * @param class-string $mutatedNodeClass
*/
- public function test_it_creates_the_mutant_code_without_altering_the_original_nodes(
- Mutation $mutation
+ public function test_it_creates_the_mutation_code_without_altering_the_original_nodes(
+ array $attributes,
+ array $originalFileAst,
+ string $mutatedNodeClass,
+ MutatedNode $mutatedNode
): void {
- $originalNodesDump = SingletonContainer::getNodeDumper()->dump($mutation->getOriginalFileAst());
+ $originalNodesDump = SingletonContainer::getNodeDumper()->dump($originalFileAst);
- $this->codeFactory->createCode($mutation);
+ $this->codeFactory->createCode(
+ $attributes,
+ $originalFileAst,
+ $mutatedNodeClass,
+ $mutatedNode
+ );
- $originalNodesDumpAfterMutation = SingletonContainer::getNodeDumper()->dump($mutation->getOriginalFileAst());
+ $originalNodesDumpAfterMutation = SingletonContainer::getNodeDumper()->dump($originalFileAst);
$this->assertSame($originalNodesDump, $originalNodesDumpAfterMutation);
}
@@ -86,79 +107,73 @@ public function test_it_creates_the_mutant_code_without_altering_the_original_no
public function mutationProvider(): iterable
{
yield [
- new Mutation(
- '/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name(
- 'Acme',
- [
- 'startLine' => 3,
- 'startTokenPos' => 4,
- 'startFilePos' => 17,
- 'endLine' => 3,
- 'endTokenPos' => 4,
- 'endFilePos' => 20,
- ]
- ),
- [new Node\Stmt\Echo_(
- [new Node\Scalar\LNumber(
- 10,
- [
- 'startLine' => 5,
- 'startTokenPos' => 9,
- 'startFilePos' => 29,
- 'endLine' => 5,
- 'endTokenPos' => 9,
- 'endFilePos' => 30,
- 'kind' => 10,
- ]
- )],
+ [
+ 'startLine' => 5,
+ 'startTokenPos' => 9,
+ 'startFilePos' => 29,
+ 'endLine' => 5,
+ 'endTokenPos' => 9,
+ 'endFilePos' => 30,
+ 'kind' => 10,
+ ],
+ [new Node\Stmt\Namespace_(
+ new Node\Name(
+ 'Acme',
+ [
+ 'startLine' => 3,
+ 'startTokenPos' => 4,
+ 'startFilePos' => 17,
+ 'endLine' => 3,
+ 'endTokenPos' => 4,
+ 'endFilePos' => 20,
+ ]
+ ),
+ [new Node\Stmt\Echo_(
+ [new Node\Scalar\LNumber(
+ 10,
[
'startLine' => 5,
- 'startTokenPos' => 7,
- 'startFilePos' => 24,
+ 'startTokenPos' => 9,
+ 'startFilePos' => 29,
'endLine' => 5,
- 'endTokenPos' => 10,
- 'endFilePos' => 31,
+ 'endTokenPos' => 9,
+ 'endFilePos' => 30,
+ 'kind' => 10,
]
)],
[
- 'startLine' => 3,
- 'startTokenPos' => 2,
- 'startFilePos' => 7,
+ 'startLine' => 5,
+ 'startTokenPos' => 7,
+ 'startFilePos' => 24,
'endLine' => 5,
'endTokenPos' => 10,
'endFilePos' => 31,
- 'kind' => 1,
]
)],
- MutatorName::getName(Plus::class),
[
- 'startLine' => 5,
- 'startTokenPos' => 9,
- 'startFilePos' => 29,
+ 'startLine' => 3,
+ 'startTokenPos' => 2,
+ 'startFilePos' => 7,
'endLine' => 5,
- 'endTokenPos' => 9,
- 'endFilePos' => 30,
- 'kind' => 10,
- ],
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(
- new Node\Scalar\LNumber(
- 15,
- [
- 'startLine' => 5,
- 'startTokenPos' => 9,
- 'startFilePos' => 29,
- 'endLine' => 5,
- 'endTokenPos' => 9,
- 'endFilePos' => 30,
- 'kind' => 10,
- ]
- )
- ),
- 0,
- []
+ 'endTokenPos' => 10,
+ 'endFilePos' => 31,
+ 'kind' => 1,
+ ]
+ )],
+ Node\Scalar\LNumber::class,
+ MutatedNode::wrap(
+ new Node\Scalar\LNumber(
+ 15,
+ [
+ 'startLine' => 5,
+ 'startTokenPos' => 9,
+ 'startFilePos' => 29,
+ 'endLine' => 5,
+ 'endTokenPos' => 9,
+ 'endFilePos' => 30,
+ 'kind' => 10,
+ ]
+ )
),
<<<'PHP'
method($this->anything())
;
- $mutantProcess = new MutantProcess(
- $processMock,
- new Mutant(
- '/path/to/mutant',
- new Mutation(
- $originalFilePath = 'path/to/Foo.php',
- [],
- $mutatorName = MutatorName::getName(For_::class),
- [
- 'startLine' => $originalStartingLine = 10,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
- []
- ),
- 'notCovered#0',
- $mutantDiff = <<<'DIFF'
+ $mutationDiff = <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -124,7 +100,19 @@ public function test_it_can_create_a_result_from_a_non_covered_mutant_process():
- echo 'original';
+ echo 'notCovered#0';
-DIFF
+DIFF;
+
+ $mutantProcess = new MutantProcess(
+ $processMock,
+ new Mutation(
+ $originalFilePath = 'path/to/Foo.php',
+ $mutatorName = MutatorName::getName(For_::class),
+ $originalStartingLine = 10,
+ [],
+ '0800f',
+ '/path/to/mutation',
+ 'notCovered#0',
+ $mutationDiff
)
);
@@ -133,7 +121,7 @@ public function test_it_can_create_a_result_from_a_non_covered_mutant_process():
$processCommandLine,
$processOutput,
DetectionStatus::NOT_COVERED,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
@@ -163,35 +151,7 @@ public function test_it_can_create_a_result_from_a_timed_out_mutant_process(): v
->method($this->anything())
;
- $mutantProcess = new MutantProcess(
- $processMock,
- new Mutant(
- '/path/to/mutant',
- new Mutation(
- $originalFilePath = 'path/to/Foo.php',
- [],
- $mutatorName = MutatorName::getName(For_::class),
- [
- 'startLine' => $originalStartingLine = 10,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ]
- ),
- 'timedOut#0',
- $mutantDiff = <<<'DIFF'
+ $mutationDiff = <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -199,9 +159,28 @@ public function test_it_can_create_a_result_from_a_timed_out_mutant_process(): v
- echo 'original';
+ echo 'timedOut#0';
-DIFF
+DIFF;
+
+ $mutantProcess = new MutantProcess(
+ $processMock,
+ new Mutation(
+ $originalFilePath = 'path/to/Foo.php',
+ $mutatorName = MutatorName::getName(For_::class),
+ $originalStartingLine = 10,
+ [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ '0800f',
+ '/path/to/mutation',
+ 'timedOut#0',
+ $mutationDiff
)
);
+
$mutantProcess->markAsTimedOut();
$this->assertResultStateIs(
@@ -209,7 +188,7 @@ public function test_it_can_create_a_result_from_a_timed_out_mutant_process(): v
$processCommandLine,
$processOutput,
DetectionStatus::TIMED_OUT,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
@@ -244,35 +223,7 @@ public function test_it_can_create_a_result_from_an_errored_mutant_process(): vo
->method($this->anything())
;
- $mutantProcess = new MutantProcess(
- $processMock,
- new Mutant(
- '/path/to/mutant',
- new Mutation(
- $originalFilePath = 'path/to/Foo.php',
- [],
- $mutatorName = MutatorName::getName(For_::class),
- [
- 'startLine' => $originalStartingLine = 10,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ]
- ),
- 'errored#0',
- $mutantDiff = <<<'DIFF'
+ $mutationDiff = <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -280,7 +231,25 @@ public function test_it_can_create_a_result_from_an_errored_mutant_process(): vo
- echo 'original';
+ echo 'errored#0';
-DIFF
+DIFF;
+
+ $mutantProcess = new MutantProcess(
+ $processMock,
+ new Mutation(
+ $originalFilePath = 'path/to/Foo.php',
+ $mutatorName = MutatorName::getName(For_::class),
+ $originalStartingLine = 10,
+ [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ '0800f',
+ '/path/to/mutation',
+ 'errored#0',
+ $mutationDiff
)
);
@@ -289,7 +258,7 @@ public function test_it_can_create_a_result_from_an_errored_mutant_process(): vo
$processCommandLine,
$processOutput,
DetectionStatus::ERROR,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
@@ -326,35 +295,7 @@ public function test_it_can_crate_a_result_from_an_escaped_mutant_process(): voi
->willReturn(true)
;
- $mutantProcess = new MutantProcess(
- $processMock,
- new Mutant(
- '/path/to/mutant',
- new Mutation(
- $originalFilePath = 'path/to/Foo.php',
- [],
- $mutatorName = MutatorName::getName(For_::class),
- [
- 'startLine' => $originalStartingLine = 10,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ]
- ),
- 'escaped#0',
- $mutantDiff = <<<'DIFF'
+ $mutationDiff = <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -362,7 +303,25 @@ public function test_it_can_crate_a_result_from_an_escaped_mutant_process(): voi
- echo 'original';
+ echo 'escaped#0';
-DIFF
+DIFF;
+
+ $mutantProcess = new MutantProcess(
+ $processMock,
+ new Mutation(
+ $originalFilePath = 'path/to/Foo.php',
+ $mutatorName = MutatorName::getName(For_::class),
+ $originalStartingLine = 10,
+ [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ '0800f',
+ '/path/to/mutation',
+ 'escaped#0',
+ $mutationDiff
)
);
@@ -371,7 +330,7 @@ public function test_it_can_crate_a_result_from_an_escaped_mutant_process(): voi
$processCommandLine,
'Tests passed!',
DetectionStatus::ESCAPED,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
@@ -408,35 +367,7 @@ public function test_it_can_crate_a_result_from_a_killed_mutant_process(): void
->willReturn(false)
;
- $mutantProcess = new MutantProcess(
- $processMock,
- new Mutant(
- '/path/to/mutant',
- new Mutation(
- $originalFilePath = 'path/to/Foo.php',
- [],
- $mutatorName = MutatorName::getName(For_::class),
- [
- 'startLine' => $originalStartingLine = 10,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ]
- ),
- 'killed#0',
- $mutantDiff = <<<'DIFF'
+ $mutationDiff = <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -444,7 +375,25 @@ public function test_it_can_crate_a_result_from_a_killed_mutant_process(): void
- echo 'original';
+ echo 'killed#0';
-DIFF
+DIFF;
+
+ $mutantProcess = new MutantProcess(
+ $processMock,
+ new Mutation(
+ $originalFilePath = 'path/to/Foo.php',
+ $mutatorName = MutatorName::getName(For_::class),
+ $originalStartingLine = 10,
+ [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ '0800f',
+ '/path/to/mutation',
+ 'killed#0',
+ $mutationDiff
)
);
@@ -453,7 +402,7 @@ public function test_it_can_crate_a_result_from_a_killed_mutant_process(): void
$processCommandLine,
'Tests failed!',
DetectionStatus::KILLED,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
diff --git a/tests/phpunit/Mutant/MutantExecutionResultTest.php b/tests/phpunit/Mutant/MutantExecutionResultTest.php
index 365219dde..a92a9a588 100644
--- a/tests/phpunit/Mutant/MutantExecutionResultTest.php
+++ b/tests/phpunit/Mutant/MutantExecutionResultTest.php
@@ -37,25 +37,20 @@
use Infection\AbstractTestFramework\Coverage\TestLocation;
use Infection\Mutant\DetectionStatus;
-use Infection\Mutant\Mutant;
use Infection\Mutant\MutantExecutionResult;
use Infection\Mutation\Mutation;
use Infection\Mutator\ZeroIteration\For_;
-use Infection\PhpParser\MutatedNode;
use Infection\Tests\Mutator\MutatorName;
-use PhpParser\Node\Stmt\Nop;
use PHPUnit\Framework\TestCase;
final class MutantExecutionResultTest extends TestCase
{
- use MutantExecutionResultAssertions;
-
public function test_it_can_be_instantiated(): void
{
$processCommandLine = 'bin/phpunit --configuration infection-tmp-phpunit.xml --filter "tests/Acme/FooTest.php"';
$processOutput = 'Passed!';
$processResultCode = DetectionStatus::ESCAPED;
- $mutantDiff = <<<'DIFF'
+ $mutationDiff = <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -73,7 +68,7 @@ public function test_it_can_be_instantiated(): void
$processCommandLine,
$processOutput,
$processResultCode,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
@@ -84,42 +79,16 @@ public function test_it_can_be_instantiated(): void
$processCommandLine,
$processOutput,
$processResultCode,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
);
}
- public function test_it_can_be_instantiated_from_a_non_covered_mutant(): void
+ public function test_it_can_be_instantiated_from_a_mutation_non_covered_by_tests(): void
{
- $mutant = new Mutant(
- '/path/to/mutant',
- new Mutation(
- $originalFilePath = 'path/to/Foo.php',
- [],
- $mutatorName = MutatorName::getName(For_::class),
- [
- 'startLine' => $originalStartingLine = 10,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ]
- ),
- 'notCovered#0',
- $mutantDiff = <<<'DIFF'
+ $mutationDiff = <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -127,15 +96,31 @@ public function test_it_can_be_instantiated_from_a_non_covered_mutant(): void
- echo 'original';
+ echo 'notCovered#0';
-DIFF
+DIFF;
+
+ $mutation = new Mutation(
+ $originalFilePath = 'path/to/Foo.php',
+ $mutatorName = MutatorName::getName(For_::class),
+ $originalStartingLine = 10,
+ [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ '0800f',
+ '/path/to/mutation',
+ 'notCovered#0',
+ $mutationDiff
);
$this->assertResultStateIs(
- MutantExecutionResult::createFromNonCoveredMutant($mutant),
+ MutantExecutionResult::createFromNonCoveredByTestsMutation($mutation),
'',
'',
DetectionStatus::NOT_COVERED,
- $mutantDiff,
+ $mutationDiff,
$mutatorName,
$originalFilePath,
$originalStartingLine
@@ -147,7 +132,7 @@ private function assertResultStateIs(
string $expectedProcessCommandLine,
string $expectedProcessOutput,
string $expectedDetectionStatus,
- string $expectedMutantDiff,
+ string $expectedMutationDiff,
string $expectedMutatorName,
string $expectedOriginalFilePath,
int $expectedOriginalStartingLine
@@ -155,7 +140,7 @@ private function assertResultStateIs(
$this->assertSame($expectedProcessCommandLine, $result->getProcessCommandLine());
$this->assertSame($expectedProcessOutput, $result->getProcessOutput());
$this->assertSame($expectedDetectionStatus, $result->getDetectionStatus());
- $this->assertSame($expectedMutantDiff, $result->getMutantDiff());
+ $this->assertSame($expectedMutationDiff, $result->getMutationDiff());
$this->assertSame($expectedMutatorName, $result->getMutatorName());
$this->assertSame($expectedOriginalFilePath, $result->getOriginalFilePath());
$this->assertSame($expectedOriginalStartingLine, $result->getOriginalStartingLine());
diff --git a/tests/phpunit/Mutant/MutantFactoryTest.php b/tests/phpunit/Mutant/MutantFactoryTest.php
deleted file mode 100644
index cd6a11757..000000000
--- a/tests/phpunit/Mutant/MutantFactoryTest.php
+++ /dev/null
@@ -1,197 +0,0 @@
-codeFactoryMock = $this->createMock(MutantCodeFactory::class);
-
- $this->printerMock = $this->createMock(PrettyPrinterAbstract::class);
-
- $this->differMock = $this->createMock(Differ::class);
-
- $this->mutantFactory = new MutantFactory(
- '/path/to/tmp',
- $this->differMock,
- $this->printerMock,
- $this->codeFactoryMock
- );
- }
-
- public function test_it_creates_a_mutant_instance_from_the_given_mutation(): void
- {
- $mutation = self::createMutation(
- $originalNodes = [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
- $tests = [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ]
- );
-
- $expectedMutantFilePath = sprintf(
- '/path/to/tmp/mutant.%s.infection.php',
- $mutation->getHash()
- );
-
- $this->codeFactoryMock
- ->expects($this->once())
- ->method('createCode')
- ->with($mutation)
- ->willReturn('mutated code')
- ;
-
- $this->printerMock
- ->expects($this->once())
- ->method('prettyPrintFile')
- ->with($originalNodes)
- ->willReturn('original code')
- ;
-
- $this->differMock
- ->expects($this->once())
- ->method('diff')
- ->with('original code', 'mutated code')
- ->willReturn('code diff')
- ;
-
- $mutant = $this->mutantFactory->create($mutation);
-
- $this->assertMutantStateIs(
- $mutant,
- $expectedMutantFilePath,
- $mutation,
- 'mutated code',
- 'code diff',
- true,
- $tests
- );
- }
-
- public function test_it_printing_the_original_file_is_memoized(): void
- {
- $mutation = self::createMutation(
- $originalNodes = [new Node\Stmt\Nop()],
- []
- );
-
- $this->printerMock
- ->expects($this->once())
- ->method('prettyPrintFile')
- ->with($originalNodes)
- ->willReturn('original code')
- ;
-
- $this->differMock
- ->expects($this->atLeastOnce())
- ->method('diff')
- ->willReturn('code diff')
- ;
-
- $this->mutantFactory->create($mutation);
- $this->mutantFactory->create($mutation);
- }
-
- /**
- * @param Node[] $originalNodes
- * @param TestLocation[] $tests
- */
- private static function createMutation(array $originalNodes, array $tests): Mutation
- {
- return new Mutation(
- '/path/to/acme/Foo.php',
- $originalNodes,
- MutatorName::getName(Plus::class),
- [
- 'startLine' => 3,
- 'endLine' => 5,
- 'startTokenPos' => 21,
- 'endTokenPos' => 31,
- 'startFilePos' => 43,
- 'endFilePos' => 53,
- ],
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- 0,
- $tests
- );
- }
-}
diff --git a/tests/phpunit/Mutant/MutantTest.php b/tests/phpunit/Mutant/MutantTest.php
deleted file mode 100644
index a857b9bc0..000000000
--- a/tests/phpunit/Mutant/MutantTest.php
+++ /dev/null
@@ -1,138 +0,0 @@
-assertMutantStateIs(
- $mutant,
- $filePath,
- $mutation,
- $mutatedCode,
- $diff,
- $expectedCoveredByTests,
- $expectedTests
- );
- }
-
- public function valuesProvider(): iterable
- {
- $nominalAttributes = [
- 'startLine' => 3,
- 'endLine' => 5,
- 'startTokenPos' => 21,
- 'endTokenPos' => 31,
- 'startFilePos' => 43,
- 'endFilePos' => 53,
- ];
-
- $tests = [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ];
-
- yield 'nominal with tests' => [
- '/path/to/tmp/mutant.Foo.infection.php',
- new Mutation(
- '/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
- MutatorName::getName(Plus::class),
- $nominalAttributes,
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- 0,
- $tests
- ),
- 'mutated code',
- 'diff value',
- true,
- $tests,
- ];
-
- yield 'nominal without tests' => [
- '/path/to/tmp/mutant.Foo.infection.php',
- new Mutation(
- '/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
- MutatorName::getName(Plus::class),
- $nominalAttributes,
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- 0,
- []
- ),
- 'mutated code',
- 'diff value',
- false,
- [],
- ];
- }
-}
diff --git a/tests/phpunit/Mutant/MutationFactoryTest.php b/tests/phpunit/Mutant/MutationFactoryTest.php
new file mode 100644
index 000000000..806c56efc
--- /dev/null
+++ b/tests/phpunit/Mutant/MutationFactoryTest.php
@@ -0,0 +1,277 @@
+codeFactoryMock = $this->createMock(MutantCodeFactory::class);
+ $this->printerMock = $this->createMock(PrettyPrinterAbstract::class);
+ $this->differMock = $this->createMock(Differ::class);
+
+ $this->mutationFactory = new MutationFactory(
+ '/path/to/tmp',
+ $this->differMock,
+ $this->printerMock,
+ $this->codeFactoryMock
+ );
+ }
+
+ /**
+ * @dataProvider valuesProvider
+ *
+ * @param Node[] $originalFileAst
+ * @param array $attributes
+ * @param class-string $mutatedNodeClass
+ * @param TestLocation[] $tests
+ * @param array $expectedFilteredAttributes
+ */
+ public function test_it_creates_a_mutation(
+ string $originalFilePath,
+ array $originalFileAst,
+ string $mutatorName,
+ array $attributes,
+ string $mutatedNodeClass,
+ MutatedNode $mutatedNode,
+ int $mutationByMutatorIndex,
+ array $tests,
+ array $expectedFilteredAttributes,
+ string $expectedHash,
+ string $expectedMutationFilePath,
+ int $expectedOriginalStartingLine
+ ): void {
+ $this->codeFactoryMock
+ ->expects($this->exactly(2))
+ ->method('createCode')
+ ->with(
+ $expectedFilteredAttributes,
+ $originalFileAst,
+ $mutatedNodeClass,
+ $mutatedNode
+ )
+ ->willReturn('mutated code')
+ ;
+
+ $this->printerMock
+ ->expects($this->once())
+ ->method('prettyPrintFile')
+ ->with($originalFileAst)
+ ->willReturn('original code')
+ ;
+
+ $this->differMock
+ ->expects($this->exactly(2))
+ ->method('diff')
+ ->with('original code', 'mutated code')
+ ->willReturn('code diff')
+ ;
+
+ $mutation1 = $this->mutationFactory->create(
+ $originalFilePath,
+ $originalFileAst,
+ $mutatorName,
+ $attributes,
+ $mutatedNodeClass,
+ $mutatedNode,
+ $mutationByMutatorIndex,
+ $tests
+ );
+
+ $this->assertMutationSateIs(
+ $mutation1,
+ $originalFilePath,
+ $mutatorName,
+ $tests,
+ $expectedHash,
+ $expectedMutationFilePath,
+ 'mutated code',
+ 'code diff',
+ $expectedOriginalStartingLine,
+ true
+ );
+
+ // Check memoization
+
+ $mutation2 = $this->mutationFactory->create(
+ $originalFilePath,
+ $originalFileAst,
+ $mutatorName,
+ $attributes,
+ $mutatedNodeClass,
+ $mutatedNode,
+ $mutationByMutatorIndex,
+ $tests
+ );
+
+ $this->assertMutationSateIs(
+ $mutation2,
+ $originalFilePath,
+ $mutatorName,
+ $tests,
+ $expectedHash,
+ $expectedMutationFilePath,
+ 'mutated code',
+ 'code diff',
+ $expectedOriginalStartingLine,
+ true
+ );
+ }
+
+ public static function valuesProvider(): iterable
+ {
+ $nominalAttributes = [
+ 'startLine' => $originalStartingLine = 3,
+ 'endLine' => 5,
+ 'startTokenPos' => 21,
+ 'endTokenPos' => 31,
+ 'startFilePos' => 43,
+ 'endFilePos' => 53,
+ ];
+
+ yield 'nominal' => (static function () use (
+ $nominalAttributes,
+ $originalStartingLine
+ ): array {
+ $expectedHash = md5('/path/to/acme/Foo.php_Plus_0_3_5_21_31_43_53');
+
+ return [
+ '/path/to/acme/Foo.php',
+ [
+ new Node\Stmt\Namespace_(
+ new Node\Name('Acme'),
+ [new Node\Scalar\LNumber(0)]
+ ),
+ ],
+ MutatorName::getName(Plus::class),
+ $nominalAttributes,
+ Node\Scalar\LNumber::class,
+ MutatedNode::wrap(new Node\Scalar\LNumber(1)),
+ 0,
+ [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ $nominalAttributes,
+ $expectedHash,
+ sprintf(
+ '/path/to/tmp/mutation.%s.infection.php',
+ $expectedHash
+ ),
+ $originalStartingLine,
+ ];
+ })();
+
+ yield 'with additional attributes' => (static function () use (
+ $nominalAttributes,
+ $originalStartingLine
+ ): array {
+ $expectedHash = md5('/path/to/acme/Foo.php_Plus_0_3_5_21_31_43_53');
+
+ return [
+ '/path/to/acme/Foo.php',
+ [
+ new Node\Stmt\Namespace_(
+ new Node\Name('Acme'),
+ [new Node\Scalar\LNumber(0)]
+ ),
+ ],
+ MutatorName::getName(Plus::class),
+ array_merge($nominalAttributes, ['foo' => 100, 'bar' => 1000]),
+ Node\Scalar\LNumber::class,
+ MutatedNode::wrap(new Node\Scalar\LNumber(1)),
+ 0,
+ [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ $nominalAttributes,
+ $expectedHash,
+ sprintf(
+ '/path/to/tmp/mutation.%s.infection.php',
+ $expectedHash
+ ),
+ $originalStartingLine,
+ ];
+ })();
+ }
+}
diff --git a/tests/phpunit/Mutation/FileMutationGeneratorTest.php b/tests/phpunit/Mutation/FileMutationGeneratorTest.php
index 705122fa0..7a201a9b4 100644
--- a/tests/phpunit/Mutation/FileMutationGeneratorTest.php
+++ b/tests/phpunit/Mutation/FileMutationGeneratorTest.php
@@ -36,6 +36,7 @@
namespace Infection\Tests\Mutation;
use function current;
+use Infection\Container;
use Infection\Mutation\FileMutationGenerator;
use Infection\Mutation\Mutation;
use Infection\Mutator\Arithmetic\Plus;
@@ -49,7 +50,6 @@
use Infection\Tests\Fixtures\PhpParser\FakeIgnorer;
use Infection\Tests\Fixtures\PhpParser\FakeNode;
use Infection\Tests\Mutator\MutatorName;
-use Infection\Tests\SingletonContainer;
use PhpParser\NodeTraverserInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -70,6 +70,11 @@ final class FileMutationGeneratorTest extends TestCase
*/
private $traverserFactoryMock;
+ /**
+ * @var \Infection\Mutant\MutationFactory|MockObject
+ */
+ private $mutationFactoryMock;
+
/**
* @var FileMutationGenerator
*/
@@ -79,16 +84,41 @@ protected function setUp(): void
{
$this->fileParserMock = $this->createMock(FileParser::class);
$this->traverserFactoryMock = $this->createMock(NodeTraverserFactory::class);
+ $this->mutationFactoryMock = $this->createMock(\Infection\Mutant\MutationFactory::class);
$this->mutationGenerator = new FileMutationGenerator(
$this->fileParserMock,
$this->traverserFactoryMock,
- new LineRangeCalculator()
+ new LineRangeCalculator(),
+ $this->mutationFactoryMock
);
}
public function test_it_generates_mutations_for_a_given_file(): void
{
+ $container = Container::create()->withDynamicParameters(
+ null,
+ '',
+ false,
+ 'default',
+ false,
+ false,
+ 'dot',
+ false,
+ '/path/to/coverage',
+ '',
+ false,
+ false,
+ .0,
+ .0,
+ 2,
+ 'phpunit',
+ '',
+ '',
+ 0,
+ true
+ );
+
$traceMock = $this->createTraceMock(
self::FIXTURES_DIR . '/Mutation/OneFile/OneFile.php',
'',
@@ -104,9 +134,7 @@ public function test_it_generates_mutations_for_a_given_file(): void
->willReturn([])
;
- $mutationGenerator = SingletonContainer::getContainer()->getFileMutationGenerator();
-
- $mutations = $mutationGenerator->generate(
+ $mutations = $container->getFileMutationGenerator()->generate(
$traceMock,
false,
[new IgnoreMutator(new IgnoreConfig([]), new Plus())],
@@ -185,18 +213,24 @@ public function test_it_skips_the_mutation_generation_if_checks_only_covered_cod
): void {
$this->fileParserMock
->expects($this->never())
- ->method('parse')
+ ->method($this->anything())
;
$this->traverserFactoryMock
->expects($this->never())
- ->method('create')
+ ->method($this->anything())
+ ;
+
+ $this->mutationFactoryMock
+ ->expects($this->never())
+ ->method($this->anything())
;
$mutationGenerator = new FileMutationGenerator(
$this->fileParserMock,
$this->traverserFactoryMock,
- new LineRangeCalculator()
+ new LineRangeCalculator(),
+ $this->mutationFactoryMock
);
$mutations = $mutationGenerator->generate(
diff --git a/tests/phpunit/Mutant/MutantExecutionResultAssertions.php b/tests/phpunit/Mutation/MutantExecutionResultAssertions.php
similarity index 94%
rename from tests/phpunit/Mutant/MutantExecutionResultAssertions.php
rename to tests/phpunit/Mutation/MutantExecutionResultAssertions.php
index 316d71bde..a638db98c 100644
--- a/tests/phpunit/Mutant/MutantExecutionResultAssertions.php
+++ b/tests/phpunit/Mutation/MutantExecutionResultAssertions.php
@@ -33,7 +33,7 @@
declare(strict_types=1);
-namespace Infection\Tests\Mutant;
+namespace Infection\Tests\Mutation;
use Infection\Mutant\MutantExecutionResult;
@@ -44,7 +44,7 @@ private function assertResultStateIs(
string $expectedProcessCommandLine,
string $expectedProcessOutput,
string $expectedDetectionStatus,
- string $expectedMutantDiff,
+ string $expectedMutationDiff,
string $expectedMutatorName,
string $expectedOriginalFilePath,
int $expectedOriginalStartingLine
@@ -52,7 +52,7 @@ private function assertResultStateIs(
$this->assertSame($expectedProcessCommandLine, $result->getProcessCommandLine());
$this->assertSame($expectedProcessOutput, $result->getProcessOutput());
$this->assertSame($expectedDetectionStatus, $result->getDetectionStatus());
- $this->assertSame($expectedMutantDiff, $result->getMutantDiff());
+ $this->assertSame($expectedMutationDiff, $result->getMutationDiff());
$this->assertSame($expectedMutatorName, $result->getMutatorName());
$this->assertSame($expectedOriginalFilePath, $result->getOriginalFilePath());
$this->assertSame($expectedOriginalStartingLine, $result->getOriginalStartingLine());
diff --git a/tests/phpunit/Mutant/MutantAssertions.php b/tests/phpunit/Mutation/MutationAssertions.php
similarity index 62%
rename from tests/phpunit/Mutant/MutantAssertions.php
rename to tests/phpunit/Mutation/MutationAssertions.php
index e850267be..1639e3e40 100644
--- a/tests/phpunit/Mutant/MutantAssertions.php
+++ b/tests/phpunit/Mutation/MutationAssertions.php
@@ -33,31 +33,32 @@
declare(strict_types=1);
-namespace Infection\Tests\Mutant;
+namespace Infection\Tests\Mutation;
-use Infection\AbstractTestFramework\Coverage\TestLocation;
-use Infection\Mutant\Mutant;
use Infection\Mutation\Mutation;
-trait MutantAssertions
+trait MutationAssertions
{
- /**
- * @param TestLocation[] $expectedTests
- */
- public function assertMutantStateIs(
- Mutant $mutant,
+ private function assertMutationSateIs(
+ Mutation $mutation,
+ string $expectedOriginalFilePath,
+ string $expectedMutatorName,
+ array $expectedTests,
+ string $expectedHash,
string $expectedFilePath,
- Mutation $expectedMutation,
- string $expectedMutatedCode,
+ string $expectedCode,
string $expectedDiff,
- bool $expectedCoveredByTests,
- array $expectedTests
+ int $expectedOriginalStartingLine,
+ bool $expectedHasTests
): void {
- $this->assertSame($expectedFilePath, $mutant->getFilePath());
- $this->assertSame($expectedMutation, $mutant->getMutation());
- $this->assertSame($expectedMutatedCode, $mutant->getMutatedCode());
- $this->assertSame($expectedDiff, $mutant->getDiff());
- $this->assertSame($expectedCoveredByTests, $mutant->isCoveredByTest());
- $this->assertSame($expectedTests, $mutant->getTests());
+ $this->assertSame($expectedOriginalFilePath, $mutation->getOriginalFilePath());
+ $this->assertSame($expectedMutatorName, $mutation->getMutatorName());
+ $this->assertSame($expectedOriginalStartingLine, $mutation->getOriginalStartingLine());
+ $this->assertSame($expectedTests, $mutation->getAllTests());
+ $this->assertSame($expectedHasTests, $mutation->isCoveredByTest());
+ $this->assertSame($expectedHash, $mutation->getHash());
+ $this->assertSame($expectedFilePath, $mutation->getFilePath());
+ $this->assertSame($expectedCode, $mutation->getMutatedCode());
+ $this->assertSame($expectedDiff, $mutation->getDiff());
}
}
diff --git a/tests/phpunit/Mutation/MutationTest.php b/tests/phpunit/Mutation/MutationTest.php
index 4cb66f5e3..8b0d99f13 100644
--- a/tests/phpunit/Mutation/MutationTest.php
+++ b/tests/phpunit/Mutation/MutationTest.php
@@ -35,14 +35,10 @@
namespace Infection\Tests\Mutation;
-use function array_merge;
use Infection\AbstractTestFramework\Coverage\TestLocation;
use Infection\Mutation\Mutation;
use Infection\Mutator\Arithmetic\Plus;
-use Infection\PhpParser\MutatedNode;
use Infection\Tests\Mutator\MutatorName;
-use function md5;
-use PhpParser\Node;
use PHPUnit\Framework\TestCase;
final class MutationTest extends TestCase
@@ -50,85 +46,59 @@ final class MutationTest extends TestCase
/**
* @dataProvider valuesProvider
*
- * @param Node[] $originalFileAst
- * @param array $attributes
- * @param array $expectedAttributes
* @param TestLocation[] $tests
*/
public function test_it_can_be_instantiated(
string $originalFilePath,
- array $originalFileAst,
string $mutatorName,
- array $attributes,
- string $mutatedNodeClass,
- MutatedNode $mutatedNode,
- int $mutationByMutatorIndex,
+ int $originalStartingLine,
array $tests,
- array $expectedAttributes,
- int $expectedOriginalStartingLine,
- bool $expectedCoveredByTests,
- string $expectedHash
+ string $hash,
+ string $filePath,
+ string $code,
+ string $diff,
+ bool $expectedHasTests
): void {
$mutation = new Mutation(
$originalFilePath,
- $originalFileAst,
$mutatorName,
- $attributes,
- $mutatedNodeClass,
- $mutatedNode,
- $mutationByMutatorIndex,
- $tests
+ $originalStartingLine,
+ $tests,
+ $hash,
+ $filePath,
+ $code,
+ $diff
);
$this->assertSame($originalFilePath, $mutation->getOriginalFilePath());
- $this->assertSame($originalFileAst, $mutation->getOriginalFileAst());
$this->assertSame($mutatorName, $mutation->getMutatorName());
- $this->assertSame($expectedAttributes, $mutation->getAttributes());
- $this->assertSame($expectedOriginalStartingLine, $mutation->getOriginalStartingLine());
- $this->assertSame($mutatedNodeClass, $mutation->getMutatedNodeClass());
- $this->assertSame($mutatedNode, $mutation->getMutatedNode());
+ $this->assertSame($originalStartingLine, $mutation->getOriginalStartingLine());
$this->assertSame($tests, $mutation->getAllTests());
- $this->assertSame($expectedCoveredByTests, $mutation->isCoveredByTest());
- $this->assertSame($expectedHash, $mutation->getHash());
+ $this->assertSame($expectedHasTests, $mutation->isCoveredByTest());
+ $this->assertSame($hash, $mutation->getHash());
+ $this->assertSame($filePath, $mutation->getFilePath());
+ $this->assertSame($code, $mutation->getMutatedCode());
+ $this->assertSame($diff, $mutation->getDiff());
}
public function valuesProvider(): iterable
{
- $nominalAttributes = [
- 'startLine' => $originalStartingLine = 3,
- 'endLine' => 5,
- 'startTokenPos' => 21,
- 'endTokenPos' => 31,
- 'startFilePos' => 43,
- 'endFilePos' => 53,
- ];
-
yield 'empty' => [
'',
- [],
MutatorName::getName(Plus::class),
- $nominalAttributes,
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- -1,
+ 3,
[],
- $nominalAttributes,
- $originalStartingLine,
+ '',
+ '',
+ '',
+ '',
false,
- md5('_Plus_-1_3_5_21_31_43_53'),
];
yield 'nominal with a test' => [
'/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
MutatorName::getName(Plus::class),
- $nominalAttributes,
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- 0,
+ 3,
[
new TestLocation(
'FooTest::test_it_can_instantiate',
@@ -136,103 +106,41 @@ public function valuesProvider(): iterable
0.01
),
],
- $nominalAttributes,
- $originalStartingLine,
- true,
- md5('/path/to/acme/Foo.php_Plus_0_3_5_21_31_43_53'),
- ];
+ '0800f',
+ '/path/to/mutation',
+ 'notCovered#0',
+ <<<'DIFF'
+--- Original
++++ New
+@@ @@
- yield 'nominal with a test with a different mutator index' => [
- '/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
- MutatorName::getName(Plus::class),
- $nominalAttributes,
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- 99,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ],
- $nominalAttributes,
- $originalStartingLine,
- true,
- md5('/path/to/acme/Foo.php_Plus_99_3_5_21_31_43_53'),
- ];
+- echo 'original';
++ echo 'notCovered#0';
- yield 'nominal with a test and additional attributes' => [
- '/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
- MutatorName::getName(Plus::class),
- array_merge($nominalAttributes, ['foo' => 100, 'bar' => 1000]),
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- 0,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ],
- $nominalAttributes,
- $originalStartingLine,
+DIFF
+ ,
true,
- md5('/path/to/acme/Foo.php_Plus_0_3_5_21_31_43_53'),
];
yield 'nominal without a test' => [
'/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
MutatorName::getName(Plus::class),
- $nominalAttributes,
- Node\Scalar\LNumber::class,
- MutatedNode::wrap(new Node\Scalar\LNumber(1)),
- 0,
+ 3,
[],
- $nominalAttributes,
- $originalStartingLine,
- false,
- md5('/path/to/acme/Foo.php_Plus_0_3_5_21_31_43_53'),
- ];
+ '0800f',
+ '/path/to/mutation',
+ 'notCovered#0',
+ <<<'DIFF'
+--- Original
++++ New
+@@ @@
- yield 'nominal with a test and multiple mutated nodes' => [
- '/path/to/acme/Foo.php',
- [new Node\Stmt\Namespace_(
- new Node\Name('Acme'),
- [new Node\Scalar\LNumber(0)]
- )],
- MutatorName::getName(Plus::class),
- $nominalAttributes,
- Node\Scalar\LNumber::class,
- MutatedNode::wrap([
- new Node\Scalar\LNumber(1),
- new Node\Scalar\LNumber(-1),
- ]),
- 0,
- [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ],
- $nominalAttributes,
- $originalStartingLine,
- true,
- md5('/path/to/acme/Foo.php_Plus_0_3_5_21_31_43_53'),
+- echo 'original';
++ echo 'notCovered#0';
+
+DIFF
+ ,
+ false,
];
}
}
diff --git a/tests/phpunit/Mutator/BaseMutatorTestCase.php b/tests/phpunit/Mutator/BaseMutatorTestCase.php
index b6b2b561d..2fbbdd19c 100644
--- a/tests/phpunit/Mutator/BaseMutatorTestCase.php
+++ b/tests/phpunit/Mutator/BaseMutatorTestCase.php
@@ -80,19 +80,19 @@ final public function doTest(string $inputCode, $expectedCode = [], array $setti
$this->fail('Input code cant be the same as mutated code');
}
- $mutants = $this->mutate($inputCode, $settings);
+ $mutatedCodes = $this->mutate($inputCode, $settings);
$this->assertCount(
- count($mutants),
+ count($mutatedCodes),
$expectedCodeSamples,
sprintf(
- 'Failed asserting that the number of code samples (%d) equals the number of mutants (%d) created by the mutator.',
+ 'Failed asserting that the number of code samples (%d) equals the number of mutations (%d) created by the mutator.',
count($expectedCodeSamples),
- count($mutants)
+ count($mutatedCodes)
)
);
- foreach ($mutants as $realMutatedCode) {
+ foreach ($mutatedCodes as $realMutatedCode) {
/** @var string|null $expectedCodeSample */
$expectedCodeSample = array_shift($expectedCodeSamples);
@@ -133,21 +133,25 @@ final protected function mutate(string $code, array $settings = []): array
$traverser = new NodeTraverser();
$traverser->addVisitor(new CloneVisitor());
- $mutants = [];
+ $mutatedCodes = [];
foreach ($mutations as $mutation) {
- $mutatorVisitor = new MutatorVisitor($mutation);
+ $mutatorVisitor = new MutatorVisitor(
+ $mutation->getAttributes(),
+ $mutation->getMutatedNodeClass(),
+ $mutation->getMutatedNode()
+ );
$traverser->addVisitor($mutatorVisitor);
$mutatedStatements = $traverser->traverse($mutation->getOriginalFileAst());
- $mutants[] = SingletonContainer::getPrinter()->prettyPrintFile($mutatedStatements);
+ $mutatedCodes[] = SingletonContainer::getPrinter()->prettyPrintFile($mutatedStatements);
$traverser->removeVisitor($mutatorVisitor);
}
- return $mutants;
+ return $mutatedCodes;
}
/**
diff --git a/tests/phpunit/Mutator/MutatorParserTest.php b/tests/phpunit/Mutator/MutatorParserTest.php
index ef7175ff4..e4e96e6d7 100644
--- a/tests/phpunit/Mutator/MutatorParserTest.php
+++ b/tests/phpunit/Mutator/MutatorParserTest.php
@@ -37,6 +37,7 @@
use Infection\Mutator\MutatorParser;
use PHPUnit\Framework\TestCase;
+use UnexpectedValueException;
final class MutatorParserTest extends TestCase
{
@@ -64,6 +65,14 @@ public function test_it_can_parse_the_provided_input(
$this->assertSame($expectedMutators, $parsedMutators);
}
+ public function test_it_cannot_parse_unknown_mutator(): void
+ {
+ $this->expectException(UnexpectedValueException::class);
+ $this->expectExceptionMessage('Expected "Unknown" to be a known mutator or profile. See "https://infection.github.io/guide/mutators.html" and "https://infection.github.io/guide/profiles.html" for the list of available mutants and profiles.');
+
+ $this->mutatorParser->parse('Unknown');
+ }
+
public function mutatorInputProvider(): iterable
{
yield 'empty string' => ['', []];
diff --git a/tests/phpunit/PhpParser/Visitor/MutatorVisitorTest.php b/tests/phpunit/PhpParser/Visitor/MutatorVisitorTest.php
index 6f310c8ee..fe81f781e 100644
--- a/tests/phpunit/PhpParser/Visitor/MutatorVisitorTest.php
+++ b/tests/phpunit/PhpParser/Visitor/MutatorVisitorTest.php
@@ -35,7 +35,6 @@
namespace Infection\Tests\PhpParser\Visitor;
-use Infection\Mutation\Mutation;
use Infection\Mutator\FunctionSignature\PublicVisibility;
use Infection\PhpParser\MutatedNode;
use Infection\PhpParser\Visitor\MutatorVisitor;
@@ -57,15 +56,19 @@ final class MutatorVisitorTest extends BaseVisitorTest
* @dataProvider providesMutationCases
*
* @param Node[] $nodes
+ * @param array $attributes
+ * @param class-string $mutatedNodeClass
*/
public function test_it_mutates_the_correct_node(
array $nodes,
- string $expectedCodeOutput,
- Mutation $mutation
+ array $attributes,
+ string $mutatedNodeClass,
+ MutatedNode $mutatedNode,
+ string $expectedCodeOutput
): void {
$this->traverse(
$nodes,
- [new MutatorVisitor($mutation)]
+ [new MutatorVisitor($attributes, $mutatedNodeClass, $mutatedNode)]
);
$output = SingletonContainer::getPrinter()->prettyPrintFile($nodes);
@@ -77,7 +80,7 @@ public function providesMutationCases(): iterable
{
yield 'it mutates the correct node' => (function () {
return [
- $nodes = $this->parseCode(<<<'PHP'
+ $this->parseCode(<<<'PHP'
29,
+ 'endTokenPos' => 48,
+ 'startLine' => -1,
+ 'endLine' => -1,
+ 'startFilePos' => -1,
+ 'endFilePos' => -1,
+ ],
+ ClassMethod::class,
+ MutatedNode::wrap(new Nop()),
<<<'PHP'
29,
- 'endTokenPos' => 48,
- 'startLine' => -1,
- 'endLine' => -1,
- 'startFilePos' => -1,
- 'endFilePos' => -1,
- ],
- ClassMethod::class,
- MutatedNode::wrap(new Nop()),
- 0,
- []
- ),
];
})();
yield 'it can mutate the node with multiple-ones' => (function () {
return [
- $nodes = $this->parseCode(<<<'PHP'
+ $this->parseCode(<<<'PHP'
29,
+ 'endTokenPos' => 48,
+ 'startLine' => -1,
+ 'endLine' => -1,
+ 'startFilePos' => -1,
+ 'endFilePos' => -1,
+ ],
+ ClassMethod::class,
+ MutatedNode::wrap([new Nop(), new Nop()]),
<<<'PHP'
29,
- 'endTokenPos' => 48,
- 'startLine' => -1,
- 'endLine' => -1,
- 'startFilePos' => -1,
- 'endFilePos' => -1,
- ],
- ClassMethod::class,
- MutatedNode::wrap([new Nop(), new Nop()]),
- 0,
- []
- ),
];
})();
yield 'it does not mutate if only one of start or end position is correctly set' => (function () {
return [
- $nodes = $this->parseCode(<<<'PHP'
+ $this->parseCode(<<<'PHP'
29,
+ 'endTokenPos' => 50,
+ 'startLine' => -1,
+ 'endLine' => -1,
+ 'startFilePos' => -1,
+ 'endFilePos' => -1,
+ ],
+ ClassMethod::class,
+ MutatedNode::wrap(new Nop()),
<<<'PHP'
29,
- 'endTokenPos' => 50,
- 'startLine' => -1,
- 'endLine' => -1,
- 'startFilePos' => -1,
- 'endFilePos' => -1,
- ],
- ClassMethod::class,
- MutatedNode::wrap(new Nop()),
- 0,
- []
- ),
];
})();
@@ -248,7 +230,7 @@ public function bye() : string
$badParser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7, $badLexer);
return [
- $nodes = $badParser->parse(<<<'PHP'
+ $badParser->parse(<<<'PHP'
29,
+ 'endTokenPos' => 48,
+ 'startLine' => -1,
+ 'endLine' => -1,
+ 'startFilePos' => -1,
+ 'endFilePos' => -1,
+ ],
+ MutatorName::getName(PublicVisibility::class),
+ MutatedNode::wrap(new Nop()),
<<<'PHP'
29,
- 'endTokenPos' => 48,
- 'startLine' => -1,
- 'endLine' => -1,
- 'startFilePos' => -1,
- 'endFilePos' => -1,
- ],
- MutatorName::getName(PublicVisibility::class),
- MutatedNode::wrap(new Nop()),
- 0,
- []
- ),
];
})();
}
diff --git a/tests/phpunit/Process/Factory/MutantProcessFactoryTest.php b/tests/phpunit/Process/Factory/MutantProcessFactoryTest.php
index 22a386cfa..0126fd73d 100644
--- a/tests/phpunit/Process/Factory/MutantProcessFactoryTest.php
+++ b/tests/phpunit/Process/Factory/MutantProcessFactoryTest.php
@@ -39,50 +39,38 @@
use Infection\AbstractTestFramework\Coverage\TestLocation;
use Infection\AbstractTestFramework\TestFrameworkAdapter;
use Infection\Event\MutantProcessWasFinished;
-use Infection\Mutant\Mutant;
use Infection\Mutant\MutantExecutionResult;
use Infection\Mutant\MutantExecutionResultFactory;
use Infection\Mutation\Mutation;
use Infection\Mutator\ZeroIteration\For_;
-use Infection\PhpParser\MutatedNode;
use Infection\Process\Factory\MutantProcessFactory;
use Infection\Tests\Fixtures\Event\EventDispatcherCollector;
use Infection\Tests\Mutator\MutatorName;
use const PHP_OS_FAMILY;
-use PhpParser\Node\Stmt\Nop;
use PHPUnit\Framework\TestCase;
final class MutantProcessFactoryTest extends TestCase
{
public function test_it_creates_a_process_with_timeout(): void
{
- $mutant = new Mutant(
- $mutantFilePath = '/path/to/mutant',
- new Mutation(
- $originalFilePath = 'path/to/Foo.php',
- [],
- MutatorName::getName(For_::class),
- [
- 'startLine' => $originalStartingLine = 10,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
- $tests = [
- new TestLocation(
- 'FooTest::test_it_can_instantiate',
- '/path/to/acme/FooTest.php',
- 0.01
- ),
- ]
- ),
- 'killed#0',
- $mutantDiff = <<<'DIFF'
+ $hash = '0800f';
+ $mutationFilePath = '/path/to/mutation';
+
+ $mutation = new Mutation(
+ $originalFilePath = 'path/to/Foo.php',
+ MutatorName::getName(For_::class),
+ 10,
+ $tests = [
+ new TestLocation(
+ 'FooTest::test_it_can_instantiate',
+ '/path/to/acme/FooTest.php',
+ 0.01
+ ),
+ ],
+ $hash,
+ $mutationFilePath,
+ 'notCovered#0',
+ <<<'DIFF'
--- Original
+++ New
@@ @@
@@ -100,8 +88,8 @@ public function test_it_creates_a_process_with_timeout(): void
->method('getMutantCommandLine')
->with(
$tests,
- $mutantFilePath,
- $this->isType('string'),
+ $mutationFilePath,
+ $hash,
$originalFilePath,
$testFrameworkExtraOptions
)
@@ -129,7 +117,7 @@ public function test_it_creates_a_process_with_timeout(): void
$resultFactoryMock
);
- $mutantProcess = $factory->createProcessForMutant($mutant, $testFrameworkExtraOptions);
+ $mutantProcess = $factory->createProcessForMutation($mutation, $testFrameworkExtraOptions);
$process = $mutantProcess->getProcess();
@@ -142,7 +130,7 @@ public function test_it_creates_a_process_with_timeout(): void
$this->assertSame(100., $process->getTimeout());
$this->assertFalse($process->isStarted());
- $this->assertSame($mutant, $mutantProcess->getMutant());
+ $this->assertSame($mutation, $mutantProcess->getMutation());
$this->assertFalse($mutantProcess->isTimedOut());
$this->assertSame([], $eventDispatcher->getEvents());
diff --git a/tests/phpunit/Process/MutantProcessTest.php b/tests/phpunit/Process/MutantProcessTest.php
index 454138ac8..8f7460a26 100644
--- a/tests/phpunit/Process/MutantProcessTest.php
+++ b/tests/phpunit/Process/MutantProcessTest.php
@@ -35,7 +35,7 @@
namespace Infection\Tests\Process;
-use Infection\Mutant\Mutant;
+use Infection\Mutation\Mutation;
use Infection\Process\MutantProcess;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -49,41 +49,41 @@ final class MutantProcessTest extends TestCase
private $processMock;
/**
- * @var MockObject|Mutant
+ * @var MockObject|Mutation
*/
- private $mutantMock;
+ private $mutationMock;
/**
* @var MutantProcess
*/
- private $mutantProcess;
+ private $mutationProcess;
protected function setUp(): void
{
$this->processMock = $this->createMock(Process::class);
- $this->mutantMock = $this->createMock(Mutant::class);
+ $this->mutationMock = $this->createMock(Mutation::class);
- $this->mutantProcess = new MutantProcess($this->processMock, $this->mutantMock);
+ $this->mutationProcess = new MutantProcess($this->processMock, $this->mutationMock);
}
public function test_it_exposes_its_state(): void
{
- $this->assertMutantProcessStateIs(
- $this->mutantProcess,
+ $this->assertMutationProcessStateIs(
+ $this->mutationProcess,
$this->processMock,
- $this->mutantMock,
+ $this->mutationMock,
false
);
}
public function test_it_can_be_marked_as_timed_out(): void
{
- $this->mutantProcess->markAsTimedOut();
+ $this->mutationProcess->markAsTimedOut();
- $this->assertMutantProcessStateIs(
- $this->mutantProcess,
+ $this->assertMutationProcessStateIs(
+ $this->mutationProcess,
$this->processMock,
- $this->mutantMock,
+ $this->mutationMock,
true
);
}
@@ -92,7 +92,7 @@ public function test_it_can_have_a_callback_registered_and_executed(): void
{
$called = false;
- $this->mutantProcess->registerTerminateProcessClosure(
+ $this->mutationProcess->registerTerminateProcessClosure(
static function () use (&$called): void {
$called = true;
}
@@ -100,19 +100,19 @@ static function () use (&$called): void {
$this->assertFalse($called);
- $this->mutantProcess->terminateProcess();
+ $this->mutationProcess->terminateProcess();
$this->assertTrue($called);
}
- private function assertMutantProcessStateIs(
- MutantProcess $mutantProcess,
+ private function assertMutationProcessStateIs(
+ MutantProcess $mutationProcess,
Process $expectedProcess,
- Mutant $expectedMutant,
+ Mutation $expectedMutation,
bool $expectedTimedOut
): void {
- $this->assertSame($expectedProcess, $mutantProcess->getProcess());
- $this->assertSame($expectedMutant, $mutantProcess->getMutant());
- $this->assertSame($expectedTimedOut, $mutantProcess->isTimedOut());
+ $this->assertSame($expectedProcess, $mutationProcess->getProcess());
+ $this->assertSame($expectedMutation, $mutationProcess->getMutation());
+ $this->assertSame($expectedTimedOut, $mutationProcess->isTimedOut());
}
}
diff --git a/tests/phpunit/Process/Runner/MutationTestingRunnerTest.php b/tests/phpunit/Process/Runner/MutationTestingRunnerTest.php
index 6713969e1..93b0a1677 100644
--- a/tests/phpunit/Process/Runner/MutationTestingRunnerTest.php
+++ b/tests/phpunit/Process/Runner/MutationTestingRunnerTest.php
@@ -43,11 +43,8 @@
use Infection\AbstractTestFramework\Coverage\TestLocation;
use Infection\Event\MutationTestingWasFinished;
use Infection\Event\MutationTestingWasStarted;
-use Infection\Mutant\Mutant;
-use Infection\Mutant\MutantFactory;
use Infection\Mutation\Mutation;
use Infection\Mutator\ZeroIteration\For_;
-use Infection\PhpParser\MutatedNode;
use Infection\Process\Factory\MutantProcessFactory;
use Infection\Process\MutantProcess;
use Infection\Process\Runner\MutationTestingRunner;
@@ -55,12 +52,12 @@
use Infection\Tests\Fixtures\Event\EventDispatcherCollector;
use Infection\Tests\Mutator\MutatorName;
use Iterator;
-use PhpParser\Node\Stmt\Nop;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use function Safe\sprintf;
use Symfony\Component\Filesystem\Filesystem;
+use Symfony\Component\Process\Process;
/**
* @group integration
@@ -72,11 +69,6 @@ final class MutationTestingRunnerTest extends TestCase
*/
private $processFactoryMock;
- /**
- * @var MutantFactory|MockObject
- */
- private $mutantFactoryMock;
-
/**
* @var ProcessRunner|MockObject
*/
@@ -100,14 +92,12 @@ final class MutationTestingRunnerTest extends TestCase
protected function setUp(): void
{
$this->processFactoryMock = $this->createMock(MutantProcessFactory::class);
- $this->mutantFactoryMock = $this->createMock(MutantFactory::class);
$this->processRunnerMock = $this->createMock(ProcessRunner::class);
$this->eventDispatcher = new EventDispatcherCollector();
$this->fileSystemMock = $this->createMock(Filesystem::class);
$this->runner = new MutationTestingRunner(
$this->processFactoryMock,
- $this->mutantFactoryMock,
$this->processRunnerMock,
$this->eventDispatcher,
$this->fileSystemMock,
@@ -145,46 +135,24 @@ public function test_it_applies_and_run_the_mutations(): void
];
$testFrameworkExtraOptions = '--filter=acme/FooTest.php';
- $this->mutantFactoryMock
- ->method('create')
- ->withConsecutive(
- [$mutation0],
- [$mutation1]
- )
- ->willReturnOnConsecutiveCalls(
- $mutant0 = new Mutant(
- '/path/to/mutant0',
- $mutation0,
- 'mutated code 0',
- 'diff0'
- ),
- $mutant1 = new Mutant(
- '/path/to/mutant1',
- $mutation1,
- 'mutated code 1',
- 'diff1'
- )
- )
- ;
-
$this->fileSystemMock
->expects($this->exactly(2))
->method('dumpFile')
->withConsecutive(
- ['/path/to/mutant0', 'mutated code 0'],
- ['/path/to/mutant1', 'mutated code 1']
+ ['/path/to/mutation0.php', 'mutated code 0'],
+ ['/path/to/mutation1.php', 'mutated code 1']
)
;
$this->processFactoryMock
- ->method('createProcessForMutant')
+ ->method('createProcessForMutation')
->withConsecutive(
- [$mutant0, $testFrameworkExtraOptions],
- [$mutant1, $testFrameworkExtraOptions]
+ [$mutation0, $testFrameworkExtraOptions],
+ [$mutation1, $testFrameworkExtraOptions]
)
->willReturnOnConsecutiveCalls(
- $process0 = $this->buildCoveredMutantProcess(),
- $process1 = $this->buildCoveredMutantProcess()
+ $process0 = $this->buildCoveredMutantProcess($mutation0),
+ $process1 = $this->buildCoveredMutantProcess($mutation1)
)
;
@@ -214,58 +182,35 @@ public function test_it_applies_and_run_the_mutations_when_concurrent_execution_
$testFrameworkExtraOptions = '--filter=acme/FooTest.php';
- $this->mutantFactoryMock
- ->method('create')
- ->withConsecutive(
- [$mutation0],
- [$mutation1]
- )
- ->willReturnOnConsecutiveCalls(
- $mutant0 = new Mutant(
- '/path/to/mutant0',
- $mutation0,
- 'mutated code 0',
- 'diff0'
- ),
- $mutant1 = new Mutant(
- '/path/to/mutant1',
- $mutation1,
- 'mutated code 1',
- 'diff1'
- )
- )
- ;
-
$this->fileSystemMock
->expects($this->exactly(2))
->method('dumpFile')
->withConsecutive(
- ['/path/to/mutant0', 'mutated code 0'],
- ['/path/to/mutant1', 'mutated code 1']
+ ['/path/to/mutation0.php', 'mutated code 0'],
+ ['/path/to/mutation1.php', 'mutated code 1']
)
;
$this->processFactoryMock
- ->method('createProcessForMutant')
+ ->method('createProcessForMutation')
->withConsecutive(
- [$mutant0, $testFrameworkExtraOptions],
- [$mutant1, $testFrameworkExtraOptions]
+ [$mutation0, $testFrameworkExtraOptions],
+ [$mutation1, $testFrameworkExtraOptions]
)
->willReturnOnConsecutiveCalls(
- $process0 = $this->buildCoveredMutantProcess(),
- $process1 = $this->buildCoveredMutantProcess()
+ $process0 = $this->buildCoveredMutantProcess($mutation0),
+ $process1 = $this->buildCoveredMutantProcess($mutation1)
)
;
$this->processRunnerMock
->expects($this->once())
->method('run')
- ->with($this->iterableContaining([$process0, $process1]), )
+ ->with($this->iterableContaining([$process0, $process1]))
;
$this->runner = new MutationTestingRunner(
$this->processFactoryMock,
- $this->mutantFactoryMock,
$this->processRunnerMock,
$this->eventDispatcher,
$this->fileSystemMock,
@@ -291,11 +236,6 @@ public function test_it_passes_through_iterables_when_concurrent_execution_reque
->method($this->anything())
;
- $this->mutantFactoryMock
- ->expects($this->never())
- ->method($this->anything())
- ;
-
$this->processFactoryMock
->expects($this->never())
->method($this->anything())
@@ -309,7 +249,6 @@ public function test_it_passes_through_iterables_when_concurrent_execution_reque
$this->runner = new MutationTestingRunner(
$this->processFactoryMock,
- $this->mutantFactoryMock,
$this->processRunnerMock,
$this->eventDispatcher,
$this->fileSystemMock,
@@ -329,11 +268,6 @@ public function test_it_dispatches_events_even_when_no_mutations_is_given(): voi
->method($this->anything())
;
- $this->mutantFactoryMock
- ->expects($this->never())
- ->method($this->anything())
- ;
-
$this->processRunnerMock
->expects($this->once())
->method('run')
@@ -429,15 +363,15 @@ private function formatExpectedEvents(array $events): string
);
}
- private function buildCoveredMutantProcess(): MutantProcess
+ private function buildCoveredMutantProcess(Mutation $mutation): MutantProcess
{
- $mutantProcess = $this->createMock(MutantProcess::class);
- $mutantProcess
+ $processMock = $this->createMock(Process::class);
+ $processMock
->expects($this->never())
- ->method('getMutant')
+ ->method($this->anything())
;
- return $mutantProcess;
+ return new MutantProcess($processMock, $mutation);
}
private function someIterable(?callable $callback = null): Callback
@@ -479,26 +413,19 @@ private function createMutation(int $i): Mutation
{
return new Mutation(
'path/to/Foo' . $i . '.php',
- [],
MutatorName::getName(For_::class),
- [
- 'startLine' => $i,
- 'endLine' => 15,
- 'startTokenPos' => 0,
- 'endTokenPos' => 8,
- 'startFilePos' => 2,
- 'endFilePos' => 4,
- ],
- 'Unknown',
- MutatedNode::wrap(new Nop()),
- 0,
+ 10,
[
new TestLocation(
'FooTest::test_it_can_instantiate',
'/path/to/acme/FooTest.php',
0.01
),
- ]
+ ],
+ 'mutationHash#' . $i,
+ '/path/to/mutation' . $i . '.php',
+ 'mutated code ' . $i,
+ 'diff'
);
}
}
diff --git a/tests/phpunit/TestFramework/TestFrameworkExtraOptionsFilterTest.php b/tests/phpunit/TestFramework/TestFrameworkExtraOptionsFilterTest.php
index deb4e8822..480735b43 100644
--- a/tests/phpunit/TestFramework/TestFrameworkExtraOptionsFilterTest.php
+++ b/tests/phpunit/TestFramework/TestFrameworkExtraOptionsFilterTest.php
@@ -45,9 +45,10 @@ final class TestFrameworkExtraOptionsFilterTest extends TestCase
*/
public function test_it_skips_filter_for_mutant_process(string $actualExtraOptions, string $expectedExtraOptions): void
{
- $filter = new TestFrameworkExtraOptionsFilter();
-
- $filteredOptions = $filter->filterForMutantProcess($actualExtraOptions, ['--configuration', '--filter', '--testsuite']);
+ $filteredOptions = (new TestFrameworkExtraOptionsFilter())->filterForMutantProcess(
+ $actualExtraOptions,
+ ['--configuration', '--filter', '--testsuite']
+ );
$this->assertSame($expectedExtraOptions, $filteredOptions);
}