Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuleTestCase: add analyseFileWithErrorsAsComments #2742

Open
wants to merge 1 commit into
base: 1.10.x
Choose a base branch
from

Conversation

janedbal
Copy link
Contributor

@janedbal janedbal commented Nov 15, 2023

I'd like to suggest this feature I'm using for about 4-5 years in my projects. E.g. here.

Benefits:

  • immediately visible where the error is raised and where not
  • errors float with code, so you can easily add code in between existing errors without modifying expected errors (currently even a single use statement added breaks everything)

Downsides:

  • no support for multiple errors on a single line
  • when traits come into play, error lines are not always in ascending order so it mismatches

I believe that at least 90% tests could benefit from this. Other can stick with the old approach.

@phpstan-bot
Copy link
Collaborator

You've opened the pull request against the latest branch 1.11.x. If your code is relevant on 1.10.x and you want it to be released sooner, please rebase your pull request and change its target to 1.10.x.

@janedbal janedbal changed the base branch from 1.11.x to 1.10.x November 15, 2023 14:05
@@ -4,7 +4,7 @@ function (
string $str
) {
(string) $str;
(string) new \stdClass();
(string) new \stdClass(); // error: Cannot cast stdClass to string.
Copy link
Contributor

@staabm staabm Nov 19, 2023

Choose a reason for hiding this comment

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

what comes to mind: maybe we can do it similar to assertType() and assertVariableCertainty()

Suggested change
(string) new \stdClass(); // error: Cannot cast stdClass to string.
assertErrorMessage('Cannot cast stdClass to string.', (string) new \stdClass());

?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I'd like something like that too. Perhaps something like assertErrorOnNextLine('message');

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is much less flexible. You cannot call method between class methods etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Error can be anywhere, in phpdoc, at class level, at trait usage. Comment is the only thing you can place anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, the implemented version works even within phpdocs (to be supported in #2807)

@DaveLiddament
Copy link
Contributor

I've created a similar package to do help with testing custom rules: https://github.com/DaveLiddament/phpstan-rule-test-helper. This provides AbstractRuleTestCase to extend for testing custom rules.

This allows you to either hard code the error message in the fixture file (similar to @janedbal's suggestion) . E.g.

    $item->updateName("world"); // ERROR can not call method

If the same error message is repeated multiple times, then you can also override the getErrorFormatter with the error message. This means error messages need updating only in one place in the test:

  protected function getErrorFormatter(): string 
  {
    return "Can not call method";
  } 

The fixture simplifies to:

    $item->updateName("world"); // ERROR 

Finally you can provide context in the error messages:

  protected function getErrorFormatter(): string 
  {
    return "Can not call method {0} from {1}";
  } 

The fixture error has additional contextual information, if there is more than 1 bit it is separated by | character.

    $item->updateName("world"); // ERROR Item::updateName|Foo

In the above example the expected error message would be: Can not call method Item::updateName from Foo


It be nice to either bring similar functionality into PHPStan, or highlight helper packages that can help with testing.

@ondrejmirtes
Copy link
Member

Some thoughts after letting this sit for a while:

  • Expecting errors in comments is very similar to ignoring errors
  • If we implement a similar system I want it to work like assertType - that it can be tested both by running PHPUnit and simply by analysing code with PHPStan
  • So what about @phpstan-error An exact error message that works the same way as @phpstan-ignore with an error identifier in 1.11.x?

@DaveLiddament
Copy link
Contributor

Some thoughts after letting this sit for a while:

  • Expecting errors in comments is very similar to ignoring errors
  • If we implement a similar system I want it to work like assertType - that it can be tested both by running PHPUnit and simply by analysing code with PHPStan
  • So what about @phpstan-error An exact error message that works the same way as @phpstan-ignore with an error identifier in 1.11.x?

I like @phpstan-error.

I love the fact you'd then not even need to create PHPUnit tests, you can just point PHPStan at the code snippet.

@janedbal
Copy link
Contributor Author

So what about @phpstan-error An exact error message that works the same way as @phpstan-ignore with an error identifier in 1.11.x?

I'm not sure that the next-line magic is needed here. Imo not.

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.

5 participants