My plan was always to use behaviour-driven development in my project. In an earlier blog post I talked about how I’ve used my supervisor meetings to clarify requirements and translate these into features. At this stage in the project I now have a bunch of signed-off features, all of which can have an automated test associated with it.
These features are written in Gherkin syntax, i.e. Given, When, And, Then, and I had always planned to use Cucumber to make these features executable. Many flavours of Cucumber exist: it was originally built for Ruby, but now there are other variants such as CucumberJS (JavaScript) and Lettuce (Python).
Given that I’m writing the business logic of my application in PHP, it would make sense to use a PHP equivalent of Cucumber. The most popular of these is Behat. All of these BDD frameworks I’ve named thus far do much the same thing: they allow you to parse features written in Gherkin syntax, write the corresponding step definitions and therefore run your features as a higher-level test.
Matthew Daly’s blog post about testing PHP web applications with Cucumber discusses Behat as a possibility, though he opts for using Ruby and Cucumber because:
- He cites RVM as being a useful tool for running multiple instances of Ruby.
- RubyGems makes it easy to install Cucumber’s dependencies.
- The Cucumber community appears to be very active, which suggests that using Cucumber over something like Behat would be a safer investment of time.
- Why not? He finds little “problem switching context between writing Ruby code for the acceptance tests and PHP code for the application itself”.
I looked into Behat and found that, for me, the biggest reason to stay away is its syntax. Behat requires that you define your step definition as a concatenated function name, i.e. “Given I am in a directory” => “function iAmInADirectory”. You also need to comment above the function declaration with metadata. This is the example in the Behat quick introduction:
/** * @Given /^I am in a directory "([^"]*)"$/ */ public function iAmInADirectory($argument1) { throw new PendingException(); }
This just isn’t as clean as vanilla Cucumber and Ruby:
Given(/^I am in a directory (.+)$/) do |argument| # pending end
I see nothing wrong with highlighting the fact that my application and my BDD testing framework are independent of each other by using different languages for each. As a software engineer, I’m simply using the best tools possible for both jobs. As a bonus, using Ruby & Cucumber for BDD discourages coupling: if I were to use Behat, it would be possible to come up with awkward hacks like directly including PHP classes from my application as part of the integration tests, which is just plain wrong. And it certainly doesn’t hurt that I’ve already got quite a bit of Cucumber experience, albeit in a Rails assignment at university.
With my decision justified, I’ve started writing my Cucumber integration tests, yesterday getting my first one to pass locally. Hooking up to Travis is proving to be a bit of an issue, as the Cucumber tests require a PHP server to be running so that the application can be rendered and tested (but Travis only supports one shell window at a time). I’m hoping to crack that today, then work through the step definitions for the rest of my features.