Skip to content

Increase test coverage toward 90% (no file below 80%) - #659

Merged
lisachenko merged 14 commits into
masterfrom
claude/code-coverage-90-percent-me7ttt
Sep 3, 2026
Merged

Increase test coverage toward 90% (no file below 80%)#659
lisachenko merged 14 commits into
masterfrom
claude/code-coverage-90-percent-me7ttt

Conversation

@lisachenko

@lisachenko lisachenko commented Sep 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Baseline overall line coverage was 85.36%, with 27 source files under 80% (4 of them at 0%).
  • Final: overall line coverage is 95.76%, and every source file is ≥80% covered (lowest is CacheWarmer.php at 82.93%).
  • Added/extended ~50 test files across Aop/Framework, Aop/Pointcut, Aop/Support, Core, Console/Command, Proxy, Proxy/Generator, Proxy/Part, Instrument/Transformer, and Lang/Attribute, following the repo's existing conventions (virtual filesystem for FS tests, @phpstan-ignore for provable-by-design runtime double-checks, etc.).
  • One small production fix: WeavingTransformer::processFunctions() wrote the function-proxy cache file with LOCK_EX unconditionally, which PHP rejects on any non-file:// stream-wrapper path. saveProxyToCache() a few lines below already guards against this; applied the same guard, with a new test exercising the actual generation path.
  • No other production behavior changed — this PR is tests only, aside from the one-line fix above.

Test plan

  • All previously-passing tests continue to pass (2799 tests / 10 skipped, up from the 2666/10 baseline)
  • XDEBUG_MODE=coverage php8.4 vendor/bin/phpunit --coverage-text shows overall line coverage ≥90% (95.76%)
  • No individual source file under src/ has line coverage below 80%
  • No risky/incomplete tests (phpunit.xml.dist enforces failOnRisky, failOnWarning, failOnNotice, failOnDeprecation)
  • phpstan analyze --memory-limit=512M (level 10) is clean across src/ and tests/
  • php-cs-fixer check --diff (PER-CS) is clean

🤖 Generated with Claude Code

https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH

…assFieldAccess

Part of raising code coverage across src/. More files in progress.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
…r, StaticInitializationJoinpoint

Part of raising code coverage across src/. More files in progress.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Part of raising code coverage across src/. More files in progress.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Part of raising code coverage across src/. More files in progress
(tests/Console/Command/BaseAspectCommandTest.php intentionally left
uncommitted: still being written, currently has a risky test).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.00%. Comparing base (3cbf646) to head (fbff93d).

Additional details and impacted files
@@              Coverage Diff              @@
##             master     #659       +/-   ##
=============================================
+ Coverage     85.40%   96.00%   +10.60%     
- Complexity     1636     1637        +1     
=============================================
  Files            99       99               
  Lines          4509     4510        +1     
=============================================
+ Hits           3851     4330      +479     
+ Misses          658      180      -478     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Real fixes: correct return type on AbstractMethodInvocationTest's
anonymous getThis() (never null), fix a namespace collision between
Go\Aop\Framework\Interceptor and Go\Aop\Intercept\Interceptor in
InterceptorInjectorTest, pass real class-string constants (instead of
made-up strings) to TraitIntroductionInfo in its test, and give
InterceptorInjector's non-empty-list<Interceptor> parameter real
interceptor instances instead of empty arrays.

Elsewhere, follow this codebase's existing @PHPStan-Ignore convention
(see StaticTraitAliasMethodInvocationTest, TheTest, ContainerTest) for
runtime double-checks of literal/narrowed return types and deliberately
mismatched test inputs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Add tests/Aop/Support/PointcutBuilderTest.php and
tests/Aop/Support/LazyPointcutAdvisorTest.php.

Fix PHPStan level-10 findings picked up in review: type the untyped
matches() callback in AdviceMatcherTest (real bug risk - untyped
closure params silently accept anything), narrow ReflectionProperty's
mixed getValue() result with a runtime is_array() check instead of a
blanket array return type, and align doParsePointcut()'s reflection
parameter with the same per-call @template T pattern already used by
AbstractAspectLoaderExtension::parsePointcut() so covariant
ReflectionClass<ConcreteAspect> arguments type-check. Elsewhere, follow
the existing @PHPStan-Ignore convention for runtime double-checks of
narrowed return types and reflection-only private methods.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Add tests/Lang/Attribute/DeclareParentsTest.php. Use real class-string
constants (a fixture trait/interface) instead of made-up strings for
DeclareParents' class-string-typed constructor params, matching the
pattern already used in IntroductionAspectExtensionTest. Give
doGetAdvice() an explicit Advice return type and type the untyped
introduction/plainProperty test-fixture properties.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Reflection-based helpers that read/invoke protected AspectKernel
internals returned raw mixed, which cascaded into ~40 PHPStan errors
(offset access, casts, foreach, array unpacking all done on mixed).
Replace with narrow-and-validate helpers (invokeProtectedArray,
invokeProtectedString, getKernelOptions/setKernelOptions) that build a
properly-keyed array via a checked loop, plus PHPUnit's
assertIsString()/assertIsArray() type-specifying extensions to narrow
individual option values before using them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
…ings

Add tests/Console/Command/BaseAspectCommandTest.php,
tests/Proxy/FunctionProxyGeneratorTest.php,
tests/Proxy/Part/AbstractInterceptedPropertyGeneratorTest.php, and
tests/Stubs/Generator/PropertyTypeStubs.php; extend the existing
DebugAdvisorCommand/DebugAspectCommand in-process tests and the
FileGenerator/InterceptedConstructorGenerator/InterceptedMethodGenerator
generator tests.

Real fix: BaseAspectCommandTest's command factory returned the
BaseAspectCommand base type while assigning extra public properties on
an anonymous subclass, so PHPStan couldn't see them - replaced with a
named BaseAspectCommandTestCommandStub subclass. Elsewhere, narrow a
ReflectionClass::getConstructor() nullable result with assertNotNull()
before use, and follow the existing @PHPStan-Ignore convention for
runtime double-checks of already-narrowed return types.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
…ix findings

Extend tests/Instrument/Transformer/WeavingTransformerTest.php and
ConstructorExecutionTransformerTest.php with trait weaving, abstract
class handling, attribute-comma removal, promoted-property attributes,
inherited-member dispatch, function-proxy caching, and no-cache-dir
paths; add matching stub fixtures under Stubs/ and _files/. Extend
PointcutParserTest with the non-Pointcut-result guard on parse().

Fix PHPStan findings: give the anonymous TokenStream's getIterator() an
explicit generic @return type, and mark the deliberate direct
__get()/__call() magic-method exercises in
ConstructorExecutionTransformerTest with the project's existing
@PHPStan-Ignore convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
file_put_contents() with LOCK_EX fails on any non-"file://" stream
wrapper (PHP core rejects the flag there), which saveProxyToCache()
already accounts for a few lines below via an $isStreamPath guard.
processFunctions() wrote the function-proxy cache file unconditionally
with LOCK_EX, so generating a fresh function proxy into a stream-backed
cache dir (e.g. the virtual file system used throughout this test
suite) would fail. Apply the same guard, and add a test that exercises
the actual generation path (previously only the "already fresh, reuse
existing file" path was covered).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
Both have had no effect since PHP 8.1 (reflection access no longer
respects visibility) and PHP 8.5 now emits a deprecation notice for
calling them, which failOnDeprecation in phpunit.xml.dist turns into a
CI failure on the PHP 8.5/8.6 test matrix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V96x2qKNqcQbqxjf5anAPH
@lisachenko
lisachenko marked this pull request as ready for review September 3, 2026 09:52
@lisachenko
lisachenko merged commit 54a148c into master Sep 3, 2026
12 checks passed
@lisachenko
lisachenko deleted the claude/code-coverage-90-percent-me7ttt branch September 3, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants