Skip to content

Commit cb8e2d0

Browse files
authored
Add phpunit v10 testing support (#2133)
1 parent 15f5d10 commit cb8e2d0

12 files changed

+67
-56
lines changed

.github/workflows/test-unit.yml

+24-24
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@ jobs:
4646
4747
- name: Install PHP dependencies
4848
run: |
49-
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpunit/phpunit johnkary/phpunit-speedtrap --dev; fi
50-
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer --dev; fi
49+
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpunit/phpunit atk4/ergebnis-phpunit-slow-test-detector --dev; fi
50+
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer ergebnis/composer-normalize --dev; fi
5151
if [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpstan/\* behat/\* --dev; fi
5252
composer update --ansi --prefer-dist --no-interaction --no-progress --optimize-autoloader
5353
5454
- name: "Run tests: SQLite (only for Phpunit)"
5555
if: startsWith(matrix.type, 'Phpunit')
5656
run: |
5757
php demos/_demo-data/create-db.php
58-
vendor/bin/phpunit --exclude-group none --no-coverage -v
58+
vendor/bin/phpunit --exclude-group none --no-coverage --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
5959
6060
- name: Check Coding Style (only for CodingStyle)
6161
if: matrix.type == 'CodingStyle'
@@ -133,13 +133,13 @@ jobs:
133133
134134
- name: Install PHP dependencies
135135
run: |
136-
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "Phpunit Lowest" ] && [ "${{ matrix.type }}" != "Phpunit Burn" ]; then composer remove --no-interaction --no-update phpunit/phpunit johnkary/phpunit-speedtrap --dev; fi
137-
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer --dev; fi
136+
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "Phpunit Lowest" ] && [ "${{ matrix.type }}" != "Phpunit Burn" ]; then composer remove --no-interaction --no-update phpunit/phpunit atk4/ergebnis-phpunit-slow-test-detector --dev; fi
137+
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer ergebnis/composer-normalize --dev; fi
138138
if [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpstan/\* behat/\* --dev; fi
139139
if [ -n "$LOG_COVERAGE" ]; then composer require --no-interaction --no-install phpunit/phpcov; fi
140140
composer update --ansi --prefer-dist --no-interaction --no-progress --optimize-autoloader
141141
if [ "${{ matrix.type }}" = "Phpunit Lowest" ]; then composer update --ansi --prefer-dist --prefer-lowest --prefer-stable --no-interaction --no-progress --optimize-autoloader; fi
142-
if [ "${{ matrix.type }}" = "Phpunit Burn" ]; then sed -i 's~ *public function runBare(): void~public function runBare(): void { gc_collect_cycles(); gc_collect_cycles(); $memDiffs = array_fill(0, '"$(if [ \"$GITHUB_EVENT_NAME\" == \"schedule\" ]; then echo 64; else echo 16; fi)"', 0); for ($i = -1; $i < count($memDiffs); ++$i) { $this->_runBare(); gc_collect_cycles(); gc_collect_cycles(); $mem = memory_get_usage(); if ($i !== -1) { $memDiffs[$i] = $mem - $memPrev; } $memPrev = $mem; rsort($memDiffs); if (array_sum($memDiffs) >= 4096 * 1024 || $memDiffs[2] > 0) { $this->onNotSuccessfulTest(new AssertionFailedError("Memory leak detected! (" . implode(" + ", array_map(static fn ($v) => number_format($v / 1024, 3, ".", " "), array_filter($memDiffs))) . " KB, " . ($i + 2) . " iterations)")); } } } private function _runBare(): void~' vendor/phpunit/phpunit/src/Framework/TestCase.php && cat vendor/phpunit/phpunit/src/Framework/TestCase.php | grep '_runBare('; fi
142+
if [ "${{ matrix.type }}" = "Phpunit Burn" ]; then sed -i 's~public function runBare(): void~public function runBare(): void { gc_collect_cycles(); gc_collect_cycles(); $memDiffs = array_fill(0, '"$(if [ \"$GITHUB_EVENT_NAME\" == \"schedule\" ]; then echo 64; else echo 16; fi)"', 0); for ($i = -1; $i < count($memDiffs); ++$i) { $this->_runBare(); gc_collect_cycles(); gc_collect_cycles(); $mem = memory_get_usage(); if ($i !== -1) { $memDiffs[$i] = $mem - $memPrev; } $memPrev = $mem; rsort($memDiffs); if (array_sum($memDiffs) >= 4096 * 1024 || $memDiffs[2] > 0) { $this->onNotSuccessfulTest(new AssertionFailedError("Memory leak detected! (" . implode(" + ", array_map(static fn ($v) => number_format($v / 1024, 3, ".", " "), array_filter($memDiffs))) . " KB, " . ($i + 2) . " iterations)")); } } } private function _runBare(): void~' vendor/phpunit/phpunit/src/Framework/TestCase.php && cat vendor/phpunit/phpunit/src/Framework/TestCase.php | grep '_runBare('; fi
143143
144144
- name: Init
145145
run: |
@@ -152,31 +152,31 @@ jobs:
152152
- name: "Run tests: SQLite"
153153
run: |
154154
php demos/_demo-data/create-db.php
155-
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) -v
155+
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
156156
if [ -n "$LOG_COVERAGE" ]; then mv coverage/phpunit.cov coverage/phpunit-sqlite.cov; fi
157157
158-
- name: "Run tests: MySQL"
159-
if: success() || failure()
158+
- name: "Run tests: MySQL (only for cron)"
159+
if: (success() || failure()) && github.event_name == 'schedule'
160160
env:
161161
DB_DSN: "mysql:host=mysql;dbname=atk4_test"
162162
DB_USER: atk4_test_user
163163
DB_PASSWORD: atk4_pass
164164
run: |
165165
sed -E "s~(\\\$db = new.+Persistence\\\\Sql)\(.+\);~\\1('$DB_DSN', '$DB_USER', '$DB_PASSWORD');~g" -i demos/db.default.php
166166
php demos/_demo-data/create-db.php
167-
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) -v
167+
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
168168
if [ -n "$LOG_COVERAGE" ]; then mv coverage/phpunit.cov coverage/phpunit-mysql.cov; fi
169169
170-
- name: "Run tests: MariaDB (only for cron)"
171-
if: (success() || failure()) && github.event_name == 'schedule'
170+
- name: "Run tests: MariaDB"
171+
if: success() || failure()
172172
env:
173173
DB_DSN: "mysql:host=mariadb;dbname=atk4_test"
174174
DB_USER: atk4_test_user
175175
DB_PASSWORD: atk4_pass
176176
run: |
177177
sed -E "s~(\\\$db = new.+Persistence\\\\Sql)\(.+\);~\\1('$DB_DSN', '$DB_USER', '$DB_PASSWORD');~g" -i demos/db.default.php
178178
php demos/_demo-data/create-db.php
179-
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) -v
179+
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
180180
if [ -n "$LOG_COVERAGE" ]; then mv coverage/phpunit.cov coverage/phpunit-mariadb.cov; fi
181181
182182
- name: "Run tests: PostgreSQL (only for cron)"
@@ -188,7 +188,7 @@ jobs:
188188
run: |
189189
sed -E "s~(\\\$db = new.+Persistence\\\\Sql)\(.+\);~\\1('$DB_DSN', '$DB_USER', '$DB_PASSWORD');~g" -i demos/db.default.php
190190
php demos/_demo-data/create-db.php
191-
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) -v
191+
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
192192
if [ -n "$LOG_COVERAGE" ]; then mv coverage/phpunit.cov coverage/phpunit-postgres.cov; fi
193193
194194
- name: "Run tests: MSSQL (only for cron)"
@@ -200,20 +200,20 @@ jobs:
200200
run: |
201201
sed -E "s~(\\\$db = new.+Persistence\\\\Sql)\(.+\);~\\1('$DB_DSN', '$DB_USER', '$DB_PASSWORD');~g" -i demos/db.default.php
202202
php demos/_demo-data/create-db.php
203-
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) -v
203+
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
204204
if [ -n "$LOG_COVERAGE" ]; then mv coverage/phpunit.cov coverage/phpunit-mssql.cov; fi
205205
206206
- name: "Run tests: Oracle (only for cron)"
207207
if: (success() || failure()) && github.event_name == 'schedule'
208208
env:
209-
DB_DSN: "oci:dbname=oracle/xe"
209+
DB_DSN: "oci:dbname=oracle/free"
210210
DB_USER: system
211211
DB_PASSWORD: atk4_pass
212212
NLS_LANG: AMERICAN_AMERICA.AL32UTF8
213213
run: |
214214
sed -E "s~(\\\$db = new.+Persistence\\\\Sql)\(.+\);~\\1('$DB_DSN', '$DB_USER', '$DB_PASSWORD');~g" -i demos/db.default.php
215215
php demos/_demo-data/create-db.php
216-
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) -v
216+
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
217217
if [ -n "$LOG_COVERAGE" ]; then mv coverage/phpunit.cov coverage/phpunit-oracle.cov; fi
218218
219219
- name: Upload coverage logs 1/2 (only for latest Phpunit)
@@ -353,8 +353,8 @@ jobs:
353353
354354
- name: Install PHP dependencies
355355
run: |
356-
composer remove --no-interaction --no-update phpunit/phpunit johnkary/phpunit-speedtrap --dev
357-
composer remove --no-interaction --no-update friendsofphp/php-cs-fixer --dev
356+
composer remove --no-interaction --no-update phpunit/phpunit atk4/ergebnis-phpunit-slow-test-detector --dev
357+
composer remove --no-interaction --no-update friendsofphp/php-cs-fixer ergebnis/composer-normalize --dev
358358
composer remove --no-interaction --no-update phpstan/\* --dev
359359
if [ -n "$LOG_COVERAGE" ]; then composer require --no-interaction --no-install phpunit/phpcov; fi
360360
composer update --ansi --prefer-dist --no-interaction --no-progress --optimize-autoloader
@@ -383,8 +383,8 @@ jobs:
383383
php demos/_demo-data/create-db.php
384384
vendor/bin/behat -vv --config behat.yml.dist
385385
386-
- name: "Run tests: MySQL (only for coverage or cron)"
387-
if: (success() || failure()) && (env.LOG_COVERAGE || github.event_name == 'schedule')
386+
- name: "Run tests: MySQL (only for cron)"
387+
if: (success() || failure()) && github.event_name == 'schedule'
388388
env:
389389
DB_DSN: "mysql:host=mysql;dbname=atk4_test"
390390
DB_USER: atk4_test_user
@@ -394,8 +394,8 @@ jobs:
394394
php demos/_demo-data/create-db.php
395395
vendor/bin/behat -vv --config behat.yml.dist
396396
397-
- name: "Run tests: MariaDB (only for cron)"
398-
if: (success() || failure()) && github.event_name == 'schedule'
397+
- name: "Run tests: MariaDB (only for coverage or cron)"
398+
if: (success() || failure()) && (env.LOG_COVERAGE || github.event_name == 'schedule')
399399
env:
400400
DB_DSN: "mysql:host=mariadb;dbname=atk4_test"
401401
DB_USER: atk4_test_user
@@ -430,7 +430,7 @@ jobs:
430430
- name: "Run tests: Oracle (only for cron)"
431431
if: (success() || failure()) && github.event_name == 'schedule'
432432
env:
433-
DB_DSN: "oci:dbname=oracle/xe"
433+
DB_DSN: "oci:dbname=oracle/free"
434434
DB_USER: system
435435
DB_PASSWORD: atk4_pass
436436
NLS_LANG: AMERICAN_AMERICA.AL32UTF8

composer.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,17 @@
6868
},
6969
"require-dev": {
7070
"atk4/behat-mink-selenium2-driver": "^1.6.2",
71+
"atk4/ergebnis-phpunit-slow-test-detector": "^2.4",
7172
"behat/mink-extension": "^2.3.1",
7273
"ergebnis/composer-normalize": "^2.13",
7374
"friendsofphp/php-cs-fixer": "^3.0",
7475
"fzaninotto/faker": "^1.6",
7576
"guzzlehttp/guzzle": "^7.3",
76-
"johnkary/phpunit-speedtrap": "^3.3",
7777
"phpstan/extension-installer": "^1.1",
7878
"phpstan/phpstan": "^1.0",
7979
"phpstan/phpstan-deprecation-rules": "^1.0",
8080
"phpstan/phpstan-strict-rules": "^1.3",
81-
"phpunit/phpunit": "^9.5.5",
81+
"phpunit/phpunit": "^9.5.5 || ^10.0",
8282
"symfony/process": "^4.4.30 || ^5.3.7 || ^6.0"
8383
},
8484
"conflict": {

phpstan.neon.dist

+10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ parameters:
1616
- '~^Only booleans are allowed in .+, .+ given( on the (left|right) side)?\.~'
1717
- '~^Variable (static )?(property access|method call) on .+\.~'
1818

19+
# remove once PHPUnit 9.x support is removed
20+
-
21+
path: 'tests/DemosTest.php'
22+
message: '~^Access to constant (STATUS_PASSED|STATUS_INCOMPLETE|STATUS_SKIPPED) on an unknown class PHPUnit\\Runner\\BaseTestRunner\.$~'
23+
count: 3
24+
-
25+
path: 'tests/DemosTest.php'
26+
message: '~^Call to an undefined method Atk4\\Ui\\Tests\\DemosTest::(getName|getStatus)\(\)\.$~'
27+
count: 4
28+
1929
# TODO these rules are generated, this ignores should be fixed in the code
2030
# for level = 2
2131
-

phpunit.xml.dist

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<phpunit bootstrap="vendor/autoload.php" printerClass="Atk4\Core\Phpunit\ResultPrinter" colors="true">
1+
<phpunit bootstrap="vendor/autoload.php" colors="true">
22
<testsuites>
33
<testsuite name="tests">
44
<directory>tests</directory>
@@ -16,17 +16,19 @@
1616
<group>require_session</group>
1717
</exclude>
1818
</groups>
19-
<listeners>
20-
<listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
21-
</listeners>
22-
<coverage>
19+
<extensions>
20+
<bootstrap class="Ergebnis\PHPUnit\SlowTestDetector\Extension" />
21+
</extensions>
22+
<source>
2323
<include>
2424
<directory>src</directory>
2525
<directory>tests</directory>
2626
</include>
2727
<exclude>
2828
<directory>src/Behat</directory>
2929
</exclude>
30+
</source>
31+
<coverage>
3032
<report>
3133
<php outputFile="coverage/phpunit.cov" />
3234
</report>

src/App.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public function __construct(array $defaults = [])
182182
if ($this->catchExceptions) {
183183
set_exception_handler(\Closure::fromCallable([$this, 'caughtException']));
184184
set_error_handler(static function (int $severity, string $msg, string $file, int $line): bool {
185-
if ((error_reporting() & ~(\PHP_MAJOR_VERSION >= 8 ? 4437 : 0)) === 0) {
185+
if ((error_reporting() & ~(\PHP_MAJOR_VERSION >= 8 ? (\E_ERROR | \E_PARSE | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR | \E_RECOVERABLE_ERROR) : 0)) === 0) {
186186
$isFirstFrame = true;
187187
foreach (array_slice(debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 10), 1) as $frame) {
188188
// allow to suppress any warning outside Atk4

src/Behat/CoverageUtil.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,18 @@ public static function startFromPhpunitConfig(string $phpunitConfigDir): void
3434
{
3535
$filter = new Filter();
3636

37-
$phpunitCoverageConfig = simplexml_load_file($phpunitConfigDir . '/phpunit.xml.dist')->coverage;
37+
$phpunitCoverageConfig = simplexml_load_file($phpunitConfigDir . '/phpunit.xml.dist')->source;
3838
foreach ($phpunitCoverageConfig->include->directory ?? [] as $path) {
39-
$filter->includeDirectory($phpunitConfigDir . '/' . $path);
39+
$filter->includeDirectory($phpunitConfigDir . '/' . $path); // @phpstan-ignore-line
4040
}
4141
foreach ($phpunitCoverageConfig->include->file ?? [] as $path) {
4242
$filter->includeFile($phpunitConfigDir . '/' . $path);
4343
}
4444
foreach ($phpunitCoverageConfig->exclude->directory ?? [] as $path) {
45-
$filter->excludeDirectory($phpunitConfigDir . '/' . $path);
45+
$filter->excludeDirectory($phpunitConfigDir . '/' . $path); // @phpstan-ignore-line
4646
}
4747
foreach ($phpunitCoverageConfig->exclude->file ?? [] as $path) {
48-
$filter->excludeFile($phpunitConfigDir . '/' . $path);
48+
$filter->excludeFile($phpunitConfigDir . '/' . $path); // @phpstan-ignore-line
4949
}
5050

5151
static::start($filter);

tests/AppTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public function testEmptyRequestPathException(): void
122122
$this->createApp(['request' => $request]);
123123
}
124124

125-
public function provideUrlCases(): iterable
125+
public static function provideUrlCases(): iterable
126126
{
127127
foreach (['/', '/page.html', '/d/', '/0/index.php'] as $requestPage) {
128128
yield [$requestPage, [], ['x'], [], 'x.php'];

tests/DemosHttpTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public function testDemoLateOutputError(string $urlTrigger, string $expectedOutp
135135
self::assertSame($expectedOutput, $response->getBody()->getContents());
136136
}
137137

138-
public function provideDemoLateOutputErrorCases(): iterable
138+
public static function provideDemoLateOutputErrorCases(): iterable
139139
{
140140
$hOutput = "\n" . '!! FATAL UI ERROR: Headers already sent, more headers cannot be set at this stage !!' . "\n";
141141
$oOutput = 'unmanaged output' . "\n" . '!! FATAL UI ERROR: Unexpected output detected !!' . "\n";

0 commit comments

Comments
 (0)