Skip to content
New issue

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

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

Already on GitHub? # to your account

Strict code coverage tracing with @covers annotations #509

Merged
merged 19 commits into from
Aug 19, 2020
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ static-analysis: vendor

.PHONY: test
test: vendor
php -d zend.assertions=1 vendor/bin/phpunit
php -d zend.assertions=1 vendor/bin/phpunit ${arg}
13 changes: 6 additions & 7 deletions bin/phpunit-wrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,19 @@
exit($lastExitCode);
}

$command = rtrim($command);
if ($command === 'EXIT') {
if ($command === \ParaTest\Runners\PHPUnit\Worker\WrapperWorker::COMMAND_EXIT) {
echo "EXITED\n";
exit($lastExitCode);
}

$arguments = unserialize($command);
$command = implode(' ', $arguments);
echo "Executing: $command\n";
echo "Executing: {$command}\n";

$info = [];
$info[] = 'Time: ' . (new DateTime())->format(DateTime::RFC3339);
$info[] = "Iteration: $i";
$info[] = "Command: $command";
$info[] = 'Time: ' . (new DateTimeImmutable())->format(DateTime::RFC3339);
$info[] = "Iteration: {$i}";
$info[] = "Command: {$command}";
$info[] = PHP_EOL;
$infoText = implode(PHP_EOL, $info) . PHP_EOL;
$logInfo($infoText);
Expand All @@ -73,5 +72,5 @@

$logInfo($infoText);

echo "FINISHED\n";
echo \ParaTest\Runners\PHPUnit\Worker\WrapperWorker::COMMAND_FINISHED;
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
"ext-pdo": "*",
"ext-reflection": "*",
"ext-simplexml": "*",
"brianium/habitat": "^1.0",
"phpunit/php-code-coverage": "^9.1.2",
"phpunit/php-file-iterator": "^3.0",
"phpunit/php-timer": "^5.0",
"phpunit/phpunit": "^9.3.5",
"sebastian/environment": "^5.1",
"symfony/console": "^4.4 || ^5.1",
"symfony/process": "^4.4 || ^5.1"
},
Expand All @@ -42,6 +42,7 @@
"phpstan/phpstan-phpunit": "^0.12.16",
"phpstan/phpstan-strict-rules": "^0.12.4",
"squizlabs/php_codesniffer": "^3.5.6",
"symfony/filesystem": "^5.1.3",
"thecodingmachine/phpstan-strict-rules": "^0.12.0",
"vimeo/psalm": "^3.12.2"
},
Expand Down
21 changes: 16 additions & 5 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,14 @@ parameters:
message: "#^Should not use function \"proc_open\", please change the code\\.$#"
count: 1
path: src/Runners/PHPUnit/Worker/BaseWorker.php
-
message: "#^Should not use function \"proc_open\", please change the code\\.$#"
count: 1
path: test/Functional/Runners/PHPUnit/WorkerTest.php

# Known errors
- "#^Variable property access on .+$#"
- "#^Variable method call on .+$#"
- "#^.+ has no value type specified in iterable type Symfony\\\\Component\\\\Process\\\\Process\\.$#"
-
message: "#^Method ParaTest\\\\Tests\\\\TestBase\\:\\:setUpTest\\(\\) is not final, but since the containing class is abstract, it should be\\.$#"
count: 1
path: test/TestBase.php
-
message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#"
count: 2
Expand Down Expand Up @@ -120,6 +119,18 @@ parameters:
message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with false will always evaluate to false\\.$#"
count: 1
path: test/fixtures/wrapper-runner-exit-code-tests/FailureTest.php
-
message: "#^Offset 'TEST_TOKEN' does not exist on array\\('PARATEST' \\=\\> 1, \\?'TEST_TOKEN' \\=\\> int, \\?'UNIQUE_TEST_TOKEN' \\=\\> string\\)\\.$#"
count: 1
path: test/Unit/Runners/PHPUnit/OptionsTest.php
-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertIsString\\(\\) with string will always evaluate to true\\.$#"
count: 1
path: test/Unit/Runners/PHPUnit/OptionsTest.php
-
message: "#^Offset 'UNIQUE_TEST_TOKEN' does not exist on array\\('PARATEST' \\=\\> 1, \\?'UNIQUE_TEST_TOKEN' \\=\\> string, 'TEST_TOKEN' \\=\\> int\\)\\.$#"
count: 1
path: test/Unit/Runners/PHPUnit/OptionsTest.php

# Level 7
-
Expand Down
62 changes: 13 additions & 49 deletions src/Coverage/CoverageMerger.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,26 @@

namespace ParaTest\Coverage;

use RuntimeException;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\ProcessedCodeCoverageData;
use SebastianBergmann\Environment\Runtime;

use function array_map;
use function array_slice;
use function assert;
use function extension_loaded;
use function filesize;
use function function_exists;
use function ini_get;
use function is_array;
use function is_file;
use function unlink;

use const PHP_SAPI;

final class CoverageMerger
{
/** @var CodeCoverage|null */
private $coverage;
/** @var int */
private $test_limit;
private $testLimit;

public function __construct(int $test_limit = 0)
public function __construct(int $testLimit)
{
$this->test_limit = $test_limit;
$this->testLimit = $testLimit;
}

private function addCoverage(CodeCoverage $coverage): void
Expand All @@ -48,29 +41,18 @@ private function addCoverage(CodeCoverage $coverage): void
* Adds the coverage contained in $coverageFile and deletes the file afterwards.
*
* @param string $coverageFile Code coverage file
*
* @throws RuntimeException When coverage file is empty.
*/
public function addCoverageFromFile(?string $coverageFile): void
public function addCoverageFromFile(string $coverageFile): void
{
if ($coverageFile === null || ! is_file($coverageFile)) {
return;
}

if (filesize($coverageFile) === 0) {
if (! is_file($coverageFile) || filesize($coverageFile) === 0) {
$extra = 'This means a PHPUnit process has crashed.';

$xdebug = function_exists('xdebug_get_code_coverage');
$phpdbg = PHP_SAPI === 'phpdbg';
$pcov = extension_loaded('pcov') && (bool) ini_get('pcov.enabled');

if (! $xdebug && ! $phpdbg && ! $pcov) {
if (! (new Runtime())->canCollectCodeCoverage()) {
// @codeCoverageIgnoreStart
$extra = 'No coverage driver found! Enable one of Xdebug, PHPDBG or PCOV for coverage.';
// @codeCoverageIgnoreEnd
}

throw new RuntimeException(
"Coverage file $coverageFile is empty. " . $extra
);
throw new EmptyCoverageFileException("Coverage file {$coverageFile} is empty. " . $extra);
}

/** @psalm-suppress UnresolvableInclude **/
Expand All @@ -79,40 +61,22 @@ public function addCoverageFromFile(?string $coverageFile): void
unlink($coverageFile);
}

/**
* Get coverage report generator.
*/
public function getReporter(): CoverageReporterInterface
{
assert($this->coverage !== null);

return new CoverageReporter($this->coverage);
}

/**
* Get CodeCoverage object.
*/
public function getCodeCoverageObject(): ?CodeCoverage
{
return $this->coverage;
}

private function limitCoverageTests(CodeCoverage $coverage): void
{
if ($this->test_limit === 0) {
if ($this->testLimit === 0) {
return;
}

$testLimit = $this->test_limit;
$testLimit = $this->testLimit;
$data = $coverage->getData(true);
$newData = array_map(
static function (array $lines) use ($testLimit): array {
/** @psalm-suppress MissingClosureReturnType **/
return array_map(static function ($value) use ($testLimit) {
if (! is_array($value)) {
return $value;
}

return array_map(static function (array $value) use ($testLimit): array {
return array_slice($value, 0, $testLimit);
}, $lines);
},
Expand Down
2 changes: 1 addition & 1 deletion src/Coverage/CoverageReporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport;
use SebastianBergmann\CodeCoverage\Version;

final class CoverageReporter implements CoverageReporterInterface
final class CoverageReporter
{
/** @var CodeCoverage */
private $coverage;
Expand Down
48 changes: 0 additions & 48 deletions src/Coverage/CoverageReporterInterface.php

This file was deleted.

11 changes: 11 additions & 0 deletions src/Coverage/EmptyCoverageFileException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace ParaTest\Coverage;

use RuntimeException;

final class EmptyCoverageFileException extends RuntimeException
{
}
Loading