[PHP 8.6] Test scaffolding and deprecation-clean audit - #226
Merged
Conversation
Establishes the "FileWith*86.php" stub naming convention together with the "PHP_VERSION_ID >= 80600" guard used for runtime-only assertions, mirroring how the 8.5 stubs are wired into the test suite. - tests/Stub/FileWithClasses86.php: baseline 8.6 stub using only syntax that is already valid and parseable, so per-feature 8.6 stubs can follow later - AbstractTestCase::getFilesToAnalyze(): yields the stub only on PHP 8.6+, because the data providers include_once every stub they yield - tests/Php86ParsingTest.php: proves the wiring - static analysis assertions run on every runtime, native reflection parity is guarded by the version check, so the suite stays green on PHP 8.5 - CLAUDE.md: documents the stub and guard conventions Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sy8BcM8ivUEpu8uVm7wADn
The matrix job name now spells out the PHP version, the dependency set and the experimental flag instead of rendering as an unlabelled tuple, and the outcome of the test step is written to the run summary for experimental rows, whose failures are otherwise hidden by continue-on-error. The 8.6 rows keep continue-on-error until PHP 8.6 reaches GA. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sy8BcM8ivUEpu8uVm7wADn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #220 (part of epic #219).
Establishes the PHP 8.6 test scaffolding, audits the code base against the "Deprecations for PHP 8.6" RFC batch, and makes the experimental 8.6 CI row readable. No library behaviour changes —
src/is untouched.1. Stub / guard scaffolding
tests/Stub/FileWithClasses86.php— baseline 8.6 stub (interface, trait, abstract class, final class with a promoted property and a variadic union-typed method, backed enum, namespaced function and constant). It deliberately uses only syntax that is already valid and parseable, so per-feature 8.6 stubs (PFA, readonly defaults,#[\Override]on constants, …) can be added later as separateFileWith<Feature>86.phpfiles by their own tickets.AbstractTestCase::getFilesToAnalyze()— yields the stub behindPHP_VERSION_ID >= 80600. The guard is load-bearing: the parity data providersinclude_onceevery stub they yield, so a*86.phpstub must never reach an older runtime.tests/Php86ParsingTest.php— proves the wiring in both directions. The static assertions (file parsing, class/enum discovery, methods, parameters, types, constants, traits) run on every runtime, because the engine analyzes sources without loading them; the native-reflection parity test is guarded withPHP_VERSION_ID >= 80600, and the "reflect by name without loading" test is guarded the other way, since the stub is loaded by the parity providers on 8.6.CLAUDE.md— documents both conventions for future contributors.On 8.6 the stub also flows through the whole existing parity matrix, which is where the extra ~1090 tests come from.
2. Deprecation audit
Checked
src/andtests/against the accepted items of the Deprecations for PHP 8.6 RFC:is_double()/is_integer()/is_long()/doubleval(),returnfromfinally,list(),let/is/readonly/_as identifiers,namespaceas a class constant,strcoll(),SORT_LOCALE_STRING,metaphone(),spl_classes(),spl_object_hash(),SplFileObjectCSV methods,mysqli_stmt_init()/mysqli_get_charset(), case-insensitivedefine(),is_a()/is_subclass_of()with a string subject andallow_string = false, objects passed toarray_walk()/array_walk_recursive()/mb_convert_variables()/http_build_query()/deflate_init()/inflate_init(),session_set_save_handler()withoutcreate_sid()/validateId(),ArrayIteratorinheritingArrayObjectimplementations, and the Reflection items (ReflectionProperty::setValue()/setRawValue()with wrong types,ReflectionMethod::invoke()/invokeArgs()with an object for a static method).Result: no hits. Details worth recording:
finallyblocks in the code base (src/Resolver/TypeExpressionResolver.php:96,src/Resolver/NodeExpressionResolver.php:190,tests/ConstantExpressionClosuresTest.php:217) only perform cleanup and do notreturn.is_subclass_of()call (src/Traits/ReflectionClassLikeTrait.php:853) passes an object, not a string, so it is unaffected.ReflectionProperty::setValue()(src/ReflectionProperty.php:763) already normalises its arguments tonull/object before delegating to the parent, so it cannot trigger the new wrong-type deprecation.define()usages in the stubs are two-argument calls.Verified empirically as well: the full suite on 8.6 with
--fail-on-deprecation --fail-on-notice --fail-on-warning --display-deprecationsreports nothing (phpunit.xml.distalready setserror_reporting=E_ALL).3. CI
The experimental 8.6 job was verified against the last master run (run 32818096739): both 8.6 rows install via setup-php and really execute the suite on the beta (
--ignore-platform-req=php+correctly relaxes only the upper platform bound). Nothing was broken, so the changes are cosmetic but do address the "surface the result clearly" part of the ticket:PHPUnit tests (PHP 8.6, highest deps) [experimental]instead ofPHPUnit tests (8.6, highest, ubuntu-latest, true).continue-on-errorreports a failing experimental row as successful in the checks list, the outcome of the test step is now written to the run summary for experimental rows.continue-on-error: trueuntil GA, as required.Local results
vendor/bin/phpunit(PHP 8.5.9)php8.6 vendor/bin/phpunit(PHP 8.6.0beta1)--fail-on-deprecation --fail-on-notice --fail-on-warningvendor/bin/phpstan analyse src --no-progress(level 10)[OK] No errorsFinding for a follow-up (not fixed here — out of scope)
While drafting the stub, an unrelated pre-existing parity gap surfaced in
ReflectionMethod::getPrototype()(src/ReflectionMethod.php:281). It searches the parent class first and does not resolve transitively, so forit returns
Awhile native reflection returnsI. This is not 8.6-specific and would be a behaviour change insrc/, so the stub was written to avoid the construct instead; it deserves its own ticket.🤖 Generated with Claude Code
https://claude.ai/code/session_01Sy8BcM8ivUEpu8uVm7wADn
Generated by Claude Code