Skip to content

Commit 4a39279

Browse files
Closes #6297
1 parent 11e5eca commit 4a39279

File tree

13 files changed

+257
-1
lines changed

13 files changed

+257
-1
lines changed

ChangeLog-10.5.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes of the PHPUnit 10.5 release series are documented in this fi
44

55
## [10.5.49] - 2025-MM-DD
66

7+
### Added
8+
9+
* [#6297](https://github.com/sebastianbergmann/phpunit/issues/6297): `--check-php-configuration` CLI option for checking whether PHP is configured for testing
10+
711
### Fixed
812

913
* Errors due to invalid data provided using `#[TestWith]` or `#[TestWithJson]` attributes are now properly reported

phpunit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
<testsuite name="end-to-end">
1818
<directory suffix=".phpt">tests/end-to-end/baseline</directory>
19+
<directory suffix=".phpt">tests/end-to-end/check-php-version</directory>
1920
<directory suffix=".phpt">tests/end-to-end/cli</directory>
2021
<directory suffix=".phpt">tests/end-to-end/code-coverage</directory>
2122
<directory suffix=".phpt">tests/end-to-end/data-provider</directory>

src/TextUI/Application.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
use PHPUnit\TextUI\CliArguments\Exception as ArgumentsException;
5353
use PHPUnit\TextUI\CliArguments\XmlConfigurationFileFinder;
5454
use PHPUnit\TextUI\Command\AtLeastVersionCommand;
55+
use PHPUnit\TextUI\Command\CheckPhpConfigurationCommand;
5556
use PHPUnit\TextUI\Command\GenerateConfigurationCommand;
5657
use PHPUnit\TextUI\Command\ListGroupsCommand;
5758
use PHPUnit\TextUI\Command\ListTestsAsTextCommand;
@@ -446,6 +447,10 @@ private function executeCommandsThatOnlyRequireCliConfiguration(CliConfiguration
446447
$this->execute(new ShowVersionCommand);
447448
}
448449

450+
if ($cliConfiguration->checkPhpConfiguration()) {
451+
$this->execute(new CheckPhpConfigurationCommand);
452+
}
453+
449454
if ($cliConfiguration->checkVersion()) {
450455
$this->execute(new VersionCheckCommand(new PhpDownloader, Version::majorVersionNumber(), Version::id()));
451456
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\TextUI\Command;
11+
12+
use const PHP_EOL;
13+
use function extension_loaded;
14+
use function ini_get;
15+
use function max;
16+
use function sprintf;
17+
use function strlen;
18+
use PHPUnit\Runner\Version;
19+
20+
/**
21+
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
22+
*
23+
* @internal This class is not covered by the backward compatibility promise for PHPUnit
24+
*/
25+
final readonly class CheckPhpConfigurationCommand implements Command
26+
{
27+
/**
28+
* @var non-empty-array<non-empty-string, array{expectedValue: non-empty-string, valueForConfiguration: non-empty-string, requiredExtensions: list<non-empty-string>}>
29+
*/
30+
private const array SETTINGS = [
31+
'display_errors' => [
32+
'expectedValue' => '1',
33+
'valueForConfiguration' => 'On',
34+
'requiredExtensions' => [],
35+
],
36+
'display_startup_errors' => [
37+
'expectedValue' => '1',
38+
'valueForConfiguration' => 'On',
39+
'requiredExtensions' => [],
40+
],
41+
'error_reporting' => [
42+
'expectedValue' => '-1',
43+
'valueForConfiguration' => '-1',
44+
'requiredExtensions' => [],
45+
],
46+
'xdebug.show_exception_trace' => [
47+
'expectedValue' => '0',
48+
'valueForConfiguration' => '0',
49+
'requiredExtensions' => ['xdebug'],
50+
],
51+
'zend.assertions' => [
52+
'expectedValue' => '1',
53+
'valueForConfiguration' => '1',
54+
'requiredExtensions' => [],
55+
],
56+
'assert.exception' => [
57+
'expectedValue' => '1',
58+
'valueForConfiguration' => '1',
59+
'requiredExtensions' => [],
60+
],
61+
'memory_limit' => [
62+
'expectedValue' => '-1',
63+
'valueForConfiguration' => '-1',
64+
'requiredExtensions' => [],
65+
],
66+
];
67+
68+
public function execute(): Result
69+
{
70+
$lines = [];
71+
$shellExitCode = 0;
72+
73+
foreach (self::SETTINGS as $name => $setting) {
74+
foreach ($setting['requiredExtensions'] as $extension) {
75+
if (!extension_loaded($extension)) {
76+
continue 2;
77+
}
78+
}
79+
80+
if (ini_get($name) === $setting['expectedValue']) {
81+
$check = 'ok';
82+
} else {
83+
$check = 'not ok';
84+
$shellExitCode = 1;
85+
}
86+
87+
$lines[] = [
88+
sprintf(
89+
'%s = %s',
90+
$name,
91+
$setting['valueForConfiguration'],
92+
),
93+
$check,
94+
];
95+
}
96+
97+
$maxLength = 0;
98+
99+
foreach ($lines as $line) {
100+
$maxLength = max($maxLength, strlen($line[0]));
101+
}
102+
103+
$buffer = sprintf(
104+
'Checking whether PHP is configured according to https://docs.phpunit.de/en/%s/installation.html#configuring-php-for-development' . PHP_EOL . PHP_EOL,
105+
Version::series(),
106+
);
107+
108+
foreach ($lines as $line) {
109+
$buffer .= sprintf(
110+
'%-' . $maxLength . 's ... %s' . PHP_EOL,
111+
$line[0],
112+
$line[1],
113+
);
114+
}
115+
116+
return Result::from($buffer, $shellExitCode);
117+
}
118+
}

src/TextUI/Configuration/Cli/Builder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ final class Builder
3838
'cache-directory=',
3939
'cache-result-file=',
4040
'check-version',
41+
'check-php-configuration',
4142
'colors==',
4243
'columns=',
4344
'configuration=',
@@ -180,6 +181,7 @@ public function fromParameters(array $parameters): Configuration
180181
$cacheDirectory = null;
181182
$cacheResult = null;
182183
$cacheResultFile = null;
184+
$checkPhpConfiguration = false;
183185
$checkVersion = false;
184186
$colors = null;
185187
$columns = null;
@@ -997,6 +999,11 @@ public function fromParameters(array $parameters): Configuration
997999

9981000
break;
9991001

1002+
case '--check-php-configuration':
1003+
$checkPhpConfiguration = true;
1004+
1005+
break;
1006+
10001007
case '--check-version':
10011008
$checkVersion = true;
10021009

@@ -1095,6 +1102,7 @@ public function fromParameters(array $parameters): Configuration
10951102
$cacheDirectory,
10961103
$cacheResult,
10971104
$cacheResultFile,
1105+
$checkPhpConfiguration,
10981106
$checkVersion,
10991107
$colors,
11001108
$columns,

src/TextUI/Configuration/Cli/Configuration.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ final class Configuration
142142
* @psalm-param list<non-empty-string> $arguments
143143
* @psalm-param ?non-empty-list<non-empty-string> $testSuffixes
144144
*/
145-
public function __construct(array $arguments, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, ?string $cacheResultFile, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, ?string $coverageCacheDirectory, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnAllIssues, ?bool $failOnDeprecation, ?bool $failOnPhpunitDeprecation, ?bool $failOnPhpunitWarning, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $doNotFailOnDeprecation, ?bool $doNotFailOnPhpunitDeprecation, ?bool $doNotFailOnPhpunitWarning, ?bool $doNotFailOnEmptyTestSuite, ?bool $doNotFailOnIncomplete, ?bool $doNotFailOnNotice, ?bool $doNotFailOnRisky, ?bool $doNotFailOnSkipped, ?bool $doNotFailOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, ?string $generateBaseline, ?string $useBaseline, bool $ignoreBaseline, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnAllIssues, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnPhpunitDeprecations, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $printerTestDox, bool $debug)
145+
public function __construct(array $arguments, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, ?string $cacheResultFile, bool $checkPhpConfiguration, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, ?string $coverageCacheDirectory, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnAllIssues, ?bool $failOnDeprecation, ?bool $failOnPhpunitDeprecation, ?bool $failOnPhpunitWarning, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $doNotFailOnDeprecation, ?bool $doNotFailOnPhpunitDeprecation, ?bool $doNotFailOnPhpunitWarning, ?bool $doNotFailOnEmptyTestSuite, ?bool $doNotFailOnIncomplete, ?bool $doNotFailOnNotice, ?bool $doNotFailOnRisky, ?bool $doNotFailOnSkipped, ?bool $doNotFailOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, ?string $generateBaseline, ?string $useBaseline, bool $ignoreBaseline, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnAllIssues, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnPhpunitDeprecations, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $printerTestDox, bool $debug)
146146
{
147147
$this->arguments = $arguments;
148148
$this->atLeastVersion = $atLeastVersion;
@@ -153,6 +153,7 @@ public function __construct(array $arguments, ?string $atLeastVersion, ?bool $ba
153153
$this->cacheDirectory = $cacheDirectory;
154154
$this->cacheResult = $cacheResult;
155155
$this->cacheResultFile = $cacheResultFile;
156+
$this->checkPhpConfiguration = $checkPhpConfiguration;
156157
$this->checkVersion = $checkVersion;
157158
$this->colors = $colors;
158159
$this->columns = $columns;
@@ -430,6 +431,11 @@ public function cacheResultFile(): string
430431
return $this->cacheResultFile;
431432
}
432433

434+
public function checkPhpConfiguration(): bool
435+
{
436+
return $this->checkPhpConfiguration;
437+
}
438+
433439
public function checkVersion(): bool
434440
{
435441
return $this->checkVersion;

src/TextUI/Help.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ private function elements(): array
310310
['arg' => '--version', 'desc' => 'Prints the version and exits'],
311311
['arg' => '--atleast-version <min>', 'desc' => 'Checks that version is greater than <min> and exits'],
312312
['arg' => '--check-version', 'desc' => 'Checks whether PHPUnit is the latest version and exits'],
313+
['arg' => '--check-php-configuration', 'desc' => 'Checks whether PHP configuration follows best practices'],
313314
];
314315

315316
return $elements;

tests/end-to-end/_files/output-cli-help-color.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,6 @@
215215
<min> and exits
216216
--check-version  Checks whether PHPUnit is the latest
217217
version and exits
218+
--check-php-configuration  Checks whether PHP configuration follows
219+
best practices
218220

tests/end-to-end/_files/output-cli-usage.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,4 @@ Miscellaneous:
142142
--version Prints the version and exits
143143
--atleast-version <min> Checks that version is greater than <min> and exits
144144
--check-version Checks whether PHPUnit is the latest version and exits
145+
--check-php-configuration Checks whether PHP configuration follows best practices
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
phpunit --check-php-configuration (failure, Xdebug loaded)
3+
--SKIPIF--
4+
<?php declare(strict_types=1);
5+
if (!extension_loaded('xdebug')) {
6+
print 'skip: Extension Xdebug must be loaded.';
7+
}
8+
--FILE--
9+
<?php
10+
$_SERVER['argv'][] = '--check-php-configuration';
11+
12+
require_once __DIR__ . '/../../bootstrap.php';
13+
14+
ini_set('display_errors', 0);
15+
16+
(new PHPUnit\TextUI\Application)->run($_SERVER['argv']);
17+
?>
18+
--EXPECTF--
19+
PHPUnit %s by Sebastian Bergmann and contributors.
20+
21+
Checking whether PHP is configured according to https://docs.phpunit.de/en/%s/installation.html#configuring-php-for-development
22+
23+
display_errors = On ... not ok
24+
display_startup_errors = On ... ok
25+
error_reporting = -1 ... ok
26+
xdebug.show_exception_trace = 0 ... ok
27+
zend.assertions = 1 ... ok
28+
assert.exception = 1 ... ok
29+
memory_limit = -1 ... ok

0 commit comments

Comments
 (0)