A better behavior driven syntax

Don’t get me wrong, I love Gherkin.

Behavior driven development has done some good things and cucumber, specflow, JBehave, NBehave, Jasmine, et al. have done wonders for improving test readability and communicating tests in business language.

You know “Given, When, Then”

But…

First of all, let’s not kid ourselves.  That’s not English, that’s programming syntax.  Change “Given” to “Let” “When” to “If” and keep “Then” just the way it is and you’ve just invented BASIC.  Or a small subset of BASIC with regular expressions.  Or rather a small subset of regular expressions.

You get rid of line numbers, but you also get rid of punctuation — which some people feel is a good trade off, because business people (who never read tests anyway) are afraid of numbers and punctuation.

Enough ranting, though.

Here’s an example of a Gherkin test:


Given some precondition
When some action is performed
Then some expected result should be verified.

It sounds good enough.  Very chronological and logical… to a procedural programmer.

Don’t get me wrong.  I love procedural programming.  I first learned to program procedurally  (in BASIC).  But we can do better than that these days.

Here’s a function in plain English:


When some action is performed
Given some data
Then some result should be returned.

Notice the difference?

It’s reusability.  

The same function with different data creates different outcomes.  The function — action — can be reused and only the inputs and outputs change.

Some people try to handle this with Gherkin language by placing the data — the conditions — in the “When” segment.  I’d say this is a common approach.

Scenario:
   Given everything is normal
   When some data exists
   Then some expected result should be verified.

Both the preconditions and action are implied.

A common pattern that tries to get data reuse is to create a scenario outline with examples:

Scenario Outline: 
   Given some <precondition>
   When I act on some <data>
   Then I should have some <expected result>

   Examples:
     | precondition | data | expected result |

My first complaint is that if you have multiple preconditions, you should probably have multiple tests.

The second is that you can have a proliferation of data.  This is the same problem Fitnesse ran into.

The third is that the action is still implied — sometimes stated explicitly scenario or the feature.

The action is what you want to test.  It should be front and center.  It is reusable.  It takes an input and has a variable output based on it.

The  scenario is the data.  The preconditions if you will.  But the preconditions are just data that is acted on to “setup” the action under test.

The expected result is tied to the scenario.

My proposal is simply that we write our tests in a slightly different way, which allows for clearer visibility of coverage and scenarios.

Rather than a scenario with a:

  1. Precondition
  2. Action
  3. Expected Result

We should have an action with a:

  1. Scenario
  2. Input data
  3. Expected Output
Action: When I do something
   Given some scenario
   Then I should observe some expected result

I think this leads to more usability and better identified the difference between precondition, action, and data.

Action: When I do something
Given some scenario
For some <input>
Then I should observe some <expected result>

| Input | Expected Result |

It also makes implementation of tests easier.  You now can focus on creating reusable fixtures — this is one thing Fitnesse got right. It makes for better data drive tests as well.  Where your examples are come from your data provider.  Which allows creating more scenarios.

An action is reusable with multiple scenarios.  This is the setup.

A test 
has one or more scenarios
and has one or more data values
that each have one expected result per data value, per scenario.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s