From 97677c8b1ad49e55c05e1bb9eb6a736c498a1da2 Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Sat, 3 Jul 2021 17:08:12 +0300 Subject: [PATCH 1/8] Run only those test cases that cover mutated line Previously, we ran **files** that contains tests that cover mutated line. In `phpunit.xml` this is all we can do. To run **test cases** that cover mutated line from that files, we can only use `--filter` options. This is what this change does --- .../AbstractTestFrameworkAdapter.php | 11 ++++++---- .../CommandLineArgumentsAndOptionsBuilder.php | 6 +++++- .../ArgumentsAndOptionsBuilder.php | 20 ++++++++++++++++++- .../ArgumentsAndOptionsBuilderTest.php | 16 ++++++++++++--- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/TestFramework/AbstractTestFrameworkAdapter.php b/src/TestFramework/AbstractTestFrameworkAdapter.php index 9f8fa0336..bea7cb635 100644 --- a/src/TestFramework/AbstractTestFrameworkAdapter.php +++ b/src/TestFramework/AbstractTestFrameworkAdapter.php @@ -91,7 +91,7 @@ public function getInitialTestRunCommandLine( array $phpExtraArgs, bool $skipCoverage ): array { - return $this->getCommandLine($this->buildInitialConfigFile(), $extraOptions, $phpExtraArgs); + return $this->getCommandLine($this->buildInitialConfigFile(), $extraOptions, $phpExtraArgs, []); } /** @@ -116,7 +116,8 @@ public function getMutantCommandLine( $mutationOriginalFilePath ), $extraOptions, - [] + [], + $tests, ); } @@ -154,15 +155,17 @@ protected function buildMutationConfigFile( /** * @param string[] $phpExtraArgs + * @param TestLocation[] $tests * * @return string[] */ private function getCommandLine( string $configPath, string $extraOptions, - array $phpExtraArgs + array $phpExtraArgs, + array $tests ): array { - $frameworkArgs = $this->argumentsAndOptionsBuilder->build($configPath, $extraOptions); + $frameworkArgs = $this->argumentsAndOptionsBuilder->build($configPath, $extraOptions, $tests); return $this->commandLineBuilder->build( $this->testFrameworkExecutable, diff --git a/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php b/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php index d18ad2c93..bb0372fcd 100644 --- a/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php @@ -35,13 +35,17 @@ namespace Infection\TestFramework; +use Infection\AbstractTestFramework\Coverage\TestLocation; + /** * @internal */ interface CommandLineArgumentsAndOptionsBuilder { /** + * @param TestLocation[] $tests + * * @return string[] */ - public function build(string $configPath, string $extraOptions): array; + public function build(string $configPath, string $extraOptions, array $tests): array; } diff --git a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php index c95c734aa..9659354fc 100644 --- a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php @@ -37,7 +37,12 @@ use function array_map; use function array_merge; +use function array_unique; +use function count; +use function escapeshellcmd; use function explode; +use function implode; +use Infection\AbstractTestFramework\Coverage\TestLocation; use Infection\TestFramework\CommandLineArgumentsAndOptionsBuilder; use function ltrim; @@ -46,7 +51,8 @@ */ final class ArgumentsAndOptionsBuilder implements CommandLineArgumentsAndOptionsBuilder { - public function build(string $configPath, string $extraOptions): array + // todo build & buildForMutant + public function build(string $configPath, string $extraOptions, array $tests): array { $options = [ '--configuration', @@ -62,6 +68,18 @@ public function build(string $configPath, string $extraOptions): array ); } +// preg_replace('/\swith data set (.*)/', '', $test->getMethod()) + + if (count($tests) > 0) { + $escapedTests = array_map( + static fn (TestLocation $testLocation): string => escapeshellcmd($testLocation->getMethod()), + $tests + ); + + $options[] = '--filter'; + $options[] = implode('|', array_unique($escapedTests)); + } + return $options; } } diff --git a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php index 45055b14d..a7440c9a4 100644 --- a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php +++ b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php @@ -35,6 +35,7 @@ namespace Infection\Tests\TestFramework\PhpUnit\CommandLine; +use Infection\AbstractTestFramework\Coverage\TestLocation; use Infection\TestFramework\PhpUnit\CommandLine\ArgumentsAndOptionsBuilder; use PHPUnit\Framework\TestCase; @@ -59,7 +60,7 @@ public function test_it_can_build_the_command_without_extra_options(): void '--configuration', $configPath, ], - $this->builder->build($configPath, '') + $this->builder->build($configPath, '', []) ); } @@ -74,7 +75,7 @@ public function test_it_can_build_the_command_with_extra_options(): void '--verbose', '--debug', ], - $this->builder->build($configPath, '--verbose --debug') + $this->builder->build($configPath, '--verbose --debug', []) ); } @@ -87,8 +88,17 @@ public function test_it_can_build_the_command_with_extra_options_that_contains_s '--configuration', $configPath, '--path=/a path/with spaces', + '--filter', + 'App\\\\Test::test_case1|App\\\\Test::test_case2', ], - $this->builder->build($configPath, '--path=/a path/with spaces') + $this->builder->build( + $configPath, + '--path=/a path/with spaces', + [ + TestLocation::forTestMethod('App\Test::test_case1'), + TestLocation::forTestMethod('App\Test::test_case2'), + ] + ) ); } } From e0cc2b11a860ee2852e67f2ab82ee348e15e9181 Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Sat, 3 Jul 2021 17:31:36 +0300 Subject: [PATCH 2/8] Split `ArgumentsAndOptionsBuilder::build` into 2 methods: for initial tests run and for mutant --- .../AbstractTestFrameworkAdapter.php | 33 ++++++++++--------- .../CommandLineArgumentsAndOptionsBuilder.php | 7 +++- .../ArgumentsAndOptionsBuilder.php | 10 ++++-- .../PhpUnit/Adapter/PestAdapterTest.php | 6 ++-- .../PhpUnit/Adapter/PhpUnitAdapterTest.php | 6 ++-- .../ArgumentsAndOptionsBuilderTest.php | 20 +++++++++-- 6 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/TestFramework/AbstractTestFrameworkAdapter.php b/src/TestFramework/AbstractTestFrameworkAdapter.php index bea7cb635..dc9e19284 100644 --- a/src/TestFramework/AbstractTestFrameworkAdapter.php +++ b/src/TestFramework/AbstractTestFrameworkAdapter.php @@ -91,7 +91,10 @@ public function getInitialTestRunCommandLine( array $phpExtraArgs, bool $skipCoverage ): array { - return $this->getCommandLine($this->buildInitialConfigFile(), $extraOptions, $phpExtraArgs, []); + return $this->getCommandLine( + $phpExtraArgs, + $this->argumentsAndOptionsBuilder->buildForInitialTestsRun($this->buildInitialConfigFile(), $extraOptions) + ); } /** @@ -109,15 +112,17 @@ public function getMutantCommandLine( string $extraOptions ): array { return $this->getCommandLine( - $this->buildMutationConfigFile( - $tests, - $mutantFilePath, - $mutationHash, - $mutationOriginalFilePath - ), - $extraOptions, [], - $tests, + $this->argumentsAndOptionsBuilder->buildForMutant( + $this->buildMutationConfigFile( + $tests, + $mutantFilePath, + $mutationHash, + $mutationOriginalFilePath + ), + $extraOptions, + $tests + ) ); } @@ -155,22 +160,18 @@ protected function buildMutationConfigFile( /** * @param string[] $phpExtraArgs - * @param TestLocation[] $tests + * @param string[] $testFrameworkArgs * * @return string[] */ private function getCommandLine( - string $configPath, - string $extraOptions, array $phpExtraArgs, - array $tests + array $testFrameworkArgs ): array { - $frameworkArgs = $this->argumentsAndOptionsBuilder->build($configPath, $extraOptions, $tests); - return $this->commandLineBuilder->build( $this->testFrameworkExecutable, $phpExtraArgs, - $frameworkArgs + $testFrameworkArgs ); } diff --git a/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php b/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php index bb0372fcd..817c5b40f 100644 --- a/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/CommandLineArgumentsAndOptionsBuilder.php @@ -42,10 +42,15 @@ */ interface CommandLineArgumentsAndOptionsBuilder { + /** + * @return string[] + */ + public function buildForInitialTestsRun(string $configPath, string $extraOptions): array; + /** * @param TestLocation[] $tests * * @return string[] */ - public function build(string $configPath, string $extraOptions, array $tests): array; + public function buildForMutant(string $configPath, string $extraOptions, array $tests): array; } diff --git a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php index 9659354fc..dbe8c778a 100644 --- a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php @@ -51,8 +51,7 @@ */ final class ArgumentsAndOptionsBuilder implements CommandLineArgumentsAndOptionsBuilder { - // todo build & buildForMutant - public function build(string $configPath, string $extraOptions, array $tests): array + public function buildForInitialTestsRun(string $configPath, string $extraOptions): array { $options = [ '--configuration', @@ -68,6 +67,13 @@ public function build(string $configPath, string $extraOptions, array $tests): a ); } + return $options; + } + + public function buildForMutant(string $configPath, string $extraOptions, array $tests): array + { + $options = $this->buildForInitialTestsRun($configPath, $extraOptions); + // preg_replace('/\swith data set (.*)/', '', $test->getMethod()) if (count($tests) > 0) { diff --git a/tests/phpunit/TestFramework/PhpUnit/Adapter/PestAdapterTest.php b/tests/phpunit/TestFramework/PhpUnit/Adapter/PestAdapterTest.php index b46876f9a..bc5c85802 100644 --- a/tests/phpunit/TestFramework/PhpUnit/Adapter/PestAdapterTest.php +++ b/tests/phpunit/TestFramework/PhpUnit/Adapter/PestAdapterTest.php @@ -129,7 +129,7 @@ public function test_it_provides_initial_test_run_command_line_when_no_coverage_ { $this->cliArgumentsBuilder ->expects($this->once()) - ->method('build') + ->method('buildForInitialTestsRun') ->with('', '--group=default') ; @@ -163,7 +163,7 @@ public function test_it_provides_initial_test_run_command_line_when_coverage_rep { $this->cliArgumentsBuilder ->expects($this->once()) - ->method('build') + ->method('buildForInitialTestsRun') ->with('', '--group=default --coverage-xml=/tmp/coverage-xml --log-junit=/tmp/infection/junit.xml') ->willReturn([ '--group=default', '--coverage-xml=/tmp/coverage-xml', '--log-junit=/tmp/infection/junit.xml', @@ -215,7 +215,7 @@ public function test_it_provides_initial_test_run_command_line_when_coverage_rep { $this->cliArgumentsBuilder ->expects($this->once()) - ->method('build') + ->method('buildForInitialTestsRun') ->with('', '--group=default --coverage-xml=/tmp/coverage-xml --log-junit=/tmp/infection/junit.xml') ->willReturn([ '--group=default', '--coverage-xml=/tmp/coverage-xml', '--log-junit=/tmp/infection/junit.xml', diff --git a/tests/phpunit/TestFramework/PhpUnit/Adapter/PhpUnitAdapterTest.php b/tests/phpunit/TestFramework/PhpUnit/Adapter/PhpUnitAdapterTest.php index 212fdc7ba..6410d8b5a 100644 --- a/tests/phpunit/TestFramework/PhpUnit/Adapter/PhpUnitAdapterTest.php +++ b/tests/phpunit/TestFramework/PhpUnit/Adapter/PhpUnitAdapterTest.php @@ -129,7 +129,7 @@ public function test_it_provides_initial_test_run_command_line_when_no_coverage_ { $this->cliArgumentsBuilder ->expects($this->once()) - ->method('build') + ->method('buildForInitialTestsRun') ->with('', '--group=default') ; @@ -163,7 +163,7 @@ public function test_it_provides_initial_test_run_command_line_when_coverage_rep { $this->cliArgumentsBuilder ->expects($this->once()) - ->method('build') + ->method('buildForInitialTestsRun') ->with('', '--group=default --coverage-xml=/tmp/coverage-xml --log-junit=/tmp/infection/junit.xml') ->willReturn([ '--group=default', '--coverage-xml=/tmp/coverage-xml', '--log-junit=/tmp/infection/junit.xml', @@ -215,7 +215,7 @@ public function test_it_provides_initial_test_run_command_line_when_coverage_rep { $this->cliArgumentsBuilder ->expects($this->once()) - ->method('build') + ->method('buildForInitialTestsRun') ->with('', '--group=default --coverage-xml=/tmp/coverage-xml --log-junit=/tmp/infection/junit.xml') ->willReturn([ '--group=default', '--coverage-xml=/tmp/coverage-xml', '--log-junit=/tmp/infection/junit.xml', diff --git a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php index a7440c9a4..cfa4b48e9 100644 --- a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php +++ b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php @@ -60,7 +60,7 @@ public function test_it_can_build_the_command_without_extra_options(): void '--configuration', $configPath, ], - $this->builder->build($configPath, '', []) + $this->builder->buildForInitialTestsRun($configPath, '') ); } @@ -75,7 +75,7 @@ public function test_it_can_build_the_command_with_extra_options(): void '--verbose', '--debug', ], - $this->builder->build($configPath, '--verbose --debug', []) + $this->builder->buildForInitialTestsRun($configPath, '--verbose --debug') ); } @@ -83,6 +83,20 @@ public function test_it_can_build_the_command_with_extra_options_that_contains_s { $configPath = '/the config/path'; + $this->assertSame( + [ + '--configuration', + $configPath, + '--path=/a path/with spaces', + ], + $this->builder->buildForInitialTestsRun($configPath, '--path=/a path/with spaces') + ); + } + + public function test_it_can_build_the_command_with_filter_option_for_covering_tests_for_mutant(): void + { + $configPath = '/the config/path'; + $this->assertSame( [ '--configuration', @@ -91,7 +105,7 @@ public function test_it_can_build_the_command_with_extra_options_that_contains_s '--filter', 'App\\\\Test::test_case1|App\\\\Test::test_case2', ], - $this->builder->build( + $this->builder->buildForMutant( $configPath, '--path=/a path/with spaces', [ From 7ae27ac699894d47137651c47fc6e55c680973a3 Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Mon, 5 Jul 2021 23:20:13 +0300 Subject: [PATCH 3/8] Add more tests, remove redundant `.*` from regular expression --- .../ArgumentsAndOptionsBuilder.php | 5 +- .../ArgumentsAndOptionsBuilderTest.php | 51 ++++++++++++++++--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php index dbe8c778a..db4054db7 100644 --- a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php @@ -45,6 +45,7 @@ use Infection\AbstractTestFramework\Coverage\TestLocation; use Infection\TestFramework\CommandLineArgumentsAndOptionsBuilder; use function ltrim; +use function Safe\sprintf; /** * @internal @@ -74,8 +75,6 @@ public function buildForMutant(string $configPath, string $extraOptions, array $ { $options = $this->buildForInitialTestsRun($configPath, $extraOptions); -// preg_replace('/\swith data set (.*)/', '', $test->getMethod()) - if (count($tests) > 0) { $escapedTests = array_map( static fn (TestLocation $testLocation): string => escapeshellcmd($testLocation->getMethod()), @@ -83,7 +82,7 @@ public function buildForMutant(string $configPath, string $extraOptions, array $ ); $options[] = '--filter'; - $options[] = implode('|', array_unique($escapedTests)); + $options[] = sprintf('/%s/', implode('|', array_unique($escapedTests))); } return $options; diff --git a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php index cfa4b48e9..8bfe9c213 100644 --- a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php +++ b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php @@ -35,6 +35,8 @@ namespace Infection\Tests\TestFramework\PhpUnit\CommandLine; +use function array_map; +use Generator; use Infection\AbstractTestFramework\Coverage\TestLocation; use Infection\TestFramework\PhpUnit\CommandLine\ArgumentsAndOptionsBuilder; use PHPUnit\Framework\TestCase; @@ -93,7 +95,10 @@ public function test_it_can_build_the_command_with_extra_options_that_contains_s ); } - public function test_it_can_build_the_command_with_filter_option_for_covering_tests_for_mutant(): void + /** + * @dataProvider provideTestCases + */ + public function test_it_can_build_the_command_with_filter_option_for_covering_tests_for_mutant(array $testCases, string $expectedFilterOptionValue): void { $configPath = '/the config/path'; @@ -103,16 +108,50 @@ public function test_it_can_build_the_command_with_filter_option_for_covering_te $configPath, '--path=/a path/with spaces', '--filter', - 'App\\\\Test::test_case1|App\\\\Test::test_case2', + $expectedFilterOptionValue, ], $this->builder->buildForMutant( $configPath, '--path=/a path/with spaces', - [ - TestLocation::forTestMethod('App\Test::test_case1'), - TestLocation::forTestMethod('App\Test::test_case2'), - ] + array_map( + static fn (string $testCase): TestLocation => TestLocation::forTestMethod($testCase), + $testCases + ) ) ); } + + public function provideTestCases(): Generator + { + yield '1 test case' => [ + [ + 'App\Test::test_case1', + ], + '/App\\\\Test::test_case1/', + ]; + + yield '2 test cases' => [ + [ + 'App\Test::test_case1', + 'App\Test::test_case2', + ], + '/App\\\\Test::test_case1|App\\\\Test::test_case2/', + ]; + + yield '2 simple test cases, 1 with data set and special character >' => [ + [ + 'App\Test::test_case1 with data set "With special character >"', + 'App\Test::test_case2', + ], + '/App\\\\Test::test_case1 with data set "With special character \\>"|App\\\\Test::test_case2/', + ]; + + yield '2 simple test cases, 1 with data set and special character @' => [ + [ + 'App\Test::test_case1 with data set "With special character @"', + 'App\Test::test_case2', + ], + '/App\\\\Test::test_case1 with data set "With special character @"|App\\\\Test::test_case2/', + ]; + } } From a47acffb4f4ff11c6e16cef96dbe19eaedf5f08c Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Mon, 5 Jul 2021 23:25:51 +0300 Subject: [PATCH 4/8] Add special char for Pest e2e test to make sure it works as expected --- .../e2e/PestTestFramework/tests/ForPestWithDataProviderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/PestTestFramework/tests/ForPestWithDataProviderTest.php b/tests/e2e/PestTestFramework/tests/ForPestWithDataProviderTest.php index 4dfd85156..123e187ad 100644 --- a/tests/e2e/PestTestFramework/tests/ForPestWithDataProviderTest.php +++ b/tests/e2e/PestTestFramework/tests/ForPestWithDataProviderTest.php @@ -10,7 +10,7 @@ [2.0, 4.0, 0.5] ]); -test('tests division with shared dataset', function (float $a, float $b, float $expectedResult) { +test('tests division with shared dataset, with special | char', function (float $a, float $b, float $expectedResult) { $sourceClass = new ForPestWithDataProvider(); expect($sourceClass->div($a, $b))->toBe($expectedResult); From bd4316c33ece72b34243cd54f2aba621ff91fe18 Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Tue, 20 Jul 2021 00:23:55 +0300 Subject: [PATCH 5/8] Use more performant way of building `--filter` option, not escaping non-unique test cases and using `foreach` --- .../ArgumentsAndOptionsBuilder.php | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php index db4054db7..77e2a4717 100644 --- a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php @@ -35,17 +35,16 @@ namespace Infection\TestFramework\PhpUnit\CommandLine; +use function array_key_exists; use function array_map; use function array_merge; -use function array_unique; use function count; use function escapeshellcmd; use function explode; -use function implode; use Infection\AbstractTestFramework\Coverage\TestLocation; use Infection\TestFramework\CommandLineArgumentsAndOptionsBuilder; use function ltrim; -use function Safe\sprintf; +use function rtrim; /** * @internal @@ -71,18 +70,33 @@ public function buildForInitialTestsRun(string $configPath, string $extraOptions return $options; } + /** + * @param TestLocation[] $tests + */ public function buildForMutant(string $configPath, string $extraOptions, array $tests): array { $options = $this->buildForInitialTestsRun($configPath, $extraOptions); if (count($tests) > 0) { - $escapedTests = array_map( - static fn (TestLocation $testLocation): string => escapeshellcmd($testLocation->getMethod()), - $tests - ); + $filterString = '/'; + $usedTestCases = []; + + foreach ($tests as $testLocation) { + $testCaseString = $testLocation->getMethod(); + + if (array_key_exists($testCaseString, $usedTestCases)) { + continue; + } + + $usedTestCases[$testCaseString] = true; + + $filterString .= escapeshellcmd($testCaseString) . '|'; + } + + $filterString = rtrim($filterString, '|') . '/'; $options[] = '--filter'; - $options[] = sprintf('/%s/', implode('|', array_unique($escapedTests))); + $options[] = $filterString; } return $options; From b185ad9aa901342f2ee228003b4d96d1713131ce Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Thu, 22 Jul 2021 23:58:16 +0300 Subject: [PATCH 6/8] Add `--only-covering-test-cases` option to enable/disable filtering by covering test cases By default, Infection runs all tests cases from **files** that contain at least 1 test case that cover mutated line Using `--only-covering-test-cases`, we can enable filtering and run only those test cases from files, that cover mutated line. For very fast test suites this decreases performance (see https://github.com/infection/infection/pull/1539). For slow test suites (like functional / integration tests) - this can dramatically improve performance of Mutation Testing / Infection --- src/Command/RunCommand.php | 11 +++++- src/Configuration/Configuration.php | 10 ++++- src/Configuration/ConfigurationFactory.php | 6 ++- src/Container.php | 13 +++++-- src/TestFramework/Factory.php | 6 ++- .../PhpUnit/Adapter/PestAdapterFactory.php | 5 ++- .../PhpUnit/Adapter/PhpUnitAdapterFactory.php | 5 ++- .../ArgumentsAndOptionsBuilder.php | 9 ++++- .../Configuration/ConfigurationAssertions.php | 4 +- .../ConfigurationFactoryTest.php | 26 +++++++++++-- .../Configuration/ConfigurationTest.php | 11 ++++-- tests/phpunit/ContainerTest.php | 6 ++- .../ArgumentsAndOptionsBuilderTest.php | 38 ++++++++++++++----- 13 files changed, 116 insertions(+), 34 deletions(-) diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php index 2bc06fdae..34483a165 100644 --- a/src/Command/RunCommand.php +++ b/src/Command/RunCommand.php @@ -116,6 +116,8 @@ final class RunCommand extends BaseCommand private const OPTION_USE_NOOP_MUTATORS = 'noop'; + private const OPTION_EXECUTE_ONLY_COVERING_TEST_CASES = 'only-covering-test-cases'; + /** @var string */ private const OPTION_MIN_MSI = 'min-msi'; @@ -257,6 +259,12 @@ protected function configure(): void InputOption::VALUE_NONE, 'Use noop mutators that do not change AST. For debugging purposes.', ) + ->addOption( + self::OPTION_EXECUTE_ONLY_COVERING_TEST_CASES, + null, + InputOption::VALUE_NONE, + 'Execute only those test cases that cover mutated line, not the whole file with covering test cases. Can dramatically speed up Mutation Testing for slow test suites. For PHPUnit / Pest it uses `--filter` option', + ) ->addOption( self::OPTION_MIN_MSI, null, @@ -444,7 +452,8 @@ private function createContainer(IO $io, LoggerInterface $logger): Container $gitDiffFilter, $gitDiffBase, (bool) $input->getOption(self::OPTION_LOGGER_GITHUB), - (bool) $input->getOption(self::OPTION_USE_NOOP_MUTATORS) + (bool) $input->getOption(self::OPTION_USE_NOOP_MUTATORS), + (bool) $input->getOption(self::OPTION_EXECUTE_ONLY_COVERING_TEST_CASES) ); } diff --git a/src/Configuration/Configuration.php b/src/Configuration/Configuration.php index fd6649bf0..87df313a3 100644 --- a/src/Configuration/Configuration.php +++ b/src/Configuration/Configuration.php @@ -87,6 +87,7 @@ class Configuration private bool $dryRun; /** @var array> */ private array $ignoreSourceCodeMutatorsMap; + private bool $executeOnlyCoveringTestCases; /** * @param string[] $sourceDirectories @@ -123,7 +124,8 @@ public function __construct( int $msiPrecision, int $threadCount, bool $dryRun, - array $ignoreSourceCodeMutatorsMap + array $ignoreSourceCodeMutatorsMap, + bool $executeOnlyCoveringTestCases ) { Assert::nullOrGreaterThanEq($timeout, 0); Assert::allString($sourceDirectories); @@ -161,6 +163,7 @@ public function __construct( $this->threadCount = $threadCount; $this->dryRun = $dryRun; $this->ignoreSourceCodeMutatorsMap = $ignoreSourceCodeMutatorsMap; + $this->executeOnlyCoveringTestCases = $executeOnlyCoveringTestCases; } public function getProcessTimeout(): float @@ -317,4 +320,9 @@ public function getIgnoreSourceCodeMutatorsMap(): array { return $this->ignoreSourceCodeMutatorsMap; } + + public function getExecuteOnlyCoveringTestCases(): bool + { + return $this->executeOnlyCoveringTestCases; + } } diff --git a/src/Configuration/ConfigurationFactory.php b/src/Configuration/ConfigurationFactory.php index 601bdd42e..07907742f 100644 --- a/src/Configuration/ConfigurationFactory.php +++ b/src/Configuration/ConfigurationFactory.php @@ -118,7 +118,8 @@ public function create( ?string $gitDiffFilter, ?string $gitDiffBase, bool $useGitHubLogger, - bool $useNoopMutators + bool $useNoopMutators, + bool $executeOnlyCoveringTestCases ): Configuration { $configDir = dirname($schema->getFile()); @@ -170,7 +171,8 @@ public function create( $msiPrecision, $threadCount, $dryRun, - $ignoreSourceCodeMutatorsMap + $ignoreSourceCodeMutatorsMap, + $executeOnlyCoveringTestCases ); } diff --git a/src/Container.php b/src/Container.php index 44c5e7820..00f6ee536 100644 --- a/src/Container.php +++ b/src/Container.php @@ -166,6 +166,7 @@ final class Container public const DEFAULT_GIT_DIFF_BASE = null; public const DEFAULT_USE_GITHUB_LOGGER = false; public const DEFAULT_USE_NOOP_MUTATORS = false; + public const DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES = false; public const DEFAULT_NO_PROGRESS = false; public const DEFAULT_FORCE_PROGRESS = false; public const DEFAULT_EXISTING_COVERAGE_PATH = null; @@ -684,7 +685,8 @@ public static function create(): self self::DEFAULT_GIT_DIFF_FILTER, self::DEFAULT_GIT_DIFF_BASE, self::DEFAULT_USE_GITHUB_LOGGER, - self::DEFAULT_USE_NOOP_MUTATORS + self::DEFAULT_USE_NOOP_MUTATORS, + self::DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES ); } @@ -715,7 +717,8 @@ public function withValues( ?string $gitDiffFilter, ?string $gitDiffBase, bool $useGitHubLogger, - bool $useNoopMutators + bool $useNoopMutators, + bool $executeOnlyCoveringTestCases ): self { $clone = clone $this; @@ -790,7 +793,8 @@ static function (self $container) use ( $gitDiffFilter, $gitDiffBase, $useGitHubLogger, - $useNoopMutators + $useNoopMutators, + $executeOnlyCoveringTestCases ): Configuration { return $container->getConfigurationFactory()->create( $container->getSchemaConfiguration(), @@ -815,7 +819,8 @@ static function (self $container) use ( $gitDiffFilter, $gitDiffBase, $useGitHubLogger, - $useNoopMutators + $useNoopMutators, + $executeOnlyCoveringTestCases ); } ); diff --git a/src/TestFramework/Factory.php b/src/TestFramework/Factory.php index 68f5fc7ed..13536f572 100644 --- a/src/TestFramework/Factory.php +++ b/src/TestFramework/Factory.php @@ -102,7 +102,8 @@ public function create(string $adapterName, bool $skipCoverage): TestFrameworkAd $this->jUnitFilePath, $this->projectDir, $this->infectionConfig->getSourceDirectories(), - $skipCoverage + $skipCoverage, + $this->infectionConfig->getExecuteOnlyCoveringTestCases() ); } @@ -120,7 +121,8 @@ public function create(string $adapterName, bool $skipCoverage): TestFrameworkAd $this->jUnitFilePath, $this->projectDir, $this->infectionConfig->getSourceDirectories(), - $skipCoverage + $skipCoverage, + $this->infectionConfig->getExecuteOnlyCoveringTestCases() ); } diff --git a/src/TestFramework/PhpUnit/Adapter/PestAdapterFactory.php b/src/TestFramework/PhpUnit/Adapter/PestAdapterFactory.php index 591b5d6f9..57250d62b 100644 --- a/src/TestFramework/PhpUnit/Adapter/PestAdapterFactory.php +++ b/src/TestFramework/PhpUnit/Adapter/PestAdapterFactory.php @@ -64,7 +64,8 @@ public static function create( string $jUnitFilePath, string $projectDir, array $sourceDirectories, - bool $skipCoverage + bool $skipCoverage, + bool $executeOnlyCoveringTestCases = false ): TestFrameworkAdapter { Assert::string($testFrameworkConfigDir, 'Config dir is not allowed to be `null` for the Pest adapter'); @@ -97,7 +98,7 @@ public static function create( $projectDir, new JUnitTestCaseSorter() ), - new ArgumentsAndOptionsBuilder(), + new ArgumentsAndOptionsBuilder($executeOnlyCoveringTestCases), new VersionParser(), new CommandLineBuilder() ); diff --git a/src/TestFramework/PhpUnit/Adapter/PhpUnitAdapterFactory.php b/src/TestFramework/PhpUnit/Adapter/PhpUnitAdapterFactory.php index cbc52b6c1..cfb13dccf 100644 --- a/src/TestFramework/PhpUnit/Adapter/PhpUnitAdapterFactory.php +++ b/src/TestFramework/PhpUnit/Adapter/PhpUnitAdapterFactory.php @@ -67,7 +67,8 @@ public static function create( string $jUnitFilePath, string $projectDir, array $sourceDirectories, - bool $skipCoverage + bool $skipCoverage, + bool $executeOnlyCoveringTestCases = false ): TestFrameworkAdapter { Assert::string($testFrameworkConfigDir, 'Config dir is not allowed to be `null` for the Pest adapter'); @@ -100,7 +101,7 @@ public static function create( $projectDir, new JUnitTestCaseSorter() ), - new ArgumentsAndOptionsBuilder(), + new ArgumentsAndOptionsBuilder($executeOnlyCoveringTestCases), new VersionParser(), new CommandLineBuilder() ); diff --git a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php index 77e2a4717..eecac103f 100644 --- a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php @@ -51,6 +51,13 @@ */ final class ArgumentsAndOptionsBuilder implements CommandLineArgumentsAndOptionsBuilder { + private bool $executeOnlyCoveringTestCases; + + public function __construct(bool $executeOnlyCoveringTestCases) + { + $this->executeOnlyCoveringTestCases = $executeOnlyCoveringTestCases; + } + public function buildForInitialTestsRun(string $configPath, string $extraOptions): array { $options = [ @@ -77,7 +84,7 @@ public function buildForMutant(string $configPath, string $extraOptions, array $ { $options = $this->buildForInitialTestsRun($configPath, $extraOptions); - if (count($tests) > 0) { + if ($this->executeOnlyCoveringTestCases && count($tests) > 0) { $filterString = '/'; $usedTestCases = []; diff --git a/tests/phpunit/Configuration/ConfigurationAssertions.php b/tests/phpunit/Configuration/ConfigurationAssertions.php index dd0e482bd..5aa9edd46 100644 --- a/tests/phpunit/Configuration/ConfigurationAssertions.php +++ b/tests/phpunit/Configuration/ConfigurationAssertions.php @@ -83,7 +83,8 @@ private function assertConfigurationStateIs( int $expectedMsiPrecision, int $expectedThreadCount, bool $expectedDryRyn, - array $expectedIgnoreSourceCodeMutatorsMap + array $expectedIgnoreSourceCodeMutatorsMap, + bool $expectedExecuteOnlyCoveringTestCases ): void { $this->assertSame($expectedTimeout, $configuration->getProcessTimeout()); $this->assertSame($expectedSourceDirectories, $configuration->getSourceDirectories()); @@ -132,6 +133,7 @@ private function assertConfigurationStateIs( $this->assertSame($expectedThreadCount, $configuration->getThreadCount()); $this->assertSame($expectedDryRyn, $configuration->isDryRun()); $this->assertSame($expectedIgnoreSourceCodeMutatorsMap, $configuration->getIgnoreSourceCodeMutatorsMap()); + $this->assertSame($expectedExecuteOnlyCoveringTestCases, $configuration->getExecuteOnlyCoveringTestCases()); } /** diff --git a/tests/phpunit/Configuration/ConfigurationFactoryTest.php b/tests/phpunit/Configuration/ConfigurationFactoryTest.php index 4b27ea5d2..f746aed8d 100644 --- a/tests/phpunit/Configuration/ConfigurationFactoryTest.php +++ b/tests/phpunit/Configuration/ConfigurationFactoryTest.php @@ -138,7 +138,8 @@ public function test_it_can_create_a_configuration( ?float $expectedMinMsi, bool $expectedShowMutations, ?float $expectedMinCoveredMsi, - array $expectedIgnoreSourceCodeMutatorsMap + array $expectedIgnoreSourceCodeMutatorsMap, + bool $inputExecuteOnlyCoveringTestCases ): void { $config = $this ->createConfigurationFactory($ciDetected) @@ -165,7 +166,8 @@ public function test_it_can_create_a_configuration( $inputGitDiffFilter, $inputGitDiffBase, $inputUseGitHubAnnotationsLogger, - $inputUseNoopMutators + $inputUseNoopMutators, + $inputExecuteOnlyCoveringTestCases ) ; @@ -198,7 +200,8 @@ public function test_it_can_create_a_configuration( $inputMsiPrecision, $inputThreadsCount, $inputDryRun, - $expectedIgnoreSourceCodeMutatorsMap + $expectedIgnoreSourceCodeMutatorsMap, + $inputExecuteOnlyCoveringTestCases ); } @@ -272,6 +275,7 @@ public function valueProvider(): iterable false, null, [], + true, ]; yield 'null timeout' => self::createValueForTimeout( @@ -717,6 +721,7 @@ public function valueProvider(): iterable false, null, [], + false, ]; yield 'complete' => [ @@ -813,6 +818,7 @@ public function valueProvider(): iterable true, 81.5, [], + false, ]; } @@ -885,6 +891,7 @@ private static function createValueForTimeout( false, null, [], + false, ]; } @@ -957,6 +964,7 @@ private static function createValueForTmpDir( false, null, [], + false, ]; } @@ -1030,6 +1038,7 @@ private static function createValueForCoveragePath( false, null, [], + false, ]; } @@ -1102,6 +1111,7 @@ private static function createValueForPhpUnitConfigDir( false, null, [], + false, ]; } @@ -1175,6 +1185,7 @@ private static function createValueForNoProgress( false, null, [], + false, ]; } @@ -1248,6 +1259,7 @@ private static function createValueForIgnoreMsiWithNoMutations( false, null, [], + false, ]; } @@ -1321,6 +1333,7 @@ private static function createValueForMinMsi( false, null, [], + false, ]; } @@ -1394,6 +1407,7 @@ private static function createValueForMinCoveredMsi( false, $expectedMinCoveredMsi, [], + false, ]; } @@ -1468,6 +1482,7 @@ private static function createValueForTestFramework( false, null, [], + false, ]; } @@ -1541,6 +1556,7 @@ private static function createValueForInitialTestsPhpOptions( false, null, [], + false, ]; } @@ -1615,6 +1631,7 @@ private static function createValueForTestFrameworkExtraOptions( false, null, [], + false, ]; } @@ -1688,6 +1705,7 @@ private static function createValueForTestFrameworkKey( false, null, [], + false, ]; } @@ -1765,6 +1783,7 @@ private static function createValueForMutators( false, null, [], + false, ]; } @@ -1843,6 +1862,7 @@ private static function createValueForIgnoreSourceCodeByRegex( false, null, $expectedIgnoreSourceCodeMutatorsMap, + false, ]; } diff --git a/tests/phpunit/Configuration/ConfigurationTest.php b/tests/phpunit/Configuration/ConfigurationTest.php index 93746ea10..3686b8514 100644 --- a/tests/phpunit/Configuration/ConfigurationTest.php +++ b/tests/phpunit/Configuration/ConfigurationTest.php @@ -87,7 +87,8 @@ public function test_it_can_be_instantiated( int $msiPrecision, int $threadsCount, bool $dryRun, - array $ignoreSourceCodeMutatorsMap + array $ignoreSourceCodeMutatorsMap, + bool $executeOnlyCoveringTestCases ): void { $config = new Configuration( $timeout, @@ -117,7 +118,8 @@ public function test_it_can_be_instantiated( $msiPrecision, $threadsCount, $dryRun, - $ignoreSourceCodeMutatorsMap + $ignoreSourceCodeMutatorsMap, + $executeOnlyCoveringTestCases ); $this->assertConfigurationStateIs( @@ -149,7 +151,8 @@ public function test_it_can_be_instantiated( $msiPrecision, $threadsCount, $dryRun, - $ignoreSourceCodeMutatorsMap + $ignoreSourceCodeMutatorsMap, + $executeOnlyCoveringTestCases ); } @@ -184,6 +187,7 @@ public function valueProvider(): iterable 0, false, [], + false, ]; yield 'nominal' => [ @@ -230,6 +234,7 @@ public function valueProvider(): iterable [ 'For_' => ['.*someMethod.*'], ], + true, ]; } } diff --git a/tests/phpunit/ContainerTest.php b/tests/phpunit/ContainerTest.php index a46f66965..7503c08d1 100644 --- a/tests/phpunit/ContainerTest.php +++ b/tests/phpunit/ContainerTest.php @@ -95,7 +95,8 @@ public function test_it_can_build_lazy_source_file_data_factory_that_fails_on_us Container::DEFAULT_GIT_DIFF_FILTER, Container::DEFAULT_GIT_DIFF_BASE, Container::DEFAULT_USE_GITHUB_LOGGER, - Container::DEFAULT_USE_NOOP_MUTATORS + Container::DEFAULT_USE_NOOP_MUTATORS, + Container::DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES ); $traces = $newContainer->getUnionTraceProvider()->provideTraces(); @@ -144,7 +145,8 @@ public function test_it_provides_a_friendly_error_when_attempting_to_configure_i Container::DEFAULT_GIT_DIFF_FILTER, Container::DEFAULT_GIT_DIFF_BASE, Container::DEFAULT_USE_GITHUB_LOGGER, - Container::DEFAULT_USE_NOOP_MUTATORS + Container::DEFAULT_USE_NOOP_MUTATORS, + Container::DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES, ); } } diff --git a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php index 8bfe9c213..3b99ff924 100644 --- a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php +++ b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php @@ -50,7 +50,7 @@ final class ArgumentsAndOptionsBuilderTest extends TestCase protected function setUp(): void { - $this->builder = new ArgumentsAndOptionsBuilder(); + $this->builder = new ArgumentsAndOptionsBuilder(false); } public function test_it_can_build_the_command_without_extra_options(): void @@ -98,19 +98,26 @@ public function test_it_can_build_the_command_with_extra_options_that_contains_s /** * @dataProvider provideTestCases */ - public function test_it_can_build_the_command_with_filter_option_for_covering_tests_for_mutant(array $testCases, string $expectedFilterOptionValue): void + public function test_it_can_build_the_command_with_filter_option_for_covering_tests_for_mutant(bool $executeOnlyCoveringTestCases, array $testCases, ?string $expectedFilterOptionValue = null): void { $configPath = '/the config/path'; + $builder = new ArgumentsAndOptionsBuilder($executeOnlyCoveringTestCases); + + $expectedArgumentsAndOptions = [ + '--configuration', + $configPath, + '--path=/a path/with spaces', + ]; + + if ($executeOnlyCoveringTestCases) { + $expectedArgumentsAndOptions[] = '--filter'; + $expectedArgumentsAndOptions[] = $expectedFilterOptionValue; + } + $this->assertSame( - [ - '--configuration', - $configPath, - '--path=/a path/with spaces', - '--filter', - $expectedFilterOptionValue, - ], - $this->builder->buildForMutant( + $expectedArgumentsAndOptions, + $builder->buildForMutant( $configPath, '--path=/a path/with spaces', array_map( @@ -123,7 +130,15 @@ public function test_it_can_build_the_command_with_filter_option_for_covering_te public function provideTestCases(): Generator { + yield '--only-covering-test-cases is disabled' => [ + false, + [ + 'App\Test::test_case1', + ], + ]; + yield '1 test case' => [ + true, [ 'App\Test::test_case1', ], @@ -131,6 +146,7 @@ public function provideTestCases(): Generator ]; yield '2 test cases' => [ + true, [ 'App\Test::test_case1', 'App\Test::test_case2', @@ -139,6 +155,7 @@ public function provideTestCases(): Generator ]; yield '2 simple test cases, 1 with data set and special character >' => [ + true, [ 'App\Test::test_case1 with data set "With special character >"', 'App\Test::test_case2', @@ -147,6 +164,7 @@ public function provideTestCases(): Generator ]; yield '2 simple test cases, 1 with data set and special character @' => [ + true, [ 'App\Test::test_case1 with data set "With special character @"', 'App\Test::test_case2', From 7a23d0b4b1331395ff7c911193f018bdb5638315 Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Fri, 23 Jul 2021 00:31:37 +0300 Subject: [PATCH 7/8] Use `preg_quote()` instead of `escapeshellcmd` to prepare string to be a regular expression --- .../PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php | 4 +++- .../CommandLine/ArgumentsAndOptionsBuilderTest.php | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php index eecac103f..df09614d9 100644 --- a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php @@ -39,11 +39,13 @@ use function array_map; use function array_merge; use function count; +use function escapeshellarg; use function escapeshellcmd; use function explode; use Infection\AbstractTestFramework\Coverage\TestLocation; use Infection\TestFramework\CommandLineArgumentsAndOptionsBuilder; use function ltrim; +use function preg_quote; use function rtrim; /** @@ -97,7 +99,7 @@ public function buildForMutant(string $configPath, string $extraOptions, array $ $usedTestCases[$testCaseString] = true; - $filterString .= escapeshellcmd($testCaseString) . '|'; + $filterString .= preg_quote($testCaseString, '/') . '|'; } $filterString = rtrim($filterString, '|') . '/'; diff --git a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php index 3b99ff924..5a271b666 100644 --- a/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php +++ b/tests/phpunit/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilderTest.php @@ -142,7 +142,7 @@ public function provideTestCases(): Generator [ 'App\Test::test_case1', ], - '/App\\\\Test::test_case1/', + '/App\\\\Test\:\:test_case1/', ]; yield '2 test cases' => [ @@ -151,7 +151,7 @@ public function provideTestCases(): Generator 'App\Test::test_case1', 'App\Test::test_case2', ], - '/App\\\\Test::test_case1|App\\\\Test::test_case2/', + '/App\\\\Test\:\:test_case1|App\\\\Test\:\:test_case2/', ]; yield '2 simple test cases, 1 with data set and special character >' => [ @@ -160,7 +160,7 @@ public function provideTestCases(): Generator 'App\Test::test_case1 with data set "With special character >"', 'App\Test::test_case2', ], - '/App\\\\Test::test_case1 with data set "With special character \\>"|App\\\\Test::test_case2/', + '/App\\\\Test\:\:test_case1 with data set "With special character \\>"|App\\\\Test\:\:test_case2/', ]; yield '2 simple test cases, 1 with data set and special character @' => [ @@ -169,7 +169,7 @@ public function provideTestCases(): Generator 'App\Test::test_case1 with data set "With special character @"', 'App\Test::test_case2', ], - '/App\\\\Test::test_case1 with data set "With special character @"|App\\\\Test::test_case2/', + '/App\\\\Test\:\:test_case1 with data set "With special character @"|App\\\\Test\:\:test_case2/', ]; } } From 64c1591e330e86c0963712dfca08ac3dcd42f13b Mon Sep 17 00:00:00 2001 From: maks-rafalko Date: Fri, 23 Jul 2021 00:35:07 +0300 Subject: [PATCH 8/8] Fix CS --- .../PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php index df09614d9..cfadbb9cc 100644 --- a/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php +++ b/src/TestFramework/PhpUnit/CommandLine/ArgumentsAndOptionsBuilder.php @@ -39,8 +39,6 @@ use function array_map; use function array_merge; use function count; -use function escapeshellarg; -use function escapeshellcmd; use function explode; use Infection\AbstractTestFramework\Coverage\TestLocation; use Infection\TestFramework\CommandLineArgumentsAndOptionsBuilder;