Skip to content

Add Infection static-analysis checks to CI and harden tests for randomized execution#51

Merged
voku merged 7 commits into
masterfrom
copilot/integrate-infection-static-analysis
May 9, 2026
Merged

Add Infection static-analysis checks to CI and harden tests for randomized execution#51
voku merged 7 commits into
masterfrom
copilot/integrate-infection-static-analysis

Conversation

Copilot AI commented May 2, 2026

Copy link
Copy Markdown
Contributor

This integrates Infection's PHPStan-backed static-analysis mode into CI on PHP 8.3 and addresses the test fragility it exposed. The main follow-up was removing order/deprecation issues that caused Infection’s initial randomized PHPUnit run to fail.

  • CI / mutation testing

    • Add infection.json.dist with PHPUnit + PHPStan static-analysis integration.
    • Extend the existing PHP 8.3 static-analysis job to install and run Infection.
    • Mirror the PHPUnit job’s service dependencies in the Infection job so mutation runs execute against the same Redis/Memcached-backed environment.
  • PHPUnit execution stability

    • Pin PHPUnit execution order in phpunit.xml so the suite behaves deterministically under Infection’s initial run.
    • Remove cross-test state assumptions in the auto-init cache tests by making each assertion set up its own data and by isolating prefixes per test.
  • PHP 8.2+ compatibility in tests

    • Replace dynamic-property usage on ArrayObject in ArrayCacheTest with ARRAY_AS_PROPS + array-backed initialization.
    • Update the serialized fixture expectation to match the new object shape.
  • Example

    {
      "$schema": "https://infection.github.io/schema.json",
      "source": {
        "directories": ["src"]
      },
      "phpUnit": {
        "configDir": ".",
        "customPath": "vendor/bin/phpunit"
      },
      "phpStan": {
        "configDir": ".",
        "customPath": "vendor/bin/phpstan"
      },
      "testFramework": "phpunit",
      "staticAnalysisTool": "phpstan"
    }

This change is Reviewable

@voku

voku commented May 2, 2026

Copy link
Copy Markdown
Owner

/gemini review

@voku voku marked this pull request as ready for review May 2, 2026 20:19

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a configuration for Infection mutation testing and updates the PHPUnit configuration. Significant changes were made to the test suite to ensure test independence by removing @Depends annotations and replacing static cache prefixes with dynamic ones. Feedback includes a recommendation to avoid hardcoding serialized strings in ArrayCacheTest.php for better maintainability and a suggestion to simplify uniqid calls by removing redundant time() prefixes.

Comment thread tests/ArrayCacheTest.php Outdated
static::assertSame('N;', $values['foo_null']);
static::assertSame('a:3:{i:0;i:3;i:1;i:2;i:2;i:1;}', $values['foo']);
static::assertSame('O:11:"ArrayObject":4:{i:0;i:0;i:1;a:1:{s:3:"arr";s:10:"array data";}i:2;a:1:{s:4:"prop";s:9:"prop data";}i:3;N;}', $values['ao']);
static::assertSame('O:11:"ArrayObject":4:{i:0;i:2;i:1;a:2:{s:4:"prop";s:9:"prop data";s:3:"arr";s:10:"array data";}i:2;a:0:{}i:3;N;}', $values['ao']);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Hardcoding serialized strings for complex objects like ArrayObject is fragile and makes tests difficult to maintain, especially as internal PHP representations or serialization formats can change between versions. A more robust approach is to dynamically generate the expected serialized string using serialize() on a known object state, or to unserialize the stored value and compare the resulting objects.

        $expectedAo = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
        $expectedAo['prop'] = 'prop data';
        $expectedAo['arr'] = 'array data';
        static::assertSame(serialize($expectedAo), $values['ao']);

Comment thread tests/CacheAutoInitOverwriteTest.php Outdated
$item = $this->cache->getItem('some:test:key');
$key = 'some:test:key';

$this->cache->setItem($key, \uniqid(\time(), true), 10);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using \time() as a prefix for \uniqid() is redundant because uniqid already incorporates the current time into its generated value. Furthermore, time() returns an integer, while uniqid expects a string prefix. While PHP handles the type coercion here, it is cleaner and more idiomatic to use an empty string or a descriptive static prefix if uniqueness is already provided by the more_entropy parameter.

        $this->cache->setItem($key, \uniqid('', true), 10);

@voku

voku commented May 2, 2026

Copy link
Copy Markdown
Owner

@copilot Check if the next llm generated feedback is valid or just AI slop: Code Review
This pull request introduces a configuration for Infection mutation testing and updates the PHPUnit configuration. Significant changes were made to the test suite to ensure test independence by removing https://github.com/Depends annotations and replacing static cache prefixes with dynamic ones. Feedback includes a recommendation to avoid hardcoding serialized strings in ArrayCacheTest.php for better maintainability and a suggestion to simplify uniqid calls by removing redundant time() prefixes.

tests/ArrayCacheTest.php
static::assertSame('N;', $values['foo_null']);
static::assertSame('a:3:{i:0;i:3;i:1;i:2;i:2;i:1;}', $values['foo']);
static::assertSame('O:11:"ArrayObject":4:{i:0;i:0;i:1;a:1:{s:3:"arr";s:10:"array data";}i:2;a:1:{s:4:"prop";s:9:"prop data";}i:3;N;}', $values['ao']);
static::assertSame('O:11:"ArrayObject":4:{i:0;i:2;i:1;a:2:{s:4:"prop";s:9:"prop data";s:3:"arr";s:10:"array data";}i:2;a:0:{}i:3;N;}', $values['ao']);
@gemini-code-assist
gemini-code-assist Bot
17 minutes ago
medium

Hardcoding serialized strings for complex objects like ArrayObject is fragile and makes tests difficult to maintain, especially as internal PHP representations or serialization formats can change between versions. A more robust approach is to dynamically generate the expected serialized string using serialize() on a known object state, or to unserialize the stored value and compare the resulting objects.

    $expectedAo = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
    $expectedAo['prop'] = 'prop data';
    $expectedAo['arr'] = 'array data';
    static::assertSame(serialize($expectedAo), $values['ao']);

@voku Reply...
tests/CacheAutoInitOverwriteTest.php
$item = $this->cache->getItem('some:test:key');
$key = 'some:test:key';

    $this->cache->setItem($key, \uniqid(\time(), true), 10);

@gemini-code-assist
gemini-code-assist Bot
17 minutes ago
medium

Using \time() as a prefix for \uniqid() is redundant because uniqid already incorporates the current time into its generated value. Furthermore, time() returns an integer, while uniqid expects a string prefix. While PHP handles the type coercion here, it is cleaner and more idiomatic to use an empty string or a descriptive static prefix if uniqueness is already provided by the more_entropy parameter.

    $this->cache->setItem($key, \uniqid('', true), 10);

Copilot AI commented May 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Check if the next llm generated feedback is valid or just AI slop: Code Review
This pull request introduces a configuration for Infection mutation testing and updates the PHPUnit con...

Mostly valid, not slop. The ArrayObject serialization feedback was actionable, so I changed that assertion to build the expected serialized value dynamically. The uniqid(\time(), true) note was also reasonable for the calls I introduced, so I simplified those in the auto-init tests. Addressed in 884e6a2.

@sonarqubecloud

sonarqubecloud Bot commented May 2, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
42.4% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copilot finished work on behalf of voku May 2, 2026 20:40
Copilot AI requested a review from voku May 2, 2026 20:40
@voku voku merged commit 8405063 into master May 9, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants