Acceptance Test Driven Development (ATDD) is a practice in which the whole team collaboratively discusses acceptance criteria, with examples, and then distills them into a set of concrete acceptance tests before development begins. If you notice the keywords here then they are
whole team discussion
concrete acceptance tests
before development begins
Hence, just like we do TDD for development, ATDD is an important practice to get your test cases in place before beginning the development of a user story. These acceptance tests are then shown to the stakeholders and the functionality is verified. Changes if any, are made and the development begins. But wait! acceptance test cases, shown to the stakeholders? Which world do we live in? Do they understand the technical mumbo-jumbo? Isn’t the idea of acceptance tests to provide a clear feedback that the story is done?
Well, as you guessed you are right in most scenarios. Precisely for that reason, we need to separate out what the technical crap from what the stakeholders understand. Enter Cucumber.
Cucumber separates out the features which the stakeholders understand from the mapping code which binds these features to the corresponding acceptance test code which tests the software functionality. It would become clear from the diagram below
As you would notice, the stakeholders would look at the features and comment whether the features have the output that they are expecting. The mapping code would responsible for running the features and verifying that the output matches the expectation.
A typical feature file would look like this
So we define a feature called multiplication. For making the intent understandable we define the user story in the format “In order to As a I would like to “. Every feature would have multiple scenarios which would include happy path and alternate paths.
For all such scenarios we would specify the
The corresponding mapping in the feature file scenario would be
Precondition == Given, And
Input == When
As you would notice, any file like this is easily understandable by the stakeholders. Hence, they view the file and validate that our understanding is correct. Now we need to do the interesting part of adding the mapping so that we can make this feature file “executable”
We need to include the following dependencies
Once we have this plugin sorted out, we have to include a corresponding Scala file which would work with the values defined in the feature file. In our scenario, the Scala file looks like this
As you would notice, we are defining a regular expression match, just like Cucumber needs them. Hence Given(“””^a variable ([a-z]+) with value (\d+)$”””) would match “Given a variable x with value 3”. The variable x is now bound to varName and the value 3 is bound to value. In our code we just store it in a mutable map for now.
“And a variable y with value 4” is also matched with the same Given regular expression and the value of y is stored as 4.
When(“””^I multiply ([a-z]+) \* ([a-z]+)$”””) matches “When I multiply x * y” and as a result of that we end up getting the values from our map and multiplying them. Likewise for Then to match the result.
When this feature file is now executed with
A working example which was forked from https://bitbucket.org/jordipradel/cucumber-scala-example and made to work with SBT 0.12.1 and Scala 2.10 can be found here.
Thus, cucumber provides an efficient way of separating out the feature files which are well understood by the stakeholders and the mapping Scala files where we can play 🙂 It provides an excellent medium to communicate in the ubiquitous language which is understood by the business. In another post, we would look at how to achieve something similar with our own ScalaTest framework. Till then.