-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
When backupStaticAttributes is enable, static data from a first test case leaks to the subsequent tests cases #1
Comments
I do not see a bug here. |
This is causing me problems as well. I think this is a real bug. I'm not sure how this could be fixed. I can't see a "class loaded" event to which PHPUnit could subscribe. Perhaps @eriksencosta 's suggestion of wrapping the autoloader would work. However, any autoloaders added after the wrapping occurred would be missed, which seems quite likely to happen (e.g. Zend controller tests bootstrap Zend in the test "setup" method, at which point a lot of autoloaders are added). |
This bug still exists. I think this was closed by mistake due to an unrelated "#1" in the commit auto-linked above. Please could you re-open, to track the issue? This may be difficult or impossible to fix, but it should still be tracked :-) |
@RichardBradley The example code repo from the OP no longer exists. Are you able to provide a new isolated test case? |
OK, will do |
I have created a repo with a reproduction case here: https://github.com/thehereward/phpunit-backup-static-attributes-bug |
To summarise the bug:
You may dismiss this by saying that the static field didn't exist before the test was run, so "backupStaticAttributes" couldn't catch it, but that does not account for how this feature appears to be intended to operate from the point of view of a PHPUnit user. If I have a static class which looks like, for example:
... and if I want to modify this static field for the duration of a single test:
Then, as things are documented I should expect the "backupStaticAttributes" feature to cause this field change to be isolated to this single test. This bug means that whichever test first loads the class in question will "win" and its static changes will leak to all other tests in the same run. It is not clear to me that this is easily fixable, but it is a real bug. Please could you reopen the issue? |
Perhaps the That wouldn't fix the issue, but at least it would give a warning when it occurred, which might save people lots of time tracking down mysterious bugs that depend on the order in which tests are run. |
@RichardBradley Thanks a lot for the elaborate description and thanks @thehereward for redoing an isolated test case. I understood the problem now, and I think I also noticed that behavior already. Especially with autoloaded classes, statics in newly loaded classes will not be reset, and worse, the list of statics to backup increases over time (because a new static of the previous test becomes a preexisting static to backup in all subsequent tests). I think that's worth to investigate and fix. However, due to various issue references (unintentionally unquoted test data provider #1 as well as PHP stack trace frame #1), this issue continues to get automatically closed by GitHub. Can we move this into a new issue, using the last comments as a good, initial summary? |
OK, now recreated at #1372 |
…n\Template\Template::setVar() expects array<string, string>, array<string, int<0, max>|string|null> given."
…n\Template\Template::setVar() expects array<string, string>, array<string, int<0, max>|string|null> given."
Basically, when using autoloading, the framework cannot have access to a certain class until it's autoloaded. Then, if the first test case stored something in the static scope, it will be available to all the subsequent tests cases and, if someone access the static scope, it can breaks a test with an unexpected behavior. It's an edge case.
I created some example files to show this: http://github.com/eriksencosta/phpunit-bsa-edge-case
Just run AllTests and see that the assertEquals calls fails. Then, uncommenting the 14th line from OneTest will cause the tests passes (or just checkouts the "pass" branch).
One solution I thought was to replace the registered autoloaders with rewrited copies that would call GlobalState::backupStaticAttributes() when the class was first loaded (something like what MockObject do when create the mock with a class skeleton).
For this, backupStaticAttributes could be refactored and a specific method would backup the static attributes of a newly loaded class. All the subsequent calls would behave as expected because as the class name would be returned in the get_declared_classes() call of GlobalState::backupStaticAttributes().
Maybe with the backupStaticAttributes = FALSE recommendation, this could be an unnecessary effort. But while the option exists, some people will eventually have problems with this, maybe thinking is misusing the option.
The text was updated successfully, but these errors were encountered: