Posts tagged behavior-driven development
In the Preamble to this Manifesto, I set out the basic proposal for direct integration of support for applying Behaviour-Driven Development (BDD) to the Zend Framework. The ideal was to move away from line-by-line setup and manipulation of Zend instances towards a more simplified model which is standardised for any PHPSpec specs.
This morning I merged the experimental branch for the implementation of the Zend Framework specific PHPSpec_Context into the main trunk for release in PHPSpec 0.3.0. Documentation of the Zend Context will be completed within the next day or two and added to the growing PHPSpec Manual at http://dev.phpspec.org/manual now available.
The main customisation required to get the Zend Context operational is to set up elements of the FrontController, I’ve selected two primary methods. The first is to use several static methods on PHPSpec_Context_Zend (addControllerDirectory() and addModuleDirectory()) and a more flexible addFrontControllerSetupCallback() which will accept a custom function or static method reference to execute. The former is handy since you can easily organise your bootstrap file into a static class and segregate FrontController, Dispatcher, Action Helper, etc. elements you are using to customise how the Zend Framework operates. Both can be called from any file included into a Context file (e.g. SpecHelper.php).
Here’s a really simple example of a Zend Framework spec. I’ll post a more in-depth tutorial next week once the Manual is finalised, and some final cleanups applied (e.g. allowing for Router specification). The only priority for basic operations left is an implementation of a Zend_Factory class to allow you to replace objects directly instantiated within controllers (to maintain the golden standard of specifying/testing controllers isolated from it’s dependencies). We’ll really start kicking some ZF ass when PHPMock has an initial devel release!
class DescribeTwitterController extends PHPSpec_Context_Zend
public function itShouldDisplayHomeTweetsFromDefaultRetrieveAction()
$this->response()->should->haveText(‘Tweets From Twitterers Followed:’);
public function itShouldPostTweetOnSendActionUsingPostData()
$this->post(‘send’, array(‘message’=>’@padraicb: All your specs are belong to us’));
$this->response()->should->haveText(‘You submitted a new Tweet!’);
public function itShouldRetrieveMessagesForUserIdInParamsFromRetrieveAction()
It’s obvious this is bare minimum. There is still a lot of ground to cover incl. integrating PHPMock, so you can literally mock/stub the Twitter service package being used in the controller action itself (Note to Matthew – implement Zend_Service_Twitter already…;)) and set expectations of how the Controller should use that Twitter service. Adding some basic HTML/XML safe Matchers would also add some fairly substantial help for specifying what the response output should be, or what template any controller action should render.
But the basics, and in short the most time consuming, bit of integration to get something working with the Zend Framework at a level not requiring any devious workarounds is now complete. The weekend should see some really useful additions to this base. Your comments are most welcome as usual whether here, or on the mailing list.
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.