Problem/Motivation
Add phpstan/phpstan-phpunit as a dev dependency would reduce the PHPStan L2 errors by approx 1k false positives due to missing interpretation of mocks.
Shorter term, right now it identifies a significant (215) number of errors in test code already.
Proposed resolution
- Add dependency
- Fix, ignore or baseline errors
Add dependency evaluation- Commit
Dependency evaluation
Maintainership: Primary author is Ondřej Mirtes, also the author of PHPStan. The author is responsive to issues and pull requests.
Security policy: https://github.com/phpstan/phpstan-phpunit/security/policy (see also : https://github.com/phpstan/phpstan-phpunit/issues/161).
Release cycle: Not as regular or prolific as PHPStan itself, but still several releases this year - more is not expected given that it is a much smaller target that PHPStan itself, and PHPUnit is fairly stable so it does not need to chase a moving target.
Other dependencies: None (except PHPStan and PHPUnit, obviously)
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3326239
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3326239-dep-only
changes, plain diff MR !3737
- 3326239-add-phpstanphpstan-unit-as
changes, plain diff MR !3095
Comments
Comment #2
mondrakeComment #4
mondrakeComment #5
spokjeMe Like!!! :)
Adding a new dependency to core will require a dependency evaluation eventually and, if approved, adding to this page https://www.drupal.org/about/core/policies/core-dependency-policies/depe...
All stuff for later though.
Comment #6
mondrakeWorking on completing the MR.
Comment #7
mondrakeNeeds review.
I added to baseline a few missing calls to
parent::setUp()in base test classes, since their setUp() methods are making unconventional things.Also, phpstan/phpstan-phpunit does not currently support methods added to mocks if they are not defined in an interface, which is a rather opinionated approach. In this case, added an ignorePattern.
Maybe we may want to change our implementation to cope, in the end, but that would require significant refactoring, so for follow up in case.
Comment #8
mondrakeComment #9
mondrakeComment #10
longwaveDependency evaluation:
Maintainership: Primary author is Ondřej Mirtes, also the author of PHPStan. The author is responsive to issues and pull requests.
Security policy: None stated - this is a development tool so it is unlikely any security issue would affect us. We could open an issue in their queue to check, although not sure it is worth it?
Release cycle: Not as regular or prolific as PHPStan itself, but still several releases this year - more is not expected given that it is a much smaller target that PHPStan itself, and PHPUnit is fairly stable so it does not need to chase a moving target.
Other dependencies: None (except PHPStan, obviously)
As a release manager I have no issue with adding this dependency; it is a development-only code quality tool and could easily be removed again if any issues arise (e.g. if it became abandoned or for some reason not forward compatible with a new version of PHP or PHPUnit).
We already know PHPStan improves code quality and so improving the quality of our tests in an automated manner will only help further.
+1 to opening a followup to explore whether we should only mock methods that exist on interfaces.
I would mark this RTBC except that version 1.3.2 of phpstan-phpunit was released today, so NW to bump that.
Comment #11
mondrakephpstan/phpstan-unit 1.3.2 requires phpstan/phpstan ^1.9.3, so we need to wait for a bump of the current dev dependencies first.
Comment #12
longwaveAh, did not see that; in that case I don't see why this can't be committed now and we can bump both dependencies together in a future issue.
Comment #13
spokjeI looked at this in #3327018: Update PHPStan to 1.9.3 and make daily "updated deps" QA jobs pass
Comment #14
spokjeWhoops, unwanted status change
Comment #15
mondrakeNeeds a rebase
Comment #16
longwavePHPStan 1.9.3 made it in as well, so we can upgrade to the latest version.
Comment #17
mondrakeOnly rerolled and bumped to latest release, so I think I am safe to reRTBC this.
Comment #18
spokjeNeeds a manual rebase :/
Comment #19
mondrakeYea, but let's wait for #3330305: Fix failing "updated deps" test-runs by upping mglaman/phpstan-drupal to latest first and avoid reroll stampede
Comment #20
mondrakeRerolled. But I think there's a new release out already. No time to fix that ATM, I'll come back to it if noone beats me.
Comment #21
mondrakeSo there's a whole new set of additional real errors identified by the latest releases that need addressing. I think we should fix them here.
Comment #22
mondrakeDidn't mean to assign myself yet.
Comment #23
spokjeAgreed, and in fact, already on it.
Comment #24
mondrakeIncredible cleanup, really... it sounds like test coverage reporting is not really a thing...
I am afraid in an earlier push I removed something from the baseline which is not for this issue. Needs being reverted as it is out of scope here. See inline comments.
Comment #25
longwaveGreat cleanup. I guess we don't actually do anything with our @covers annotations!
Is @covers on an interface really correct? We are only actually testing a concrete implementation?
Also why is (for example) this change required, when the class has @coversDefaultClass set to that class already?
Comment #26
longwaveAlso: this patch is now quite large; should we consider ignoring or baselining the common errors and solving them separately? e.g assertSame(NULL) could have its own issue.
Comment #27
spokjeI hate it when the right answer means more work ;)
Tried to replace all (obvious) interfaces.
And that's all I can do for now until somebody decides if and how to chop this up into pieces.
Comment #28
mondrake-1 on splitting this at this stage. It’s fixes on test code only, and all backed by phpstan errors reported. PHPUnit tests all pass.
If at all necessary, a test-only patch with the composer json+lock changes only could help showing what’s being fixed.
Comment #29
spokjeI agree with @mondrake: Yes, this MR is big, all changes are backed up by PHPStan(-PHPUnit), so we can "verify" the changes.
Also, if we split, we basically give everybody more work with several issues where we have to c/p from this issue and creating suppressions just to remove them, when we have the "solution" already.
Comment #30
spokjeMy bad, missed the colon after
@coversand assumed a full-class-name fix was needed for the::displayAllowedTags-bit, like most of the other issues with@covers,Fixed now, also for other occurrences.
Comment #31
spokjeComment #32
spokjeBack to NR for #30.
Comment #33
mondrakeThanks for the test only patch, @Spokje.
Comment #34
spokjeSegway:
The test-only patch made me wonder: What (if any) is the rule-of-thumb for adding a patch-level semver number in a dependency?
For example: All
symfony/*stop at minor level, some other dependencies include patch-level versions, andphpspec/prophecy-phpunitonly has a major version.Comment #35
mallezieNitpick in
core/modules/ckeditor5/tests/src/Unit/HTMLRestrictionsTest.php
* @covers \Drupal\ckeditor5\HTMLRestrictions::allowsNothing::allowsNothing
Double allowsNothing. Which is a bit strange this is not flagged by phpstan-phpunit.
Comment #36
mondrakeFixed #35 in 08e01a73, thanks!
Comment #37
mondrakeComment #38
mondrakererolled, fixed new errors that came in
Comment #39
longwaveReviewed the whole MR this time, a bunch more @coversDefaultClass comments and some other minor nitpicks.
Comment #40
mondrakeThanks! Looking into it
Comment #41
mondrakeAddressed @longwave's comments.
Comment #42
longwaveAdded dependency evaluation to the IS.
Otherwise this all looks good to me so marking RTBC for another core committer opinion - +1 from me because this will only improve our tests in the future.
Comment #43
xjmRegarding:
That is not necessarily true. We had to issue a security advisory for RCE in PHPUnit in SA-CORE-2017-001. This is why we now have an explicit warning about PHPUnit's full disclosure policy on the core dependency info page. The purpose of these dependency evaluations is partly to supply content for that page, not just to determine whether the dependency can be added or not.
Comment #44
longwaveOpened https://github.com/phpstan/phpstan-phpunit/issues/161 to confirm the security policy.
Comment #45
xjmAre there separate rules for this that we could enable one at a time? While I was skimming the MR, I had a lot of questions about the changes to
@coversespecially that would be best reviewed in their own issue. The stuff with missingparent::setUp(),parent::tearDown(),assertCount(), etc. OTOH is self-explanatory.Comment #46
xjmI see that @longwave previously suggested splitting this up and others pushed back. However, the problem with the current approach is that we're mixing adding the dependency with simple, obvious 1:1 replacements and the
@coverschanges that essentially require running the tool locally and/or reading the entire test or method to understand what's correct -- and therefore blocking adding the dependency on all that. This is covered in the Context, contextual scope, and reviewability section of the issue scope policy.The average human brain can't effectively catch defects with this many different changes, and there is research that supports this. That's why we have the issue scope policy. It's not enough that the tool tells us to change it. The tool cannot tell us whether test coverage that we thought was there is actually missing, for example, meaning additional followups for additional test coverage might be needed, and that's one of the outcomes that there might be from the
@coverserrors.Comment #48
xjmSo far three of three release managers agree and independently came to the conclusion that this issue needs to be split up (@quietone had also intended to suggest it).
Comment #49
mondrakeUpdated dependency evaluation for privacy policy based on outcome of https://github.com/phpstan/phpstan-phpunit/issues/161.
Comment #50
mondrakeI think the review here has bent towards fixing the usage of @cover, which is not PHPStan's business.
According to PHPUnit's dcoumentation, https://phpunit.readthedocs.io/en/9.5/annotations.html#covers,
To me, this means that fixing @covers issues is part of using code coverage reporting tools. PHPStan in this context is only doing basic sanity checks like existence of indicated classes and methods, and syntax.
Then, #25:
On one side we actually do, as we (intend to) do more or less the same checks that PHPStan is doing here via DrupalStandardsListenerTrait. But it actually turns out that that has not been working for the last two years: #3335406: DrupalStandardsListenerTrait is broken.
That means that on the other side #25 is right in the sense that noone is doing test coverage reporting actually, otherwise #3335406: DrupalStandardsListenerTrait is broken would have been uncovered before this isssue here.
Comment #51
xjmWhen we added phpcs support to core, we did not run a gigantic cleanup patch to fix every single error it detected. Instead, we first made the choice to add the dependency and did that by itself, then opted into CS rules one at a time. Fixing errors correctly required context, and it was too many changes to review at once.
When we added CSpell, we did not fix every spelling error in core at once. Instead, we generated a dictionary of the words that were flagged as misspelled, and have been gradually reducing its size.
When we added PHPStan, we similarly did not fix everything it detected in core at once, but instead generated a large baseline, which we continue to fix gradually.
This issue should take the same approach. Understanding the changes to the
@coversannotation requires context that is not available from scanning the large MR. It requires reading the code of each changed test.If this MR simply added the dependency and added the errors to the baseline with a followup meta, it probably would have been committed weeks ago.
Let's split the MR up to add the dependency plus the necessary baseline, and then we can make incremental improvements, and discuss the
@coversproblem in its own, dedicated policy issue.Comment #52
spokjeDiscussed this with @mondrake in Slack, our plan is to:
- Use #3335406: DrupalStandardsListenerTrait is broken to fix
DrupalStandardsListenerTraitand all the@coverserrors it detects once fixed.- Then return to this issue and try to get
phpstan/phpstan-phpunitadded as a dev dependency.- Since we then have coverage of
@covers(Baduum tish, I'm here all week, try the veal...) throughphpstan/phpstan-phpunitwe can then deprecate/removeDrupalStandardsListenerTraitin (Yet Another) issue to be more ready for PHPUnit 10 that drops the usage of listeners.So, for now, postponing this issue on #3335406: DrupalStandardsListenerTrait is broken.
Comment #53
spokjeComment #54
mondrakeRebased and fixed more errors that show up in code committed recently.
Comment #55
mondrakeRebased and fixed more errors that show up in code committed recently.
Comment #56
alexpottThe blocker is in.
Comment #58
andypostrebase and upgraded to 1.3.11
Comment #59
mondrakeThanks. As much as I hate the idea, I think we should better split the issue: here just the added dependency with baselined/ignored errors, and in followups the error fixes and baseline cleanup. On that.
Comment #61
mondrakeDone #59 in MR!3737
Comment #62
spokjeRebasing to be able to retest and get rid of the (alarmingly increased) random JS test failures.
Comment #63
spokjeRight....
Random JS test failures galore!
Not wasting any more test-cycles on that, marking RTBC.
Note: I _did_ work on this issue, but only on the resolving of the new PHPStan errors, which are now out of scope and out of the new MR.
Therefore I think I'm OK to do so. There will be plenty of eyes on this from Core Committers and Framework managers anyway.
Comment #64
alexpottCommitted 947fd48 and pushed to 10.1.x. Thanks!
Comment #66
andypost@mondrake one follow-up to clean-up baseline should be enough?
Comment #67
spokjeOpened #3351055: [META] Fix PHPStan baseline suppressions introduced with phpstan/phpstan-phpunit to get rid of the new suppressions in the PHPStan baseline.
INSTA-EDIT: Cross-post with @andypost. Hope the new issue works for you?
Comment #68
alexpottI created a CR for this https://www.drupal.org/node/3351386