BDD & Behat: Avoiding implementation in features

Warning: This post is over a year old. The information may be out of date.

While giving my BDD & Behat talk recently, I was asked an interesting question by a tester about how to avoid writing implementation in feature files.

It’s something I’ve struggled with myself before - and still do now at times.

I cover the subject of implementation in features during my BDD talk.

Ideally, feature files are written before implementation happens. They’re written based on conversations as part of the BDD process with multiple stakeholders and aren’t just written by developers while they’re building a feature.

But this isn’t always the case, Behat isn’t always used purely as a BDD tool. So often it’s used as a testing tool to test things through the UI.

It’s so easy to write…

Scenario: I can add a product to my basket
 Given I am on "/products/playstation-4"
  When I press "Add to basket"
  Then I should see "Playstation 4"

…as a scenario when a developer is writing it having already thought about (or even implemented) the design and functionality. Functionally this scenario works if testing it through the UI. But what if the user were doing this via a native mobile app? Or the command line? Or as a physical action? There are no URLs or “add to basket” buttons in a physical impementation of this scenario.

If you’re still struggling with writing implementation in feature files (and you’re doing so without your scenarios being a part of conversations before even designing code - yes, even in your head), ask yourself this question (as I have done in the past):

What if the user was performing this via [insert-other-method]?

Another way to write the scenario above is:

Scenario: I can add a product to my basket
 Given a "Playstation 4" is available in the store
  When I add the "Playstation 4" to my basket
  Then I should have a "Playstation 4" in my basket

Behind the scenes, you can still test a scenario such as this through the UI using something like Mink. However, now the scenario only documents the business rules (and value) and doesn’t care how it’s implemented, just that it is.

Now, because of this - if your implementation changes, your feature file outlining and documenting the business rule(s) doesn’t have to change!

You can use this scenario to test a native mobile app, the UI of a web interface, a command line app, even the domain / service layer at a lower level!

Lovely, isn’t it?

tl;dr: Don’t write implementation in features, avoid doing so by considering if other implementations could be described or tested by your scenarios.

Edit: Ciaran McNulty shared some thoughts with me on this subject on Twitter:

It’s good to separate design from implementation. Before you even start designing, write these scenarios, then you’re capturing the “business thing” and not the design you’re already thinking about.