一键导入
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.