phpunit: Usage of asserts is incorrect?
It’s not a secret that all asserts in PHPUnit are in fact static methods, but everyone are using them as they are not, even official documentation.
I think I understand the reasons, why they were made static in first place, probably it is related to performance (btw, do other reasons exists for that?).
But in my own opinion, if they are static, we should use them as we use other static methods to make our code cleaner.
This means using:
self::assertTrue(...);
instead of:
$this->assertTrue(...);
Can anyone give me a good reason why we shouldn’t?
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 39
- Comments: 19 (8 by maintainers)
Links to this issue
Commits related to this issue
- phpunit self::assert... -> $this->assert... https://github.com/sebastianbergmann/phpunit/issues/1914 — committed to NovikovRoman/simpleRating by NovikovRoman 8 years ago
- [TEST] $this->assert* should be used See https://github.com/sebastianbergmann/phpunit/issues/1914#issuecomment-148407321 — committed to mhujer/elasticsearch-php by mhujer 7 years ago
- [TEST] $this->assert* should be used See https://github.com/sebastianbergmann/phpunit/issues/1914#issuecomment-148407321 — committed to mhujer/elasticsearch-php by mhujer 7 years ago
- [TEST] $this->assert* should be used See https://github.com/sebastianbergmann/phpunit/issues/1914#issuecomment-148407321 — committed to mhujer/elasticsearch-php by mhujer 7 years ago
- [TEST] tests code cleanup (#618) * [TEST] use ::class instead of classname string Reason - when the class is renamed or removed, it will be detected much faster. It helps with the static analysis... — committed to elastic/elasticsearch-php by mhujer 7 years ago
- [TEST] tests code cleanup (#618) * [TEST] use ::class instead of classname string Reason - when the class is renamed or removed, it will be detected much faster. It helps with the static analysis... — committed to p365labs/elasticsearch-php by mhujer 7 years ago
- [TEST] tests code cleanup (#618) * [TEST] use ::class instead of classname string Reason - when the class is renamed or removed, it will be detected much faster. It helps with the static analysis... — committed to p365labs/elasticsearch-php by mhujer 7 years ago
- Use `self::assert*()` instead of `$this->assert*()` — committed to doctrine/dbal by lcobucci 7 years ago
- - Removed `create_function()` function usage — committed to magento/magento2 by joni-jones 6 years ago
- Rule for checking a dynamic call on static methods — committed to phpstan/phpstan-strict-rules by lookyman 7 years ago
- Follow the standard to use this instead of self https://github.com/sebastianbergmann/phpunit/issues/1914\#issuecomment-148407321 — committed to justcarakas/forkcms by carakas 6 years ago
- Follow the standard to use this instead of self https://github.com/sebastianbergmann/phpunit/issues/1914\#issuecomment-148407321 — committed to justcarakas/forkcms by carakas 6 years ago
$this->
instead ofself::
I still fail to see the motivation behind keeping things as they are.
Great then.
Fair enough. But still, we’re15 years later, 6 major versions of PHPUnit have been released since then, slowly forgetting this heritage doesn’t look like a big deal.
Now that’s a good point.
This is where I get lost. You’re giving all your reasons to keep the methods static, yet you advise users to call them dynamically, with no explanation whatsoever.
Why on earth should we call them dynamically?
What is the reasoning behind the statement?
Its what I do, but why is it considered the ‘right’ choice?
https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.static-vs-non-static-usage-of-assertion-methods
I understand the reasons above (and I find them reasonable), but maybe there can be a slight change? With growth of static analysis tools for PHP this could provide unnecessary warnings, because in most other cases if you call a static method non-statically that might be an error.
I think that it is certainly useful to allow reuse of asserts and doing it by static calls is perfectly fine in this case, but maybe there could be different behavior directly on TestCase? I mean instead of extending
PHPUnit_Framework_Assert
why not just call the static method in a new non-static method with the same name?That means that the API would stay the same - obviously other than the static change, but maybe that is not a big BC break, because everywhere is written to use
$this->
with these methods?I would advocate to call methods with respect to their declarations as well.
For all who want’s to automate choosing his way of usage of assertions, PHP CS Fixer can do it for you with
php_unit_test_case_static_method_calls
rule - it can be configured to ensure assertions are called in unified way -$this->
,self::
orstatic::
I feel with you. With higher phpstan levels you face the same thing in the default behavior of reporting. It is a code smell - totally. And I think it should be fixed up in one direction, both for usage and docs.
…and I almost went to PhpStorm bug tracker to submit a bug, that $this->assert… IDE suggestions don’t offer anything, but the code still works. I thought I was going insane…
I have thoroughly analyzed PHPUnit’s
TestCase
andAssert
code, and unless we are going to declare willfully disregarding the static method calls are OK, then such an important code quality tool as PHPUnit should have code written for it usingself::assertEquals()
vs. the contextually ambiguous$this->assertEquals()
.Or, PHPUnit needs to have a third class that does something like
Then extend
TestCase
againstAssertLogic
. Then literally everyone can be happy, at probably minimal overhead. (if the news are too much, thenprivate static $asserter
.For anyone that is interested we have since moved to using
Assert::assert*()
methods directly. Since these are basically functions (no state) and do not need to be connected toTestCase
, it makes more sense.The only downside is that you have to add use for
Assert
(and potentially other classes), but I don’t mind that at all. Plus it becomes clearer if you use some custom asserts where they come from and you don’t have to “register” them in TestCase either.Static anlyzers, IDEs, everything is warning and complaining about this. Why is this then an issue for those to report if it was totally “acceptable”? Sure, technically it is fine, but conceptually?
I like this idea 👍
But to better comply with PHPUnit standards, I won’t be calling
Assert::assert*()
statically, I’ll prefer:…
I can see value in the assertions being declared statically, this probably allows for better code reuse.
But I cannot see the value in calling them via
$this
- It would be impossible to change the assertions to need object context because it would contradict the reason of code reuse, it would be a very breaking change.If anything it just hide the fact that they are static and reusability.
I think the reason for static assertions is:
What’s the point of fixing tools if we can fix the documentation?
Fix the tools!
I thinks is great that the methods are defined as static when they are not using
$this
.Please also notice:
In other languages like C# its event a hint that if some method don’t access instance data (don’t use
this
) can be declared static https://msdn.microsoft.com/en-us/library/ms245046.aspxCalling a non-method method statically generates on PHP 5 E_STRICT & on PHP 7 E_DEPRECATED. But not the other way around. Call a static method non-statically is fine.
👯