PHP, Zend Framework and Other Crazy Stuff
Archive for November, 2007
Mocks, Stubs, And SimpleTest Wins
Nov 10th
The word is that SimpleTest is moving towards PHP5 in the near future which is great news for all Mockists in PHP. When I moved to PHP, SimpleTest became the main ingredient in many a coding session up to 2 in the morning but once PHP5 gained traction and I was seduced into leaving PHP4 behind I found myself relying more heavily on PHPUnit. Not that SimpleTest is anti-PHP5 in any way (only some small things and obviously E_STRICT giving it a heart attack), but more projects I didn’t control leaned heavily towards PHPUnit once PHP5 took off.
Why the noting of SimpleTest? Because it’s a Mockist library. Between PHPUnit and SimpleTest, ST under Marcus Baker’s leadership stomps all over PHPUnit for Mock Object support, and has done for years. PHPUnit is a great Unit Testing library, but I just don’t like it when applying TDD (or even some limited BDD before recently). The SimpleTest documentation (which is itself deceptively simple) is basically a TDD tutorial which runs you through basic Unit Testing, how test-first approaches lead to better design decisions, and how Mocks and Stubs make designing even better by exploring the interactions between objects (i.e. SimpleTest’s introduction to TDD is behaviour driven) and server resources.
PHPUnit has always seemed to attract people who prefer to test state, or use Stubs predominantly (hand coded objects with fixed return values), or at a minimum those who can endure the lack of Mock Objects in their lives. I prefer none of these – being behaviour focused. I find it really hard to work with a Unit Testing library that first spent years ignoring Mock Object support, and which then bundles one which is a) a bit foggy, and b) rarely used or highlighted anywhere, and c) useful mainly on a hit or miss basis (some nagging missing features).
Is this short sightedness on my part? Maybe it’s just a matter of development styles? I am afterall relatively new to PHPUnit – SimpleTest has served all my needs previously since time began. What does the atypical PHPUnit user do though when they need a Mock Object or Stub? Hand code it???
I’ve become more interested in Mock Object frameworks recently, mainly to see the broad range available (count them for Java or Ruby and you get quite a collection) before dabbling in one for PHPSpec on the premise a loosely coupled Mock Object framework has value beyond PHPSpec (which I’m sure it does – phpt + mocks would be interesting, but other uses suggest themselves). PHPSpec + PHPMock = BDD At Last.
My vision is still pretty SimpleTest tinted. Noting this is only one part of PHPUnit I’m bashing, but the PHPUnit MO API leaves too much to be desired. It looks quite cute – PHP5, fluent interface, etc., all fluffy and friendly – but the fluent interface doesn’t flow naturally, and it seems fickle to a fault. Surely my syntax opinions are questionable, but I just like to have one that doesn’t need to be memorised so precisely and flows more intuitively. Handling of indexed method calls with parameters would also be nice – nearly everything I do with Mocks/Stubs needs it at some point. Dropping the fluent interface entirely might actually be an improvement until (if) it’s changed.
Is syntax really that important? I know Rubyists would have fun debating the benefits of Mocha vs Flexmock vs rspec mocks. Nearly the whole argument ends up being a syntax choice coloured by your approach to TDD or BDD. Some like to use real objects, others stubs, others mocks, and others even partial-objects that are more real than stubs but not production quality. Martin Fowler even has a wonderously clarifying post on Mock Objects and Stubs, and the kind of people who prefer each. Going by it, SimpleTesters who refuse to get with the popular program of PHPUnit (lots of them about still
– many live over on Devnetwork) seem to more likely be inclined towards the BDD-related style of TDD – focusing on behaviour and object interactions over state and simple verification.
I mean here’s a quick thought. PHPUnit’s standard Mock Object example:
[geshi lang=php]$observer = $this->getMock(‘Observer’, array(‘update’));
$observer->expects($this->once())
->method(‘update’)
->with($this->equalTo(‘something’));[/geshi]
Seriously – this is just horrible! What about:
[geshi lang=php]$observer = $this->getStub(‘Observer’, array(‘update’));
$observer->shouldReceive(‘update’)->once()->with(‘something’);[/geshi]
Anyone see a difference? Obviously, with all my moaning above I prefer the second. It’s simpler, less typing, reads like plain English (I seem to note that a lot recently
), does the same thing, and just feels cleaner. I used Stub since it’s slightly more accurate for what this is doing – a canned response from an otherwise real object. SimpleTest refers to these as Partial Mocks; respects to Marcus but I still consider them Stubs with partial Mock behaviour – just to be vague, difficult and convoluted
.
Personally though, this is all enough to convince me SimpleTest remains the Mockist’s hero. PHPUnit is all shiny and bespeckled, but it’s just not working for me since I rely heavily on Mock Objects and really really don’t like writing Stubs (except for server/slow resources) if I can help it.
PHPSpec Manual (Work In Progress)
Nov 6th
Just a quick update. I started writing a draft manual recently, so I’m publishing it online at:
I’ll keep adding to it over the days, weeks and months ahead. The current form is going to be mainly a draft. When it’s done, I’ll go through it and do some serious editing. Next priority is getting in the material on actually using and implementing PHPSpec…
The PHPSpec 0.2.0devel API
Nov 5th
I had a request to make a very quick summary of the PHPSpec API for the current development snapshots over on http://dev.phpspec.org. We’re lacking documentation for right now, so here’s a brief overview.
First of all, since this is a relatively short-life development period, there are a few basic assumptions in place for now.
1. One spec class per file
2. The file name reflects the classname
3. Spec classnames start with “Describe”
A current valid spec class would be similar to
[geshi lang=php]class DescribeNewLoggerUsingFileStorage extends PHPSpec_Context
{
public function itShouldCreateCreateNewFileIfNoneExists()
{
$this->pending();
}
public function itShouldUseAnExistingFileIfOneExistsWithoutTruncatingIt()
{
$this->pending();
}
}[/geshi]
This based on a plain text spec such as:
New logger using file storage: - should create new file if none exists - should use an existing file if one exists without truncating it
So the filename in this case would be DescribeNewLoggerUsingFileStorage.php. In reality there should be a less restrictive naming scheme but for now it narrows the possible variations while development is progressing.
The PHPSpec_Context class is a bit like your typical xUnit TestCase class. It’s the ultimate parent for all specs. It’s called a Context because each class should describe a class or system of classes for a “Given” or context, i.e. the condition or environment of the class being tested. In the case above, the context is that we’ve just instantiated a Logger which writes messages to a file.
PHPSpec_Context::pending() simple marks an example as awaiting completion.
We can flesh out the spec’s examples (note: a spec is a collection of executable examples) as follows.
[geshi lang=php]class DescribeANewLoggerUsingFileStorage
{
public function itShouldCreateNewFileIfNoneExists()
{
$file = $this->getTmpFileName();
$logger = new Logger( $file );
$this->spec(file_exists($file))->should->beTrue();
}
public function itShouldUseAnExistingFileIfOneExistsWithoutTruncatingIt()
{
$file = $this->getTmpFileName();
file_put_contents($file, ‘Hello’ . “\n”);
$logger = new Logger( $file );
$this->spec(file_get_contents($file))->should->be(‘Hello’ . “\n”);
}
public function after()
{
unlink($this->getTmpFileName());
}
public function getTmpFileName()
{
return sys_get_temp_dir() . DIRECTORY_SEPARATOR . ‘logger_tmp_file’;
}
}[/geshi]
You can execute a spec by using the command line script “phpspec” available also for Windows as a batch file.
phpspec DescribeANewLoggerUsingFileStorage
You can also simple execute all specs within a directory tree using.
phpspec -r
Specs can also be continually re-run using the -a flag.
Back to the full spec example, PHPSpec_Context::spec() method returns an implementation of a Domain Specific Language (DSL) which basically means it’s a specific language designed for Behaviour-Driven Development. This contrasts to an xUnit API based on assertions. The DSL is intended as being more readable, and more intuitive to write examples with.
A very basic call above uses the “be” Matcher, and the “should” Expectation. In PHPSpec, you can state whether any Matcher “should” or “shouldNot” pass. The Matchers presently available (by no means a complete list sufficient for general usage quite yet):
be()
equal()
beEqualTo()
beAnInstanceOf()
beGreaterThan()
beLessThan()
beGreaterThanOrEqualTo()
beLessThanOrEqualTo()
beEmpty()
beTrue()
beFalse()
Scheduled for the next day or two:
beBetween()
beNull()
beOfType()
beIdenticalTo()
beSet()
match() // PCRE Regular Expressions
raise() // Exceptions
trigger() // Errors
In addition, I recently implemented “Predicate” matching. Predicates are basically methods starting with “is” or “has”, e.g. hasMessages(), isPrepared(), hasPlayer(), present in your implementation classes. Using PHPSpec’s predicate matcher you can write an example such as:
[geshi lang=php]$this->spec($someObject)->should->haveMessages();[/geshi]
This calls $someObject->hasMessages(), and compares the result to the boolean TRUE to ascertain a match. Of course the should/shouldNot expectations work here also to interpret whether a matcher result should pass or fail.
Output from PHPSpec is still a bit unintelligent. I have updated it to follow the traditional xUnit output (same style as PHPUnit for example) but data such as error line numbers, and backtraces, and string comparison results are not yet possible. Obviously a big priority before any public release could be finalised
.
We’re homing in on an initial public release but I’ll hold off until minimal documentation is in place. In the meantime, you can download regularly updated snapshots from http://dev.phpspec.org. Note that the tar.gz file is a typical archive, and the .tgz file is a PEAR installable package. The second is much preferred since it will install the necessary script files.
PHPSpec hits Subversion Revision 100
Nov 3rd
What is it? PHPSpec is a Behaviour-Driven Development framework for PHP currently entering it’s fourth week of consuming my free time
.
What is Behaviour-Driven Development? BDD is Test-Driven Development without all the crap that nobody really understands and everyone tends to get wrong anyway, including something called a domain specific language (DSL) that means specs are incredibly readable and clear.
Why is this better? Because it’s easy to get into, requires less experience building, and dumps the traditional Unit Testing API in favour of a domain specific language inspired by Plain English (TM).
Everyone’s favourite question is going to be how BDD differs from TDD, which is entirely valid but a question which usually leads to the short insufficient answer or the long inevitably boring answer. So I’ll try to put it in perspective insufficiently and refer to a much better explanation later in the near future.
Essentially, TDD is performed using a Unit Testing framework. Whether it’s SimpleTest, PHPUnit, Test::Unit or JUnit, it doesn’t really matter since they all share the same common approach. You call everything a Test, and within your tests you assert things. In TDD we advocate the idea of testing before coding – since it leads to better code. But TDD tends to be obsessed with Testing unless explained very very clearly. And because it’s so closely linked to testing, programmers understandably get TDD confused with Testing and think they are facets of the same thing. In fact it’s common to assume TDD is a testing practice, when in reality tests are just the byproduct of a design practice.
BDD takes a slightly different tack. It cheats. Instead of teaching you all about Unit Testing, it just jettisons all that baggage and drops you into the practice of “describing behaviour with specifications”. You do not start with a test for BDD, you start by specifying the behaviour of the system (classes/methods) you intend writing. If that sounds horribly familiar (it should to any experienced hardened practitioner of TDD) it’s because this really is what TDD is supposed to be about – if you can find it in the small print on the last page of all those TDD tutorials or the artfully concealed manual page of your UT documentation.
So with BDD, you identify a system, write specifications for it, and then implement code to the required specifications. If your code coverage sucks, well, what the hell, you’re not testing so unless you have a code coverage of <70% you're probably safe. Why? Because refactoring will naturally generate lots of extra helper classes which do not alter the specified behaviour - and if the specs have not shifted then there's little need to write new specs (more usually worthless effort) for those classes. This raises another symptom of over enthusiastic testers - tests are bound to the structure of classes/functions, not the facets of observable system behaviour. This leads to the totally uncool situation where tests are "brittle" - they change as regularly as your implementing code does. This is different to the brittleness introduced by using Mock Objects, at least Mock Objects do something useful to make their brittleness a worthwhile cost.
There's my insufficient debatable answer in all its meagre glory. To learn more about why PHPSpec is the next best thing since Travis Swicegood's new and glorious PHPT framework (which is introducing it's own optional BDD-Lite syntax, if you read his blog) visit the mailing list, or subversion repository at http://www.phpspec.org. There’s even a rumour of documentation turning up soon.

