We had notable successes using Jasmine, however to my mind it never quite felt like our project management and development workflows were converging in true agile style like the text books seemed to allude to.
Havells-Sylvania’s global website was our first major Symfony 2 project of the year. It was immediately apparent that many of the highest value features would centre around a product finder, which would allow customers to quickly locate a product within a catalogue of over 7000 SKUs. We eventually went on to implement this as a snappy Backbone.js web application backed by Elasticsearch powered webservices. Given this was our first PHP project since committing to BDD, we took some time to look at the tools available to us.
We’d heard of Behat and PHPSpec before and were considering all options. However once Pete opened a presentation called ‘Full stack BDD for Symfony2′ from Symfony Live back in June, it looked like the search was over. Full stack BDD delivers a BDD ‘toolset’ using the 2 aforementioned components, Behat and PHPSpec (specifically the 2nd version phpspec2). I say ‘toolset’, because a large proportion of the success we found with full-stack BDD was not due the tooling alone, but actually came from the changes in our development workflow and sprint planning that it enabled.
The website went live in December and given that we’ve worked on a number of sprints since, I wanted take this opportunity to share the successes and challenges we’ve experienced in adopting the approach. I intend to write this over 2-3 posts and I thought a good place to start would be a quick retrospective on the successes Behat + PHPSpec has delivered.
*SOC – Separation of concerns http://en.wikipedia.org/wiki/Separation_of_concerns
*Subject under specification - http://everzet.com/post/33178339051/sus-collaborators
Now that may all sounds very good, ‘just how much of that Kool-Aid did he drink?’ you might be asking yourself. Hopefully a quick intro into full-stack BDD and an overview of the workflow might help me justify some of these claims.
If you Google ‘full stack bdd’, apart from a Scala presentation from 2010, pretty much everything is related to Konstantin Kudryashov’s (@everzet) and Marcello Duarte’s (@_md) talk which leads me to believe its a term they’ve coined for their approach. Once you read a little bit more into it however you’ll see it’s exactly in line with ‘outside-in development’, which I understand was established in The RSpec Book. As a result it’s very easy for me to doctor an core diagram in that book, overlaying Behat and PHPSpec in the appropriate places.
The RSpec Book goes into great detail regarding this outside-in approach so I’m going to provide an overview of how this approach worked for us.
The workflow kicks off by taking a user story from the sprint backlog and fleshing out the business scenarios which encompasses it. It was quite a tricky activity to start with, but once we got going we were capturing these scenarios directly in Trello with the whole team (backend, frontend, design) and client involved.
As a result, the user story
As a customer in order to find a product more easily I can filter a list of product lines by application might be broken down into:
I will be shown a list of available applications for that category
When I select an application I will be shown a list of product lines for that application
I will be able to view the products relevant to my search results
We now had the green light to crack open Sublime Text in order to start fleshing out Behat features. In doing this we would take each scenario and expand them into Scenario Outlines adhering to the Gherkin syntax ‘Given, When, Then’.
The scenario ‘I will be shown a list of available applications for that category’, might become:
Given I want to search for product lines
And I want to filter by the category ‘Tracks’
When I request this in the ‘json’ format
Then I should see valid JSON
And I should see the filter ‘application’ with the values:
| name |
| Restaurant |
| Museum & Gallery |
Once a scenario was fully defined (we sometimes went back to the wider team for clarification), we were able to start coding the Step Definitions, with each developer picking the scenarios they were best placed to eventually implement. Even though this was the first point we were writing any PHP, we weren’t writing application code. Moreover, Behat sees you using it’s API to automate the user behaviour you had previously defined on paper.
#2, #3, #4
Once we had defined a step definition it was possible to move inwards. You can only do this by running your Behat command and watching it fail. Early on in the project you’ll find most initial failures come from routes not being configured. So the first thing is to sort those out and any wider Symfony config, re-run Behat, at which point it is likely to tell you you’re missing a controller.
Now, whereas a non TDD/BDD approach would see you jumping straight into the ‘src’ directory, fullstack BDD rains you in and turns your attention to the ‘spec’ directory and PHPSpec. From this point onwards you are following the classic xDD idoim test-code-refactor. However, there are plenty of reasons why PHPSpec2 makes it very quick and easy to develop in this way, all of which I’ll cover in part 3. Suffice to say, having gone through #1 and #2 above we found ourselves much more equipped with business knowledge to start writing our specs and implementations.
Once you go through a number of test-code-refactor loops in PHPSpec you can ‘extend and escape’ back to Behat and run your scenarios again. Hopefully at this point you’ll see a green light, however if you don’t its not a problem. All a red light means is your implementation, although it passes its specs, doesn’t quite meet the business requirements. We found ourselves repeating #3 – #6 for a given step to be quite a common occurance.
A green light in Behat was our signal to move to the next step in the scenario. Then, once we got a scenario finished and eventually a feature, we were able to head back to our Trello board, move the card into QA and repeat the whole process. We did of course revisit the feature again if the requirements changed or it failed QA. However, I’ve hopefully I’ve demonstrated how this workflow goes a long way to preventing you failing QA because of implementation bugs (i.e problems with your specs). If you are following the steps closely enough, in theory only bugs that can get through to QA are those which exist in your Behat features, in other words in your understanding of the business requirements.
In the next issue of this post I’m going to cover a few practical examples of how the successes above were delivered using Behat and PHPSpec.