Acceptance Criteria Should be Executable
Having covered the debacle at Backwater Bank inc, you would have thought that my last blog had said just about everything there is to say about Agile User Stories. Well, that turns out not to be the case. If you take a look at an example order a cheque book story from the Backwater Bank inc scenario, you’ll see that includes some acceptance criteria:
Title: Order Cheque Book As a customer I want to access my online account So that I can order a new cheque book Acceptance Criteria 1) The bank will only send out a cheque book if the customer is in credit. 2) The user can only request a cheque book if the bank has his/her complete address details.
One of the main problems with writing tests (and yes there are problems) is that you have to test the right thing. One of the ways of doing this is to ensure that your test method names describe the behaviour of the class you’re testing: what it should (and shouldn’t) do. For example, in my tests for the body mass index (BMI) calculator example used in my blog on defensive programming, I’ve got tests named:
@Test(expected = NullPointerException.class) public void test_null_height_input() { }
…and
@Test(expected = NullPointerException.class) public void test_null_weight_input() { }
From these method signatures you can hopefully work out that a null weight or height input will throw a NullPointerException
It was Dan North, in his introduction to behaviour driven development who spotted that you can take this idea one step further. If you can define required behaviour for a simple unit test, then why can’t you define required behaviour for acceptance tests? Taking the ideas from Eric Evan’s book Domain-Driven Design Dan and Chris Matts came up with a “ubiquitous” language for describing requirements by adding the idea of including scenarios with the stories.
Is it me or does the word “ubiquitous” seems to crop up everywhere in Agile? It really just means “Present, appearing, or found everywhere”. In the case of Agile development, you could easily substitute the word “simple”. I think what it really means is that developers should learn the vocabulary of the problem they’re solving rather than the customer learning any development jargon.
Simply put, they came up with four ubiquitous words that in sequence define a scenario. These words are Given, When, Then and And, and they fit together like this:
Scenario: The name of the scenario Given an initial condition When something happens Then this is the result
The word ‘And’ chips in to expand the complexity of the scenario if required:
Scenario: The name of the scenario Given an initial condition And another condition When something happens And something else happens Then this is the result And this is also the result
The way it works is that each story you write will have its own set of acceptance criteria expressed in the Given, When, Then format. For example, looking at the order a cheque book story above, you might come up with something like this.
Scenario: Order a Cheque Book Given the account is in credit And the user has been authenticated And the user's address is available When the user clicks on 'order a cheque book' Then send cheque book to user
…and once you have the happy flow scenario you can then add in all the alternate flows to create a full and useful story that can be used in acceptance testing.
Scenario: Order a Cheque Book, no address available Given the account is in credit And the user has been authenticated And the the bank does not have complete user address details When the user clicks on 'order a cheque book' Then ask user for complete their address
Scenario: Order a Cheque Book, user is overdrawn Given the account is overdrawn And the user has been authenticated When the user clicks on 'order a cheque book' Then refuse to send user a cheque book
Once you have your scenarios they can be added to your story card. For example:
Title: Order Cheque Book As a customer I want to access my online account So that I can order a new cheque book Scenario: Order a Cheque Book Given the account is in credit And the user has been authenticated And the user's address is available When the user clicks on 'order a cheque book' Then send cheque book to user Scenario: Order a Cheque Book, no address available Given the account is in credit And the user has been authenticated And the the bank does not have complete user address details When the user clicks on 'order a cheque book' Then ask user to complete address Scenario: Order a Cheque Book, user is overdrawn Given the account is overdrawn And the user has been authenticated When the user clicks on 'order a cheque book' Then refuse to send user a cheque book
If there’s a case for an ‘epic’ story, then is there a case for an ‘epic’ scenario? If you take a look at my first stab at these scenarios, you’ll see that they are a little vague, untestable and need a bit more work. For example, I said “Given the account is in credit”, which leads to yet more questions:
- How do you define ‘credit’?
- Are we talking about the case where there is a positive account balance?
- Does the user have an over draught limit?
In this case I’m defining ‘in credit’ as a positive balance, which means that I can use real numbers in the scenarios and hence they become real examples:
Title: Order Cheque Book As a customer I want to access my online account So that I can order a new cheque book Scenario: Order a Cheque Book Given the balance of the account is 200 And the account number is 12345 And the user has been authenticated And the user's address is 15 Credibility Street When the user clicks on 'order a cheque book' Then reply YES to the user's request Scenario: Order a Cheque Book, user is overdrawn Given the balance of the account is -150 And the account number is 12345 And the user has been authenticated When the user clicks on 'order a cheque book' Then reply NO to the user's request Scenario: Order a Cheque Book, zero account Given the balance of the account is 0 And the account number is 12345 And the user has been authenticated When the user clicks on 'order a cheque book' Then reply NO to the user's request Scenario: Order a Cheque Book, no address available Given the balance of the account is 200 And the account number is 12345 And the user has been authenticated And the the user's address is UNKNOWN When the user clicks on 'order a cheque book' Then reply NO_ADDRESS to the user's request
The benefit of having a story that contains a bunch of specific examples rather than a few vague scenarios is that you can link your stories to your tests, so that the scenarios in your stories become the tests. In this blog I’ve progressed from the idea of vague acceptance criteria to testable scenarios. What’s needed now are some tools that will allow us to execute these scenarios as tests. Enter jbehave and Cucumber. Both jbehave and Cucumber seem to do the same thing, but it is the blurb from the Cucumber website that best sums up their functionality:
“Cucumber lets software development teams describe how software should behave in plain text. The text is written in a business-readable domain-specific language and serves as documentation, automated tests and development-aid – all rolled into one format.”