PHPUnit 3.5: Less $this Required
The feature discussed below has been removed from PHPUnit due to community feedback.
Over the years, I have gotten quite a few "complaints" from PHPUnit users that they do not like typing $this-> as often as they have to:
<?php
class StackTest extends PHPUnit_Framework_TestCase
{
public function testPushAndPop()
{
$stack = array();
$this->assertEquals(0, count($stack));
array_push($stack, 'foo');
$this->assertEquals('foo', $stack[count($stack)-1]);
$this->assertEquals(1, count($stack));
$this->assertEquals('foo', array_pop($stack));
$this->assertEquals(0, count($stack));
}
}
?>
As of PHPUnit 3.5, they can write test code that requires less $this-> statements:
<?php
require_once 'PHPUnit/Framework/Assert/Functions.php';
class StackTest extends PHPUnit_Framework_TestCase
{
public function testPushAndPop()
{
$stack = array();
assertEquals(0, count($stack));
array_push($stack, 'foo');
assertEquals('foo', $stack[count($stack)-1]);
assertEquals(1, count($stack));
assertEquals('foo', array_pop($stack));
assertEquals(0, count($stack));
}
}
?>
Here's hoping that this makes some people happy :-)
Defined tags for this entry: phpunit
16/08/2010 at 16:58 Permalink
Reply
16/08/2010 at 17:00 Permalink
Reply
16/08/2010 at 17:49 Permalink
I mean PHPUnit is a great quality tool which promotes good practices in the PHP world. In my opinion, these global functions are exactly what you are fighting against.
Reply
16/08/2010 at 17:57 Permalink
Reply
16/08/2010 at 18:07 Permalink
Next question will be why they need the method and class wrapping the tests. And they would be right in asking so.
And if they are that lazy, they are probably not writing tests anyway.
Reply
16/08/2010 at 20:43 Permalink
Reply
16/08/2010 at 21:37 Permalink
Reply
17/08/2010 at 08:13 Permalink
at => assertTrue
ae => assertEquals
...
--
Wil Moore III
Reply
17/08/2010 at 08:23 Permalink
Reply
16/08/2010 at 17:29 Permalink
it's 7 characters and, if you type properly it takes less then half a second $this->... there see....
Reply
16/08/2010 at 17:43 Permalink
Reply
16/08/2010 at 18:08 Permalink
Reply
16/08/2010 at 18:51 Permalink
This is a perfect example of why namespaces are useful. For instance: place all functions in a 'PHPUnit\functions' namespace. It would become an optional feature just for PHP 5.3+ users.
Reply
17/08/2010 at 10:15 Permalink
Reply
16/08/2010 at 19:28 Permalink
Reply
16/08/2010 at 20:11 Permalink
Altought I'm not really familiar with PHPUnit, from what I've seen in Functions.php, no function call was really "oriented" to the testcase itself, so using them on $this fashion was more like a matter of keeping all functions on a single place than applying Object Oriented logic.
As a matter of fact I don't think it makes much sense that class TestCase should extend Assert - or am I missing something? As a rule of thumb I suppose you'd subclass if TestCase "is a" Assert.
It seems that at some point at the past (and it's just a fictional guess) the test cases looked like PHPUnit_Framework_Assert::assertEquals(0, count($stack)); but it was too "static" and too long to type. Then at that time it could have made sense to extend Assert so it was simpler to just type $this. But I digress.
So for me it looks more sane to use the static functions from Assert class than extending it.
I'm also not really familiar with PHP's namespace functionality, but on some other languages you can have the package functions exported to the current scope. Coming from such background it makes sense if we could "use" Assert which exports all the functions without the need of a script defining global functions as gateways. Assuming PHP can't export from Assert into the current scope, Functions.php is fine.
Anyway, keep up the great job - whatever way community prefers =)
Diogo
Reply
16/08/2010 at 20:32 Permalink
Reply
16/08/2010 at 23:20 Permalink
looking at your api most of these methods return void, so perhaps they could return self and then the methods could be chained, this would cut down on some of the $this usage (although i don't see it as a problem myself)
Reply
17/08/2010 at 08:54 Permalink
This shows me again, that the most PHP-Developers are idiots (unless they wouldnt have complaints)! Now you pollute the globales Namsepsace: Very nice! I bet for an beer that someone out there will have the Problem that he need to integrate PHPUnit with an other Software and both introduces an asert*() function. Welcome in hell.
And please, do not say Namespaces.
Reply
17/08/2010 at 09:07 Permalink
$this->assertEquals('foo', $stack[count($stack)-1])
->assertEquals(1, count($stack));
->assertEquals('foo', array_pop($stack));
->assertEquals(0, count($stack));
Reply
17/08/2010 at 09:30 Permalink
Reply
17/08/2010 at 10:03 Permalink
You can alias the namespace, but IMHO it looks ugly.
Reply
17/08/2010 at 10:17 Permalink
So, I'd vote for having assert* functions, although... there's a little problem. These functions would be defined in the global scope for the moment, but I'm sure Sebastian intends to move them into their own namespace later on. Unfortunately this means that people would need to prefix those functions with the PHPUnit namespace or some alias for that namespace, because PHP cannot import all defined functions inside a namespace.
So, what I'd do then is to provide an Assert or assert class that would contain static methods like equals, isTrue, isFalse and the like. That would allow people to write:
assert::equals($expected, $actual);
One downside, static methods are slower than instance methods or functions, but I'm not sure this is such an important issue in test cases.
Other option is to let them like there were supposed to be in this 3.5 release, and later on, put them in a PHPUnit namespace that a user can alias to "assert" and remove the assert prefix from the functions:
use PHPUnit/Assert as assert;
assert\equals($expected, $actual);
Unfortunately this looks ugly, at least for me. That's why I still prefer an Assert class with static methods. And this would also allow subclassing, while providing shorter names.
Reply
17/08/2010 at 10:52 Permalink
A fluent interface would be fine in case we need multiple assertions in the same test, but functions... I'm glad it has been removed.
Reply
17/08/2010 at 12:04 Permalink
Reply
17/08/2010 at 13:14 Permalink
Reply
17/08/2010 at 10:55 Permalink
I do like the idea of fluent interfaces though! I'm already very fond of it when making mock objects.
Reply
17/08/2010 at 14:54 Permalink
>> and won't mind putting a few extra $this variables in their code.
Except that the assertion methods are not Object Oriented.
Reply
17/08/2010 at 13:37 Permalink
Reply
17/08/2010 at 15:03 Permalink
-Pete
Reply
27/02/2011 at 19:17 Permalink
Using vim you could either simply make a map that types "$this->assert" for you. For example: putting "nmap a i$this->assert" in your vimrc file allows you to simply type \a to insert: $this->assert
Or even better, use the SnipMate plugin and create your own phpunit snippet, so that no only will it auto-complete "$this->assert" but will even give you a dropdown list of all the assert methods there are to choose from, as well as being able to create snippets for mocks and other things so you can Tab to each next insert point.
I appreciate how well Sebastian listens to all his types of users and in the end went with the smart rather than the lazy and misguided.
Reply
18/08/2010 at 14:23 Permalink
Yes, globals are ugly in most cases, but this is an optional feature that actually makes the code more readable.
I would rather see PHPUnit offer some options to those who like to write less code for the same functionality than forcing a specific style of usage.
PHPUnit is becoming the tool of choice for all test coding in PHP so being open to different styles of coding should be allowed.
To give an example, look at PHPUnit's Mock implementation.
It uses the is that it has an abundance of methods - so it is hard to remember all of them. When using Simpletests mock library I can remember the few methods I need. With PHPUnit I must look it up again and again. I often have to think more when reading code written with the fluent interface than the simple calls that Simpletest uses.
So +1 for keeping the functions. They make the code a bit more readable - at least for me. And maybe I'll use the clicks to write an extra test.
Reply
11/10/2010 at 12:38 Permalink
lubosdz
Reply
25/11/2010 at 15:04 Permalink
Reply
10/03/2011 at 16:34 Permalink
$ phpunit --verbose --debug t.php
PHPUnit 3.5.13 by Sebastian Bergmann.
Class PHPUnit_Framework_Assert could not be found in /home/chammers/t.php.
Maybe you should remove the file if it is no longer supported.
Reply