Skip to content

Add the PHPUnit adapter over property-testing-core - #1

Merged
rasuvaeff merged 3 commits into
masterfrom
feat/phpunit-adapter
Aug 9, 2026
Merged

Add the PHPUnit adapter over property-testing-core#1
rasuvaeff merged 3 commits into
masterfrom
feat/phpunit-adapter

Conversation

@rasuvaeff

@rasuvaeff rasuvaeff commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Brings the package to its 0.1.0 state: a fluent forAll() trait on top of rasuvaeff/property-testing-core ^0.1.

$this->forAll(['values' => Gen::arrayOf(Gen::int())])
    ->runs(300)
    ->check(function (array $values): void {
        self::assertSame(sortValues($values), sortValues(sortValues($values)));
    });

What this package owns: only the PHPUnit boundary — one AssertionFailedError carrying the original throwable as previous, Assume reported as a discard inside the property rather than a skipped PHPUnit test, the distribution report and discard warning, and a verbose listener. Generation, integrated shrinking, the regression corpus and the event model all come from core; there is no algorithm here.

Environment parity with the Testo adapter is a tested contract, not a claim: PROPERTY_RUNS, PROPERTY_SEED, PROPERTY_VERBOSE and PROPERTY_DB behave identically, and a corpus written by one adapter is read by the other (EnvironmentParityTest).

No #[Property] attribute in 0.1, deliberately. PHPUnit's public extension API observes execution but offers no supported way to intercept and replace a test method call; this adapter does not reach into PHPUnit internals. An attribute can follow only if it becomes implementable on documented API.

The test suite isolates itself from the ambient environment in both directions: setUp clears every PROPERTY_* variable and tearDown restores the caller's original values instead of deleting them.

Verification: composer build green against core 0.1.0 resolved from Packagist, psalm level 1 clean (two narrow issueHandlers at the PHPUnit boundary), mutation 104/113 with nine equivalent survivors (gate 90 — 100 is unreachable without ignores, which are forbidden here), bin/package-audit 0 errors / 0 warnings, zizmor --persona=auditor clean. The Backward compatibility job skips by design — there is no tag yet.

Summary by CodeRabbit

  • New Features
    • Added PHPUnit property testing with randomized inputs, configurable runs, shrinking, seeds, timeouts, budgets, and discard handling.
    • Added support for pinned examples, assumptions, classification and distribution reports, regression corpus replay, and verbose execution tracing.
    • Added clear assertion failures and counterexample reporting for falsified properties.
  • Documentation
    • Added installation guidance, API reference, environment-variable behavior, and a runnable sorting example.
  • Chores
    • Added repository contribution guidance, issue templates, release automation, and automated quality checks.

A fluent `forAll()` trait on top of the framework-agnostic engine: generation,
integrated shrinking, the regression corpus and the event model all come from
`rasuvaeff/property-testing-core` ^0.1, and this package only adapts them to
PHPUnit — one AssertionFailedError carrying the original throwable as previous,
`Assume` reported as a discard inside the property rather than a skipped test,
the distribution report and discard warning, and a verbose listener.

Environment parity with the Testo adapter is a tested contract, not a claim:
PROPERTY_RUNS, PROPERTY_SEED, PROPERTY_VERBOSE and PROPERTY_DB behave
identically, and a corpus written by one adapter is read by the other.

No `#[Property]` attribute in 0.1 on purpose: PHPUnit's public extension API
observes execution but offers no supported way to intercept and replace a test
method call, and this adapter does not reach into PHPUnit internals.

Verification: composer build green against core 0.1.0 from Packagist, psalm
level 1 clean (two narrow issueHandlers at the PHPUnit boundary), mutation
104/113 with nine equivalents, bin/package-audit 0 errors / 0 warnings,
zizmor --persona=auditor clean.
@rasuvaeff
rasuvaeff marked this pull request as draft August 9, 2026 06:43
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@rasuvaeff, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 17 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 947935bc-3523-4818-97e6-cef0c9cc5ed5

📥 Commits

Reviewing files that changed from the base of the PR and between d88d6ee and c913118.

📒 Files selected for processing (8)
  • .php-cs-fixer.php
  • AGENTS.md
  • psalm.xml
  • rector.php
  • src/PhpUnit/PropertyCheck.php
  • src/PhpUnit/VerboseListener.php
  • tests/AdapterDetailsTest.php
  • tests/PropertyCheckTest.php
📝 Walkthrough

Walkthrough

Adds a PHPUnit property-testing adapter with fluent configuration, environment support, regression replay, reporting, verbose tracing, tests, documentation, package tooling, CI workflows, and release automation.

Changes

PHPUnit Property Testing Adapter

Layer / File(s) Summary
Package and developer tooling
.editorconfig, .gitattributes, .gitignore, composer.json, phpunit.xml, psalm.xml, rector.php, .php-cs-fixer.php, infection.json5, Makefile, AGENTS.md, CLAUDE.md
Defines package metadata, autoloading, development commands, analysis and formatting rules, test configuration, mutation testing, repository guidance, and archive or ignore rules.
Property check execution
src/PhpUnit/PropertyTesting.php, src/PhpUnit/PropertyCheck.php
Adds the forAll() entry point and fluent property execution with generator binding, environment overrides, regression replay, reporting, assertion accounting, and failure conversion.
Verbose event and output handling
src/PhpUnit/VerboseListener.php
Adds verbose event logging for attempts, generated values, and accepted shrink steps with configurable output streams.
Adapter validation and examples
tests/*, examples/*, llms.txt
Adds support utilities and tests for execution, environment behavior, corpus replay, reporting, discards, shrinking, and output. Adds a sorting example and API documentation.
Repository intake and release automation
.github/ISSUE_TEMPLATE/*, .github/dependabot.yml, .github/workflows/*, CHANGELOG.md
Adds structured issue forms, dependency update scheduling, build and analysis workflows, workflow security auditing, and tag-based release creation with changelog notes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PHPUnitTest as PHPUnit TestCase
  participant PropertyTesting
  participant PropertyCheck
  participant PropertyRunner
  participant VerboseListener

  PHPUnitTest->>PropertyTesting: call forAll(generators)
  PropertyTesting->>PropertyCheck: create configured property check
  PHPUnitTest->>PropertyCheck: call check(property)
  PropertyCheck->>VerboseListener: attach verbose listener when enabled
  PropertyCheck->>PropertyRunner: execute generated cases
  PropertyRunner-->>VerboseListener: emit attempt and shrink events
  PropertyRunner-->>PropertyCheck: return result or failure
  PropertyCheck-->>PHPUnitTest: record assertion or throw failure
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a PHPUnit adapter for property-testing-core.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phpunit-adapter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

🧹 Nitpick comments (5)
src/PhpUnit/VerboseListener.php (1)

85-94: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Type the key parameter as string.

The docblock declares array<string, mixed>, so array_keys($arguments) returns list<string>. Declaring mixed $name and then concatenating it weakens the guarantee that the trace key is a string. Use string $name.

♻️ Proposed typing change
         $pairs = array_map(
-            static fn(mixed $value, mixed $name): string => $name . '=' . ValueRenderer::render($value),
+            static fn(mixed $value, string $name): string => $name . '=' . ValueRenderer::render($value),
             $arguments,
             array_keys($arguments),
         );
As per coding guidelines: "Use `declare(strict_types=1)`, explicit types, `final` classes, `readonly` where state allows".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/PhpUnit/VerboseListener.php` around lines 85 - 94, Update the key
parameter in the formatArguments array_map callback from mixed to string,
matching the declared array<string, mixed> contract and ensuring trace keys are
explicitly typed as strings.

Source: Coding guidelines

examples/SortPropertyTest.php (1)

54-70: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The median property is a tautology.

For any sorted list, $sorted[intdiv(count($sorted), 2)] is always between $sorted[0] and $sorted[count($sorted) - 1]. Both assertions hold for every input, so this property cannot be falsified by any generator. It still demonstrates Assume::that(), which is the stated purpose, but consider a property that can actually fail, for example that the median of the sorted list equals the median of the unsorted input passed through self::sorted().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/SortPropertyTest.php` around lines 54 - 70, Replace the tautological
assertions in testMedianStaysBetweenMinAndMax with a property that compares the
median derived from the sorted values against the median of the original
unsorted input after applying self::sorted(). Preserve the existing
Assume::that(count($values) > 1) demonstration and generator setup.
tests/EnvironmentParityTest.php (1)

179-185: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the unused catch variable.

$failure is never read in this block. PHP 8 allows a non-capturing catch, and AdapterDetailsTest line 305 already uses that form.

♻️ Proposed change
-        } catch (AssertionFailedError $failure) {
+        } catch (AssertionFailedError) {
             // Recorded.
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/EnvironmentParityTest.php` around lines 179 - 185, Update the catch
block around runFalsifiableProperty in EnvironmentParityTest to use PHP 8’s
non-capturing catch syntax, removing the unused $failure variable while
preserving the existing AssertionFailedError handling.
tests/AdapterDetailsTest.php (1)

62-77: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Strengthen the assertion so it actually pins the reindexing.

The test name states that named variadic arguments must not leak string keys. assertNotSame([], $listener->events) passes with or without array_values() in PropertyCheck::listeners(), because the engine iterates the array either way. This matches the escaped UnwrapArrayValues mutant reported on src/PhpUnit/PropertyCheck.php line 154. Assert the list shape directly.

♻️ Proposed assertion
-        self::assertNotSame([], $listener->events);
+        self::assertNotSame([], $listener->events);
+        self::assertSame(array_keys($listener->events), range(0, count($listener->events) - 1));

The reindexing itself is only observable inside the engine, so consider also asserting on a value the engine derives from the listener list if core exposes one.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/AdapterDetailsTest.php` around lines 62 - 77, Strengthen
testListenersAcceptNamedArgumentsWithoutLeakingStringKeys by asserting the
listener-derived event data has the expected reindexed list shape, rather than
only checking that events are non-empty. Use an assertion that fails when
PropertyCheck::listeners() omits array_values() and preserves the named
argument’s string key, while retaining the existing property check.

Source: Linters/SAST tools

src/PhpUnit/PropertyCheck.php (1)

287-300: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Confirm the intended behavior for out-of-range PROPERTY_RUNS.

(int) $env saturates to PHP_INT_MAX for a digit string above the integer range. PROPERTY_RUNS=999999999999999999999 therefore passes validation and configures an effectively unbounded run count. If you want a hard rejection, compare the string against (string) PHP_INT_MAX length or use filter_var($env, FILTER_VALIDATE_INT).

♻️ Optional stricter parse
-        if (preg_match('/^\d+\z/', $env) !== 1 || (int) $env < 1) {
+        $runs = filter_var($env, FILTER_VALIDATE_INT);
+
+        if (preg_match('/^\d+\z/', $env) !== 1 || !is_int($runs) || $runs < 1) {
             throw new \InvalidArgumentException(sprintf('PROPERTY_RUNS must be a positive integer, got "%s"', $env));
         }
 
-        return (int) $env;
+        return $runs;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/PhpUnit/PropertyCheck.php` around lines 287 - 300, Update
PropertyCheck::envRuns() to reject digit strings outside PHP’s integer range
instead of allowing values that cast to PHP_INT_MAX; use a range-safe integer
validation approach such as FILTER_VALIDATE_INT or an explicit comparison
against PHP_INT_MAX, while preserving acceptance of positive in-range values and
the existing exception behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 122-124: Update the Infection guidance in AGENTS.md to document
minMsi as 90 instead of 85, matching the configured threshold in
infection.json5.

In `@examples/README.md`:
- Around line 14-16: Update the documented PHPUnit command in the README to
invoke PHPUnit through the Composer Docker image correctly, using either an
explicit PHP entrypoint or composer exec while preserving the existing volume,
working directory, and test target.

In `@psalm.xml`:
- Around line 28-34: Remove the PHPUnit constructor suppressions for
PHPUnit\Framework\Exception::__construct and
PHPUnit\Framework\AssertionFailedError::__construct from the InternalMethod
errorLevel block in psalm.xml, retaining only AssertionFailedError and
TestCase::addToAssertionCount allowances. If this exposes a Psalm boundary
violation, adjust the related throw/catch code rather than adding new
suppressions.

In `@rector.php`:
- Around line 20-30: Update the comment above the dead-code skip rules to remove
the obsolete #[Property] rationale and unsupported attribute claim. Describe
only the actual reflection-based contract requiring generator methods and stub
test bodies to remain, or omit the explanatory comment while preserving the
existing skip configuration.

In `@tests/AdapterDetailsTest.php`:
- Around line 141-147: Update the report regex in the test’s assertSame call to
accept the platform-specific line terminator emitted by
PropertyCheck::reportClassifications, using PHP_EOL rather than hardcoding \n.
Preserve the existing distribution and percentage assertions.

In `@tests/PropertyCheckTest.php`:
- Around line 25-31: Add the same PROPERTY_* environment isolation used by
AdapterDetailsTest and EnvironmentParityTest to PropertyCheckTest: call
Env::isolateProperty() during setUp and restore the captured environment during
tearDown. Preserve the existing test behavior while ensuring tests use their
unseeded defaults or explicitly pinned seeds rather than ambient configuration.

---

Nitpick comments:
In `@examples/SortPropertyTest.php`:
- Around line 54-70: Replace the tautological assertions in
testMedianStaysBetweenMinAndMax with a property that compares the median derived
from the sorted values against the median of the original unsorted input after
applying self::sorted(). Preserve the existing Assume::that(count($values) > 1)
demonstration and generator setup.

In `@src/PhpUnit/PropertyCheck.php`:
- Around line 287-300: Update PropertyCheck::envRuns() to reject digit strings
outside PHP’s integer range instead of allowing values that cast to PHP_INT_MAX;
use a range-safe integer validation approach such as FILTER_VALIDATE_INT or an
explicit comparison against PHP_INT_MAX, while preserving acceptance of positive
in-range values and the existing exception behavior.

In `@src/PhpUnit/VerboseListener.php`:
- Around line 85-94: Update the key parameter in the formatArguments array_map
callback from mixed to string, matching the declared array<string, mixed>
contract and ensuring trace keys are explicitly typed as strings.

In `@tests/AdapterDetailsTest.php`:
- Around line 62-77: Strengthen
testListenersAcceptNamedArgumentsWithoutLeakingStringKeys by asserting the
listener-derived event data has the expected reindexed list shape, rather than
only checking that events are non-empty. Use an assertion that fails when
PropertyCheck::listeners() omits array_values() and preserves the named
argument’s string key, while retaining the existing property check.

In `@tests/EnvironmentParityTest.php`:
- Around line 179-185: Update the catch block around runFalsifiableProperty in
EnvironmentParityTest to use PHP 8’s non-capturing catch syntax, removing the
unused $failure variable while preserving the existing AssertionFailedError
handling.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b7bdc224-5853-4ce8-a997-814320240a98

📥 Commits

Reviewing files that changed from the base of the PR and between 284871e and d88d6ee.

📒 Files selected for processing (32)
  • .editorconfig
  • .gitattributes
  • .github/ISSUE_TEMPLATE/bug_report.yml
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/ISSUE_TEMPLATE/feature_request.yml
  • .github/dependabot.yml
  • .github/workflows/build.yml
  • .github/workflows/release.yml
  • .github/workflows/static-analysis.yml
  • .github/workflows/zizmor.yml
  • .gitignore
  • .php-cs-fixer.php
  • AGENTS.md
  • CHANGELOG.md
  • CLAUDE.md
  • Makefile
  • composer.json
  • examples/README.md
  • examples/SortPropertyTest.php
  • infection.json5
  • llms.txt
  • phpunit.xml
  • psalm.xml
  • rector.php
  • src/PhpUnit/PropertyCheck.php
  • src/PhpUnit/PropertyTesting.php
  • src/PhpUnit/VerboseListener.php
  • tests/AdapterDetailsTest.php
  • tests/EnvironmentParityTest.php
  • tests/PropertyCheckTest.php
  • tests/Support/Env.php
  • tests/Support/RecordingListener.php

Comment thread AGENTS.md
Comment thread examples/README.md
Comment on lines +14 to +16
```bash
docker run --rm -v "$PWD":/app -w /app composer:2 vendor/bin/phpunit examples/SortPropertyTest.php
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Compare the documented example command with the Makefile invocations.
fd -t f 'Makefile' -d 2 | xargs -I{} sh -c 'echo "== {} =="; rg -n "phpunit|composer:2|entrypoint" {}'

Repository: rasuvaeff/property-testing-phpunit

Length of output: 433


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== README excerpt =="
sed -n '1,40p' examples/README.md

echo
echo "== Makefile relevant lines =="
sed -n '1,120p' Makefile

echo
echo "== dockerfile/composer config files =="
git ls-files | sed -n '/^Dockerfile$/p; /^composer\.json$/p; /^compose.*\.ya?ml$/p; /^\..*composer.*$/p'

Repository: rasuvaeff/property-testing-phpunit

Length of output: 3643


Use an entrypoint or composer exec for the documented PHPUnit command.

composer:2 has Composer as its entrypoint, so docker run … composer:2 vendor/bin/phpunit … runs Composer instead of PHPUnit. Use --entrypoint php or composer exec so the README example matches the working composer:2 Docker workflow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/README.md` around lines 14 - 16, Update the documented PHPUnit
command in the README to invoke PHPUnit through the Composer Docker image
correctly, using either an explicit PHP entrypoint or composer exec while
preserving the existing volume, working directory, and test target.

Source: Learnings

Comment thread psalm.xml
Comment thread rector.php Outdated
Comment on lines +141 to +147
rewind($stdout);
$report = (string) stream_get_contents($stdout);
rewind($stderr);

// "always" hits every check, so it leads regardless of insertion
// order; percentages are integer-rounded of count/checks.
self::assertSame(1, preg_match('/^Property "\w+" distribution: always 100% \(50\/50\), rare \d+% \(\d+\/50\)\n$/', $report));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Fix the Windows build failure: the regex hardcodes \n.

PropertyCheck::reportClassifications terminates the report line with PHP_EOL. On Windows PHP_EOL is \r\n, and php://memory does not translate line endings. The pattern requires ) immediately followed by \n, so the match returns 0 and the Windows job fails at this line. The sibling tests at lines 195, 263, and 285 already compare against PHP_EOL and stay green.

Make the terminator platform-independent.

🐛 Proposed fix
-        self::assertSame(1, preg_match('/^Property "\w+" distribution: always 100% \(50\/50\), rare \d+% \(\d+\/50\)\n$/', $report));
+        self::assertSame(1, preg_match('/^Property "\w+" distribution: always 100% \(50\/50\), rare \d+% \(\d+\/50\)\R\z/', $report));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
rewind($stdout);
$report = (string) stream_get_contents($stdout);
rewind($stderr);
// "always" hits every check, so it leads regardless of insertion
// order; percentages are integer-rounded of count/checks.
self::assertSame(1, preg_match('/^Property "\w+" distribution: always 100% \(50\/50\), rare \d+% \(\d+\/50\)\n$/', $report));
rewind($stdout);
$report = (string) stream_get_contents($stdout);
rewind($stderr);
// "always" hits every check, so it leads regardless of insertion
// order; percentages are integer-rounded of count/checks.
self::assertSame(1, preg_match('/^Property "\w+" distribution: always 100% \(50\/50\), rare \d+% \(\d+\/50\)\R\z/', $report));
🧰 Tools
🪛 GitHub Actions: build / 0_Windows.txt

[error] 147-147: PHPUnit test Rasuvaeff\PropertyTesting\PhpUnit\Tests\AdapterDetailsTest::testTheDistributionReportLineIsExactAndSortedByCount failed: expected value 1 but received 0. The composer test/phpunit command exited with code 1.

🪛 GitHub Actions: build / Windows

[error] 147-147: PHPUnit test Rasuvaeff\PropertyTesting\PhpUnit\Tests\AdapterDetailsTest::testTheDistributionReportLineIsExactAndSortedByCount failed: expected 1 but got 0. The phpunit command failed with exit code 1.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/AdapterDetailsTest.php` around lines 141 - 147, Update the report regex
in the test’s assertSame call to accept the platform-specific line terminator
emitted by PropertyCheck::reportClassifications, using PHP_EOL rather than
hardcoding \n. Preserve the existing distribution and percentage assertions.

Source: Pipeline failures

Comment thread tests/PropertyCheckTest.php
…boundary

- PropertyCheck/VerboseListener: report lines now use a literal "\n" instead
  of PHP_EOL. This CLI output is machine-greppable; PHP_EOL is \r\n on
  Windows and broke every test (and would break every downstream tool) that
  matches a line with a plain-LF pattern. Caught by the Windows CI job.
- .php-cs-fixer.php: drop /benchmarks from the Finder. This package has no
  benchmarks/ and never will without pulling in a Testo-specific #[Bench]
  runner it deliberately doesn't depend on; pointing Finder at a directory
  that doesn't exist broke cs/build on every PHP job and prefer-lowest.
  Documented the omission in AGENTS.md.
- tests/PropertyCheckTest.php: isolate PROPERTY_* the same way the other two
  suites already do (setUp/tearDown via Support/Env) — this one was missed.
- psalm.xml: drop the redundant Exception::__construct suppression, keep
  AssertionFailedError::__construct. Verified empirically that Psalm keys
  InternalMethod suppression to the class named at the `new` call site, not
  to the class that actually declares the constructor (which is what its own
  diagnostic text names) — documented the gotcha in both psalm.xml and
  AGENTS.md so it doesn't get "simplified" back.
- rector.php: the three dead-code skips (reflection-driven fixtures) were
  copied from the Testo/core templates verbatim but don't apply here — this
  adapter has no <method>Generators()-by-reflection convention, forAll()
  takes generators as a plain argument. Verified rector finds nothing to
  remove without them; kept only the actually-needed RemoveUselessVarTagRector
  skip (@var mixed suppressing Psalm's MixedAssignment).

Reviewed and kept as-is: examples/README.md's documented `docker run ...
composer:2 vendor/bin/phpunit ...` command runs phpunit correctly — verified
live (composer:2's entrypoint execs a non-composer command directly).
@rasuvaeff
rasuvaeff marked this pull request as ready for review August 9, 2026 07:22
…t source

The previous commit made PropertyCheck emit a literal "\n" for its report
lines, but three AdapterDetailsTest assertions still built their EXPECTED
string with `. PHP_EOL` — so on Windows the source now emits \n while the
test still wants \r\n, and the Windows job failed the other direction than
before. Same root cause (report lines must be \n everywhere, source and
test), same fix, the other half of it. Grepped the whole tree this time —
no PHP_EOL left outside vendor/.
@rasuvaeff
rasuvaeff merged commit d6f3bad into master Aug 9, 2026
12 checks passed
@rasuvaeff
rasuvaeff deleted the feat/phpunit-adapter branch August 9, 2026 07:28
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.

1 participant