원클릭으로
regression-test
Add a regression test for an already-fixed PHPStan bug given a GitHub issue number
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Add a regression test for an already-fixed PHPStan bug given a GitHub issue number
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | regression-test |
| description | Add a regression test for an already-fixed PHPStan bug given a GitHub issue number |
| argument-hint | [issue-number] |
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.
Fetch the GitHub issue and its comments:
gh issue view <number> --repo phpstan/phpstan --json title,body,comments
In the comments, look for:
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.
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.
tests/PHPStan/Analyser/nsrt/bug-<number>.phpassertType() and optionally assertNativeType() to pin the correct typesExample (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}());
};
}
}
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:
grep -r 'identifier' tests/PHPStan/Rules/ --include='*Test.php'
Or look at the error identifier from the playground output (e.g., argument.type points to a rule in Rules/Methods/ or Rules/Functions/).
Create the test data file at tests/PHPStan/Rules/<Category>/data/bug-<number>.php.
Add a test method in the corresponding *Test.php rule 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.
namespace Bug<number>;.use function PHPStan\Testing\assertType; for NSRT tests.// lint >= 8.0 (or whichever version) on the first line.versionedErrors. If the fix eliminated a false positive, expect []. If the fix added a missing error, list the expected [message, line] pairs.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>
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 pop
If the test passes even with the fix reverted, the test is not correctly covering the bug — revisit the assertions or the reproducing code.
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>"
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.