Skip to content

Add support for multiple coverage files passed as argument #38

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,23 +82,24 @@ php vendor/bin/phpfci inspect coverage.xml --reportGitlab=reports/gitlab.errors.
Text format to stdout:
```shell script
php vendor/bin/phpfci inspect coverage.xml
php vendor/bin/phpfci inspect coverage1.xml coverage2.xml
```
```shell script
php vendor/bin/phpfci inspect coverage.xml --reportText
```

## Command line arguments

| Option | Values | Description |
|-------------------------------|------------------------------------------|-------------------------------------------------------------------------|
| `argument 1` | `inspect`, `baseline` | the command to execute. |
| `argument 2` | `coverage.xml` | the phpunit clover coverage input file. |
| `--reportGitlab=[<file>]` | filepath or if absent stdout | the file (or stdout) to write the gitlab format to. |
| `--reportCheckstyle=[<file>]` | filepath or if absent stdout | the file (or stdout) to write the checkstyle format to. |
| `--reportText=[<file>]` | filepath or if absent stdout | the file (or stdout) to write the checkstyle format to. |
| `--config=<path-to-file>` | `phpfci.xml` | the path to the config file. |
| `--baseDir=<path>` | defaults to directory of the output file | The root directory of the project, will be used to make paths relative. |
| `--exit-code-on-failure` | - | Set exit code to `1` when there are failures. |
| Option | Values | Description |
|--------------------------------|------------------------------------------|-------------------------------------------------------------------------|
| `argument 1` | `inspect`, `baseline` | the command to execute. |
| `argument 2` [`argument 3`]... | `coverage.xml` [`coverage2.xml`] | the phpunit clover coverage input file(s). |
| `--reportGitlab=[<file>]` | filepath or if absent stdout | the file (or stdout) to write the gitlab format to. |
| `--reportCheckstyle=[<file>]` | filepath or if absent stdout | the file (or stdout) to write the checkstyle format to. |
| `--reportText=[<file>]` | filepath or if absent stdout | the file (or stdout) to write the checkstyle format to. |
| `--config=<path-to-file>` | `phpfci.xml` | the path to the config file. |
| `--baseDir=<path>` | defaults to directory of the output file | The root directory of the project, will be used to make paths relative. |
| `--exit-code-on-failure` | - | Set exit code to `1` when there are failures. |

Note: if no `--reportGitlab`, `--reportCheckstyle` or `--reportText` is set, it will default to `--reportText=php://stdout`

Expand Down
13 changes: 9 additions & 4 deletions src/Command/InspectCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use DigitalRevolution\CodeCoverageInspection\Renderer\TextRenderer;
use JsonException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -25,7 +26,7 @@
class InspectCommand extends Command
{
private ConfigFactory $configFactory;
private string $schemaPath;
private string $schemaPath;

public function __construct(string $name = null)
{
Expand All @@ -38,7 +39,7 @@ protected function configure(): void
{
$this->setName("inspect")
->setDescription("PHPUnit code coverage inspection")
->addArgument('coverage', InputOption::VALUE_REQUIRED, 'Path to phpunit\'s coverage.xml')
->addArgument('coverage', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'Path to phpunit\'s coverage.xml')
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Path to configuration file. Optional')
->addOption('baseDir', '', InputOption::VALUE_REQUIRED, 'Base directory from where to determine the relative config paths')
->addOption('reportGitlab', '', InputOption::VALUE_OPTIONAL, 'Gitlab output format. To file or if absent to stdout', false)
Expand All @@ -62,10 +63,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int
// gather data
$domConfig = DOMDocumentFactory::getValidatedDOMDocument($inputConfig->getConfigPath(), $this->schemaPath);
$config = InspectionConfigFactory::fromDOMDocument($inputConfig->getBaseDir(), $domConfig);
$metrics = MetricsFactory::getFileMetrics(DOMDocumentFactory::getDOMDocument($inputConfig->getCoverageFilepath()));

$domDocuments = [];
foreach ($inputConfig->getCoveragesFilepath() as $coverageFilepath) {
$domDocuments[] = DOMDocumentFactory::getDOMDocument($coverageFilepath);
}
$metrics = MetricsFactory::getFilesMetrics($domDocuments);
if (count($metrics) === 0) {
$output->writeln("No metrics found in coverage file: " . $inputConfig->getCoverageFilepath());
$output->writeln("No metrics found in coverage files: " . implode(', ', $inputConfig->getCoveragesFilepath()));

return Command::FAILURE;
}
Expand Down
15 changes: 11 additions & 4 deletions src/Lib/Config/ConfigFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@ class ConfigFactory
*/
public function createInspectConfig(InputInterface $input)
{
$configPath = FileUtil::getExistingFile($input->getOption('config') ?? FileUtil::findFilePath((string)getcwd(), self::CONFIG_FILES));
$coverageFilepath = FileUtil::getExistingFile($input->getArgument('coverage'));
$baseDir = $input->getOption('baseDir') ?? $configPath->getPath();
$configPath = FileUtil::getExistingFile($input->getOption('config') ?? FileUtil::findFilePath((string)getcwd(), self::CONFIG_FILES));
$coveragesFilepath = [];
$coverageArgument = $input->getArgument('coverage');
if (is_array($coverageArgument) === false) {
return new ConfigViolation('Coverage argument should be an array');
}
foreach ($coverageArgument as $coverageFilepath) {
$coveragesFilepath[] = FileUtil::getExistingFile($coverageFilepath);
}
$baseDir = $input->getOption('baseDir') ?? $configPath->getPath();

if (is_string($baseDir) === false) {
return new ConfigViolation('--base-dir expecting a value string as argument');
Expand Down Expand Up @@ -46,7 +53,7 @@ public function createInspectConfig(InputInterface $input)

$exitCodeOnFailure = $input->getOption('exit-code-on-failure') !== false;

return new InspectConfig($coverageFilepath, $configPath, $baseDir, $reportGitlab, $reportCheckstyle, $reportText, $exitCodeOnFailure);
return new InspectConfig($coveragesFilepath, $configPath, $baseDir, $reportGitlab, $reportCheckstyle, $reportText, $exitCodeOnFailure);
}

/**
Expand Down
27 changes: 17 additions & 10 deletions src/Lib/Config/InspectConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,28 @@

class InspectConfig
{
private SplFileInfo $coverageFilepath;
/** @var SplFileInfo[] */
private array $coveragesFilepath;
private SplFileInfo $configPath;
private string $baseDir;
private ?string $reportGitlab;
private ?string $reportCheckstyle;
private ?string $reportText;
private bool $exitCodeOnFailure;
private string $baseDir;
private ?string $reportGitlab;
private ?string $reportCheckstyle;
private ?string $reportText;
private bool $exitCodeOnFailure;

/**
* @param SplFileInfo[] $coveragesFilepath
*/
public function __construct(
SplFileInfo $coverageFilepath,
array $coveragesFilepath,
SplFileInfo $configPath,
string $baseDir,
?string $reportGitlab,
?string $reportCheckstyle,
?string $reportText,
bool $exitCodeOnFailure
) {
$this->coverageFilepath = $coverageFilepath;
$this->coveragesFilepath = $coveragesFilepath;
$this->configPath = $configPath;
$this->baseDir = $baseDir;
$this->reportGitlab = $reportGitlab;
Expand All @@ -33,9 +37,12 @@ public function __construct(
$this->exitCodeOnFailure = $exitCodeOnFailure;
}

public function getCoverageFilepath(): SplFileInfo
/**
* @return SplFileInfo[]
*/
public function getCoveragesFilepath(): array
{
return $this->coverageFilepath;
return $this->coveragesFilepath;
}

public function getConfigPath(): SplFileInfo
Expand Down
27 changes: 27 additions & 0 deletions src/Lib/IO/MetricsFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,33 @@ class MetricsFactory
{
private const COVERAGE_PERCENTAGE_PRECISION = 2;

/**
* Get metrics information from coverage.xml files
*
* @param DOMDocument[] $documents
*
* @return FileMetric[]
*/
public static function getFilesMetrics(array $documents): array
{
$metrics = [];

foreach ($documents as $document) {
$foundMetrics = self::getFileMetrics($document);
foreach ($foundMetrics as $metric) {
if (isset($metrics[$metric->getFilepath()])) {
$previousMetric = $metrics[$metric->getFilepath()];
if ($previousMetric->getCoverage() > $metric->getCoverage()) {
continue;
}
}
$metrics[$metric->getFilepath()] = $metric;
}
}

return $metrics;
}

/**
* Get metrics information from coverage.xml file
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1598702199">
<project timestamp="1598702199">
<!-- custom configured files -->
<!-- coverage 60% -->
<file name="/home/workspace/test/case/above-threshold.php">
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="60"
elements="0"
coveredelements="0"/>
</file>
<!-- coverage 50% -->
<file name="/home\workspace/test/case\below-threshold.php">
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="50"
elements="0"
coveredelements="0"/>
</file>

<!-- coverage 90% -->
<file name="\home/workspace/test/case\unnecessary-custom-rule.php">
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="90"
elements="0"
coveredelements="0"/>
</file>

<!-- coverage 90% and uncovered methods -->
<file name="/home/workspace/test/case/uncovered-method.php">
<line num="16" type="method" name="__construct" visibility="public" complexity="1" crap="2" count="0"/>
<line num="30" type="method" name="myMethod" visibility="public" complexity="3" crap="3" count="2"/>
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="90"
elements="0"
coveredelements="0"/>
</file>

<!-- coverage 90% and ignore uncovered methods -->
<file name="/home/workspace/test/case/ignored-uncovered-method.php">
<line num="16" type="method" name="__construct" visibility="public" complexity="1" crap="2" count="0"/>
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="90"
elements="0"
coveredelements="0"/>
</file>

<!-- coverage same test 70%, will be ignored, coverage at 90% in coverage.xml -->
<file name="/home/workspace/test\case/result-same-test.php">
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="70"
elements="0"
coveredelements="0"/>
</file>
</project>
</coverage>
69 changes: 2 additions & 67 deletions tests/Functional/Command/InspectCommand/Data/coverage.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,72 +58,8 @@
elements="0"
coveredelements="0"/>
</file>

<!-- custom configured files -->
<!-- coverage 60% -->
<file name="/home/workspace/test/case/above-threshold.php">
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="60"
elements="0"
coveredelements="0"/>
</file>
<!-- coverage 50% -->
<file name="/home\workspace/test/case\below-threshold.php">
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="50"
elements="0"
coveredelements="0"/>
</file>

<!-- coverage 90% -->
<file name="\home/workspace/test/case\unnecessary-custom-rule.php">
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="90"
elements="0"
coveredelements="0"/>
</file>

<!-- coverage 90% and uncovered methods -->
<file name="/home/workspace/test/case/uncovered-method.php">
<line num="16" type="method" name="__construct" visibility="public" complexity="1" crap="2" count="0"/>
<line num="30" type="method" name="myMethod" visibility="public" complexity="3" crap="3" count="2"/>
<metrics loc="11"
ncloc="11"
classes="0"
methods="0"
coveredmethods="0"
conditionals="0"
coveredconditionals="0"
statements="100"
coveredstatements="90"
elements="0"
coveredelements="0"/>
</file>

<!-- coverage 90% and ignore uncovered methods -->
<file name="/home/workspace/test/case/ignored-uncovered-method.php">
<line num="16" type="method" name="__construct" visibility="public" complexity="1" crap="2" count="0"/>
<!-- coverage same test 90% -->
<file name="/home/workspace/test\case/result-same-test.php">
<metrics loc="11"
ncloc="11"
classes="0"
Expand All @@ -136,6 +72,5 @@
elements="0"
coveredelements="0"/>
</file>

</project>
</coverage>
Loading