regression-test
Skill400 starsChanged 48 days agoMITView on GitHub
Add a regression test for an already-fixed PHPStan bug given a GitHub issue number
4 other projects use a version of this.
Adopted by
Most recently taken up by
- cloudposse/atmostheir own version, first seen Nov 1, 2026
- open-guji/luatex-cntheir own version, first seen Oct 9, 2026
- peteonrails/voxtypetheir own version, first seen Oct 8, 2026
- VodouAI/OStheir own version, first seen Jul 19, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- peteonrails/voxtype★ 1.8ksame name
- cloudposse/atmos★ 1.4ksame name
- open-guji/luatex-cn★ 127same name
- VodouAI/OS★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository3 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- turbo-ext/CLAUDE.mdCLAUDE.md
- rebase-branchSkill
The file
We split this skill into the rules it gives an agent
11 rules. 0 are common, 6 are distinctive, and 5 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
6
Distinctive
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 43
Use when the bug is about wrong inferred type, missing type narrowing, or incorrect type after control flow — i.e., PHPStan reports the …
- Very specific: line 46
Use assertType() and optionally assertNativeType() to pin the correct types
- Distinctive: line 94
Use when the bug is about a false positive (rule reported an error that shouldn't exist) or a false negative (rule failed to report an …
- Distinctive: line 96
Find the relevant rule test case: Search for the rule's identifier or class name:
- Distinctive: line 157
Use the reproducing code from the playground sample for the test file.
- Very specific: line 158
Put it in the correct namespace Bug<number>;.
- Very specific: line 159
Add use function PHPStan\Testing\assertType.
- Very specific: line 160
If the playground code requires a minimum PHP version, add // lint >= 8.0 (or whichever version) on the first line.
- Distinctive: line 165
Run the specific test to confirm it passes with the current (fixed) code:
- Distinctive: line 188
If the test passes even with the fix reverted, the test is not correctly covering the bug — revisit the assertions or the reproducing code.
- Very specific: line 203
If you are submitting a pull request, append the PR description with a link to the issue with Closes …
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Adding a regression test for a fixed PHPStan bug
You are given a GitHub issue number. Your goal is to write a regression test that locks in the fix so the bug cannot silently resurface.
Step 1 — Gather context from the issue
Fetch the GitHub issue and its comments:
gh issue view <number> --repo phpstan/phpstan --json title,body,commentsIn the comments, look for:
- phpstan-bot's commit link — this identifies the commit that fixed the bug.
- PHPStan Playground links — URLs matching
https://phpstan.org/r/<UUID>. These contain the reproducing code and the analysis results before and after the fix.
For each playground link, fetch the sample data:
curl -s 'https://api.phpstan.org/sample?id=<UUID>'The API returns JSON with:
code— the PHP code that was analysedlevel— the PHPStan rule level usedconfig.strictRules,config.bleedingEdge,config.treatPhpDocTypesAsCertain— configuration flagsversionedErrors— array of{phpVersion, errors: [{line, message, identifier}]}
The playground sample gives you the reproducing code and tells you what errors PHPStan produces (or should no longer produce) at each line. Use this to determine the correct test type and expected outcomes.
Step 2 — Decide which kind of test to write
Type-inference test (NSRT)
Use when the bug is about wrong inferred type, missing type narrowing, or incorrect type after control flow — i.e., PHPStan reports the wrong type for an expression but no specific rule error is involved.
- Create
tests/PHPStan/Analyser/nsrt/bug-<number>.php - Use
assertType()and optionallyassertNativeType()to pin the correct types - The file is auto-discovered — no test-case class changes are needed
Example (tests/PHPStan/Analyser/nsrt/bug-12875.php):
<?php // lint >= 8.0
declare(strict_types = 1);
namespace Bug12875;
use function PHPStan\Testing\assertType;
interface HasFoo
{
public function foo(): int;
}
interface HasBar
{
public function bar(): int;
}
class HelloWorld
{
/**
* @param "foo"|"bar" $method
* @param ($method is "foo" ? HasFoo : HasBar) $a
* @param ($method is "foo" ? HasFoo : HasBar) $b
*/
public function add(string $method, HasFoo|HasBar $a, HasFoo|HasBar $b): void
{
assertType('int', $a->{$method}());
assertType('int', $b->{$method}());
$addInArrow = fn () => assertType('int', $a->{$method}());
$addInAnonymous = function () use ($a, $b, $method): void {
assertType('int', $a->{$method}());
assertType('int', $b->{$method}());
};
}
}Rule test
Use when the bug is about a false positive (rule reported an error that shouldn't exist) or a false negative (rule failed to report an error that should exist).
- Find the relevant rule test case. Search for the rule's identifier or class name:
Or look at the error identifier from the playground output (e.g.,grep -r 'identifier' tests/PHPStan/Rules/ --include='*Test.php'argument.typepoints to a rule inRules/Methods/orRules/Functions/). - Create the test data file at
tests/PHPStan/Rules/<Category>/data/bug-<number>.php. - Add a test method in the corresponding
*Test.phprule test case.
Example — test data (tests/PHPStan/Rules/Methods/data/bug-11470.php):
<?php declare(strict_types = 1);
namespace Bug11470;
use DateTimeImmutable;
interface HelloWorld
{
public function sayHello(): dateTimeImmutable;
}
interface HelloWorld2
{
public function sayHello(dateTimeImmutable $a): void;
}
interface HelloWorld3
{
public function sayHello(): ?dateTimeImmutable;
}Example — test method in ExistingClassesInTypehintsRuleTest.php:
public function testBug11470(): void
{
$this->analyse([__DIR__ . '/data/bug-11470.php'], [
[
'Class DateTimeImmutable referenced with incorrect case: dateTimeImmutable.',
9,
],
[
'Class DateTimeImmutable referenced with incorrect case: dateTimeImmutable.',
14,
],
[
'Class DateTimeImmutable referenced with incorrect case: dateTimeImmutable.',
19,
],
]);
}For false-positive fixes the expected-errors array is usually empty [], meaning the code should analyse clean.
Step 3 — Write the test
- Use the reproducing code from the playground sample for the test file. Keep it as close as possible to the original. Once you have a reproducing failing test with the same error as the issue is about, do not edit the tested code sample.
- Put it in the correct
namespace Bug<number>;. - Add
use function PHPStan\Testing\assertType;for NSRT tests. - If the playground code requires a minimum PHP version, add
// lint >= 8.0(or whichever version) on the first line. - For rule tests, determine the expected errors from the playground
versionedErrors. If the fix eliminated a false positive, expect[]. If the fix added a missing error, list the expected[message, line]pairs.
Step 4 — Verify the test
Run the specific test to confirm it passes with the current (fixed) code:
# NSRT test — run the full NSRT suite or a filtered subset:
vendor/bin/phpunit tests/PHPStan/Analyser/NodeScopeResolverTest.php --filter 'bug-<number>'
# Rule test — run the specific test class:
vendor/bin/phpunit tests/PHPStan/Rules/<Category>/<TestClass>.php --filter testBug<number>Step 5 — Confirm the test catches a regression
Temporarily revert the fixing commit and verify the test fails:
git stash
git revert --no-commit <fixing-commit-hash>
vendor/bin/phpunit <test-command-from-step-4>
# Expect failure
git checkout .
git stash popIf the test passes even with the fix reverted, the test is not correctly covering the bug — revisit the assertions or the reproducing code.
Step 6 — Commit
Stage the new/modified test files and commit.
git add tests/
git commit -m "Add regression test for #<number>
Closes https://github.com/phpstan/phpstan/issues/<number>"Step 7 - Adjust pull request description
If you are submitting a pull request, append the PR description with a link to the issue with Closes https://github.com/phpstan/phpstan/issues/<number> so the upstream issue is closed automatically.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

