Skip to content

Commit

Permalink
Skip analysis when no executed lines with --git-diff-lines option (#…
Browse files Browse the repository at this point in the history
…1688)

When using the `--git-diff-lines` option, there are situations where a
file can be modified but will not yield any test change, for instance
when only a comment is modified in a PHP source file.

This commit prevents an error being thrown when this very situation
occurs; instead, the analysis is skipped.
  • Loading branch information
romm committed May 6, 2022
1 parent 714a8d2 commit e5aa8de
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/Command/RunCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
use Infection\Logger\GitHub\NoFilesInDiffToMutate;
use Infection\Metrics\MinMsiCheckFailed;
use Infection\Process\Runner\InitialTestsFailed;
use Infection\TestFramework\Coverage\XmlReport\NoLineExecutedInDiffLinesMode;
use Infection\TestFramework\TestFrameworkTypes;
use InvalidArgumentException;
use const PHP_SAPI;
Expand Down Expand Up @@ -369,7 +370,7 @@ protected function executeCommand(IO $io): bool
$engine->execute();

return true;
} catch (NoFilesInDiffToMutate $e) {
} catch (NoFilesInDiffToMutate | NoLineExecutedInDiffLinesMode $e) {
$io->success($e->getMessage());

return true;
Expand Down
4 changes: 3 additions & 1 deletion src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,9 @@ public static function create(): self
$container = new self([
Filesystem::class => static fn (): Filesystem => new Filesystem(),
TmpDirProvider::class => static fn (): TmpDirProvider => new TmpDirProvider(),
IndexXmlCoverageParser::class => static fn (): IndexXmlCoverageParser => new IndexXmlCoverageParser(),
IndexXmlCoverageParser::class => static fn (self $container): IndexXmlCoverageParser => new IndexXmlCoverageParser(
$container->getConfiguration()->isForGitDiffLines()
),
XmlCoverageParser::class => static fn (): XmlCoverageParser => new XmlCoverageParser(),
CoveredTraceProvider::class => static fn (self $container): CoveredTraceProvider => new CoveredTraceProvider(
$container->getPhpUnitXmlCoverageTraceProvider(),
Expand Down
15 changes: 12 additions & 3 deletions src/TestFramework/Coverage/XmlReport/IndexXmlCoverageParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@
*/
class IndexXmlCoverageParser
{
private bool $isForGitDiffLines;

public function __construct(bool $isForGitDiffLines)
{
$this->isForGitDiffLines = $isForGitDiffLines;
}

/**
* Parses the given PHPUnit XML coverage index report (index.xml) to collect the information
* needed to parse general coverage data. Note that this data is likely incomplete an will
Expand All @@ -60,7 +67,7 @@ public function parse(
): iterable {
$xPath = XPathFactory::createXPath($xmlIndexCoverageContent);

self::assertHasExecutedLines($xPath);
self::assertHasExecutedLines($xPath, $this->isForGitDiffLines);

return $this->parseNodes($coverageIndexPath, $coverageBasePath, $xPath);
}
Expand Down Expand Up @@ -90,7 +97,7 @@ private function parseNodes(
/**
* @throws NoLineExecuted
*/
private static function assertHasExecutedLines(SafeDOMXPath $xPath): void
private static function assertHasExecutedLines(SafeDOMXPath $xPath, bool $isForGitDiffLines): void
{
$lineCoverage = $xPath->query('/phpunit/project/directory[1]/totals/lines')->item(0);

Expand All @@ -99,7 +106,9 @@ private static function assertHasExecutedLines(SafeDOMXPath $xPath): void
|| ($coverageCount = $lineCoverage->getAttribute('executed')) === '0'
|| $coverageCount === ''
) {
throw NoLineExecuted::create();
throw $isForGitDiffLines
? NoLineExecutedInDiffLinesMode::create()
: NoLineExecuted::create();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* This code is licensed under the BSD 3-Clause License.
*
* Copyright (c) 2017, Maks Rafalko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

declare(strict_types=1);

namespace Infection\TestFramework\Coverage\XmlReport;

use UnexpectedValueException;

/**
* @internal
*/
final class NoLineExecutedInDiffLinesMode extends UnexpectedValueException
{
public static function create(): self
{
return new self('No covered lines in diff found, skipping mutation analysis.');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use function array_diff;
use Infection\TestFramework\Coverage\XmlReport\IndexXmlCoverageParser;
use Infection\TestFramework\Coverage\XmlReport\NoLineExecuted;
use Infection\TestFramework\Coverage\XmlReport\NoLineExecutedInDiffLinesMode;
use Infection\TestFramework\Coverage\XmlReport\SourceFileInfoProvider;
use Infection\Tests\Fixtures\TestFramework\PhpUnit\Coverage\XmlCoverageFixture;
use Infection\Tests\Fixtures\TestFramework\PhpUnit\Coverage\XmlCoverageFixtures;
Expand Down Expand Up @@ -68,7 +69,7 @@ final class IndexXmlCoverageParserTest extends TestCase

protected function setUp(): void
{
$this->parser = new IndexXmlCoverageParser();
$this->parser = new IndexXmlCoverageParser(false);
}

/**
Expand Down Expand Up @@ -169,6 +170,20 @@ public function test_it_errors_when_no_lines_were_executed(string $xml): void
);
}

/**
* @dataProvider noCoveredLineReportProviders
*/
public function test_it_errors_for_git_diff_lines_mode_when_no_lines_were_executed(string $xml): void
{
$this->expectException(NoLineExecutedInDiffLinesMode::class);

(new IndexXmlCoverageParser(true))->parse(
'/path/to/index.xml',
$xml,
XmlCoverageFixtures::FIXTURES_COVERAGE_DIR
);
}

public function coverageProvider(): iterable
{
yield 'nominal' => [self::getXml()];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/**
* This code is licensed under the BSD 3-Clause License.
*
* Copyright (c) 2017, Maks Rafalko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

declare(strict_types=1);

namespace Infection\Tests\TestFramework\Coverage\XmlReport;

use Infection\TestFramework\Coverage\XmlReport\NoLineExecutedInDiffLinesMode;
use PHPUnit\Framework\TestCase;

final class NoLineExecutedInDiffLinesModeTest extends TestCase
{
public function test_it_can_create_an_instance(): void
{
$exception = NoLineExecutedInDiffLinesMode::create();

$this->assertInstanceOf(NoLineExecutedInDiffLinesMode::class, $exception);
$this->assertSame(
'No covered lines in diff found, skipping mutation analysis.',
$exception->getMessage()
);
}
}

0 comments on commit e5aa8de

Please sign in to comment.