diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php index da22c4f1d6..86d6b13e1b 100644 --- a/src/Command/RunCommand.php +++ b/src/Command/RunCommand.php @@ -115,6 +115,8 @@ final class RunCommand extends BaseCommand /** @var string */ private const OPTION_LOGGER_GITHUB = 'logger-github'; + private const OPTION_LOGGER_HTML = 'logger-html'; + private const OPTION_USE_NOOP_MUTATORS = 'noop'; private const OPTION_EXECUTE_ONLY_COVERING_TEST_CASES = 'only-covering-test-cases'; @@ -254,6 +256,12 @@ protected function configure(): void InputOption::VALUE_NONE, 'Log escaped Mutants as GitHub Annotations.', ) + ->addOption( + self::OPTION_LOGGER_HTML, + null, + InputOption::VALUE_REQUIRED, + 'Path to HTML report file, similar to PHPUnit HTML report.', + ) ->addOption( self::OPTION_USE_NOOP_MUTATORS, null, @@ -378,6 +386,7 @@ private function createContainer(IO $io, LoggerInterface $logger): Container $testFramework = trim((string) $input->getOption(self::OPTION_TEST_FRAMEWORK)); $testFrameworkExtraOptions = trim((string) $input->getOption(self::OPTION_TEST_FRAMEWORK_OPTIONS)); $initialTestsPhpOptions = trim((string) $input->getOption(self::OPTION_INITIAL_TESTS_PHP_OPTIONS)); + $htmlFileLogPath = trim((string) $input->getOption(self::OPTION_LOGGER_HTML)); /** @var string|null $minMsi */ $minMsi = $input->getOption(self::OPTION_MIN_MSI); @@ -457,6 +466,7 @@ private function createContainer(IO $io, LoggerInterface $logger): Container $gitDiffFilter, $gitDiffBase, (bool) $input->getOption(self::OPTION_LOGGER_GITHUB), + $htmlFileLogPath === '' ? Container::DEFAULT_HTML_LOGGER_PATH : $htmlFileLogPath, (bool) $input->getOption(self::OPTION_USE_NOOP_MUTATORS), (bool) $input->getOption(self::OPTION_EXECUTE_ONLY_COVERING_TEST_CASES) ); diff --git a/src/Configuration/ConfigurationFactory.php b/src/Configuration/ConfigurationFactory.php index 07907742f8..22abe3e2a7 100644 --- a/src/Configuration/ConfigurationFactory.php +++ b/src/Configuration/ConfigurationFactory.php @@ -118,6 +118,7 @@ public function create( ?string $gitDiffFilter, ?string $gitDiffBase, bool $useGitHubLogger, + ?string $htmlLogFilePath, bool $useNoopMutators, bool $executeOnlyCoveringTestCases ): Configuration { @@ -149,7 +150,7 @@ public function create( ), $this->retrieveFilter($filter, $gitDiffFilter, $gitDiffBase), $schema->getSource()->getExcludes(), - $this->retrieveLogs($schema->getLogs(), $useGitHubLogger), + $this->retrieveLogs($schema->getLogs(), $useGitHubLogger, $htmlLogFilePath), $logVerbosity, $namespacedTmpDir, $this->retrievePhpUnit($schema, $configDir), @@ -306,12 +307,16 @@ private function retrieveFilter(string $filter, ?string $gitDiffFilter, ?string return $this->gitDiffFileProvider->provide($gitDiffFilter, $gitDiffBase ?? GitDiffFileProvider::DEFAULT_BASE); } - private function retrieveLogs(Logs $logs, bool $useGitHubLogger): Logs + private function retrieveLogs(Logs $logs, bool $useGitHubLogger, ?string $htmlLogFilePath): Logs { if ($useGitHubLogger) { $logs->setUseGitHubAnnotationsLogger($useGitHubLogger); } + if ($htmlLogFilePath !== null) { + $logs->setHtmlLogFilePath($htmlLogFilePath); + } + return $logs; } } diff --git a/src/Configuration/Entry/Logs.php b/src/Configuration/Entry/Logs.php index 33fed796d7..bc511685fa 100644 --- a/src/Configuration/Entry/Logs.php +++ b/src/Configuration/Entry/Logs.php @@ -94,6 +94,11 @@ public function getHtmlLogFilePath(): ?string return $this->htmlLogFilePath; } + public function setHtmlLogFilePath(string $htmlLogFilePath): void + { + $this->htmlLogFilePath = $htmlLogFilePath; + } + public function getSummaryLogFilePath(): ?string { return $this->summaryLogFilePath; diff --git a/src/Container.php b/src/Container.php index 534730621a..e6c4e66f1b 100644 --- a/src/Container.php +++ b/src/Container.php @@ -167,6 +167,7 @@ final class Container public const DEFAULT_GIT_DIFF_FILTER = null; public const DEFAULT_GIT_DIFF_BASE = null; public const DEFAULT_USE_GITHUB_LOGGER = false; + public const DEFAULT_HTML_LOGGER_PATH = null; public const DEFAULT_USE_NOOP_MUTATORS = false; public const DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES = false; public const DEFAULT_NO_PROGRESS = false; @@ -695,6 +696,7 @@ public static function create(): self self::DEFAULT_GIT_DIFF_FILTER, self::DEFAULT_GIT_DIFF_BASE, self::DEFAULT_USE_GITHUB_LOGGER, + self::DEFAULT_HTML_LOGGER_PATH, self::DEFAULT_USE_NOOP_MUTATORS, self::DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES ); @@ -727,6 +729,7 @@ public function withValues( ?string $gitDiffFilter, ?string $gitDiffBase, bool $useGitHubLogger, + ?string $htmlLogFilePath, bool $useNoopMutators, bool $executeOnlyCoveringTestCases ): self { @@ -803,6 +806,7 @@ static function (self $container) use ( $gitDiffFilter, $gitDiffBase, $useGitHubLogger, + $htmlLogFilePath, $useNoopMutators, $executeOnlyCoveringTestCases ): Configuration { @@ -829,6 +833,7 @@ static function (self $container) use ( $gitDiffFilter, $gitDiffBase, $useGitHubLogger, + $htmlLogFilePath, $useNoopMutators, $executeOnlyCoveringTestCases ); diff --git a/tests/benchmark/Tracing/provide-traces-closure.php b/tests/benchmark/Tracing/provide-traces-closure.php index 5140cad961..e25a206de0 100644 --- a/tests/benchmark/Tracing/provide-traces-closure.php +++ b/tests/benchmark/Tracing/provide-traces-closure.php @@ -70,6 +70,7 @@ Container::DEFAULT_GIT_DIFF_FILTER, Container::DEFAULT_GIT_DIFF_BASE, Container::DEFAULT_USE_GITHUB_LOGGER, + Container::DEFAULT_HTML_LOGGER_PATH, true, Container::DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES ); diff --git a/tests/phpunit/Configuration/ConfigurationFactoryTest.php b/tests/phpunit/Configuration/ConfigurationFactoryTest.php index 4f4fdda03a..03a2d71754 100644 --- a/tests/phpunit/Configuration/ConfigurationFactoryTest.php +++ b/tests/phpunit/Configuration/ConfigurationFactoryTest.php @@ -112,6 +112,7 @@ public function test_it_can_create_a_configuration( ?string $inputGitDiffFilter, string $inputGitDiffBase, bool $inputUseGitHubAnnotationsLogger, + ?string $inputHtmlLogFilePath, bool $inputUseNoopMutators, int $inputMsiPrecision, int $expectedTimeout, @@ -166,6 +167,7 @@ public function test_it_can_create_a_configuration( $inputGitDiffFilter, $inputGitDiffBase, $inputUseGitHubAnnotationsLogger, + $inputHtmlLogFilePath, $inputUseNoopMutators, $inputExecuteOnlyCoveringTestCases ) @@ -248,6 +250,7 @@ public function valueProvider(): iterable 'AM', 'master', true, + null, false, 2, 10, @@ -278,6 +281,30 @@ public function valueProvider(): iterable true, ]; + yield 'null html file log path with existing path from config file' => self::createValueForHtmlLogFilePath( + 'from-config.html', + null, + 'from-config.html' + ); + + yield 'override html file log path from CLI option with existing path from config file' => self::createValueForHtmlLogFilePath( + 'from-config.html', + 'from-cli.html', + 'from-cli.html' + ); + + yield 'set html file log path from CLI option when config file has no setting' => self::createValueForHtmlLogFilePath( + null, + 'from-cli.html', + 'from-cli.html' + ); + + yield 'null html file log path in config and CLI' => self::createValueForHtmlLogFilePath( + null, + null, + null + ); + yield 'null timeout' => self::createValueForTimeout( null, 10 @@ -691,6 +718,7 @@ public function valueProvider(): iterable null, 'master', false, + null, false, 2, 10, @@ -774,6 +802,7 @@ public function valueProvider(): iterable null, 'master', false, + null, false, 2, 10, @@ -866,6 +895,7 @@ private static function createValueForTimeout( null, 'master', false, + null, false, 2, $expectedTimeOut, @@ -939,6 +969,7 @@ private static function createValueForTmpDir( null, 'master', false, + null, false, 2, 10, @@ -1013,6 +1044,7 @@ private static function createValueForCoveragePath( null, 'master', false, + null, false, 2, 10, @@ -1086,6 +1118,7 @@ private static function createValueForPhpUnitConfigDir( null, 'master', false, + null, false, 2, 10, @@ -1160,6 +1193,7 @@ private static function createValueForNoProgress( null, 'master', false, + null, false, 2, 10, @@ -1234,6 +1268,7 @@ private static function createValueForIgnoreMsiWithNoMutations( null, 'master', false, + null, false, 2, 10, @@ -1308,6 +1343,7 @@ private static function createValueForMinMsi( null, 'master', false, + null, false, 2, 10, @@ -1382,6 +1418,7 @@ private static function createValueForMinCoveredMsi( null, 'master', false, + null, false, 2, 10, @@ -1457,6 +1494,7 @@ private static function createValueForTestFramework( null, 'master', false, + null, false, 2, 10, @@ -1531,6 +1569,7 @@ private static function createValueForInitialTestsPhpOptions( null, 'master', false, + null, false, 2, 10, @@ -1606,6 +1645,7 @@ private static function createValueForTestFrameworkExtraOptions( null, 'master', false, + null, false, 2, 10, @@ -1680,6 +1720,7 @@ private static function createValueForTestFrameworkKey( null, 'master', false, + null, false, 2, 10, @@ -1758,6 +1799,7 @@ private static function createValueForMutators( null, 'master', false, + null, $useNoopMutatos, 2, 10, @@ -1835,6 +1877,7 @@ private static function createValueForIgnoreSourceCodeByRegex( null, 'master', false, + null, false, 2, 10, @@ -1868,6 +1911,98 @@ private static function createValueForIgnoreSourceCodeByRegex( ]; } + private static function createValueForHtmlLogFilePath(?string $htmlFileLogPathInConfig, ?string $htmlFileLogPathFromCliOption, ?string $expectedHtmlFileLogPath): array + { + $expectedLogs = new Logs( + null, + $expectedHtmlFileLogPath, + null, + null, + null, + null, + true, + null, + ); + + return [ + false, + new SchemaConfiguration( + '/path/to/infection.json', + null, + new Source([], []), + new Logs( + null, + $htmlFileLogPathInConfig, + null, + null, + null, + null, + false, + null, + ), + '', + new PhpUnit(null, null), + null, + null, + null, + [], + null, + null, + null, + null + ), + null, + null, + false, + 'none', + false, + false, + false, + false, + null, + false, + null, + '', + null, + null, + '', + 0, + false, + 'AM', + 'master', + true, + $htmlFileLogPathFromCliOption, + false, + 2, + 10, + [], + [], + 'src/a.php,src/b.php', + [], + $expectedLogs, + 'none', + sys_get_temp_dir() . '/infection', + new PhpUnit('/path/to', null), + self::getDefaultMutators(), + 'phpunit', + null, + null, + false, + '', + sys_get_temp_dir() . '/infection', + false, + false, + false, + false, + false, + null, + false, + null, + [], + true, + ]; + } + /** * @return array */ diff --git a/tests/phpunit/ContainerTest.php b/tests/phpunit/ContainerTest.php index 1e29ad125e..ec516e5808 100644 --- a/tests/phpunit/ContainerTest.php +++ b/tests/phpunit/ContainerTest.php @@ -95,6 +95,7 @@ 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_HTML_LOGGER_PATH, Container::DEFAULT_USE_NOOP_MUTATORS, Container::DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES ); @@ -143,6 +144,7 @@ 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_HTML_LOGGER_PATH, Container::DEFAULT_USE_NOOP_MUTATORS, Container::DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES, );