I recently hosted a discussion at the London Agile Discussion Group (LADG) on the topic of BDD and feature files.
It’s always a popular topic and the session appeared to be at full capacity.
I initially kicked off the session with a question to everyone: “What is Behaviour Driven Development?”. I dished out some post-it notes and we discussed the thoughts of the audience.
There were distinct groups of thoughts. Many thought BDD was about testing – test cases, testable requirements, something testers do or use, related to automation, etc…
Others thought it was related to requirements – another way to write them, a way to format acceptance criteria, using the Gherkin “given when then” format so that the business stakeholders can write them, etc.
Personally, I see BDD as being an activity or process which is all about having conversations and collaborating to discuss the idea of the software. The purpose is to uncover more information and refine and refactor the idea, discovering and dispelling assumptions and ambiguities (or discovering problems in our thinking to prevent problems in our designing, coding, testing and checking activities later on down the line). The output of these conversations is our feature files, with scenarios that provide examples of the features, based on the information that we have uncovered throughout the collaborative conversations.
In the discussion group, I think we had some good conversations around this and the conversations then flowed towards the actual creation of the feature files.
I used an example before setting a challenge to the group.
The context for my example was that the idea of the new feature was “a search screen to be able to search for registered users of a system”.
So the first scenario that I gave them was:
Scenario: User account level permissions and restrictions
My thinking behind this example is that it’s an important part of the feature of the search screen, and its simple enough to use as an example ☺
So the way I’d start writing this feature file (with the team – remember, this is about stemming conversations to uncover more information) is but trying to be vague with the wording, writing my gherkin “given when then” scenarios in a declarative format:
Given the user has an account with a certain access level When the search screen is viewed Then the user should see something
Seems useless at first, but if we then start to talk about the ambiguities, properties and variables within each part of this sentence, then we can start to form an example table around the ambiguous words.
Given the user [has] an account with [a certain access level] When the search screen is viewed Then the user [should see something]
| has | a certain access level | should see something | | | | |
When we start to question and test these properties, we can start to uncover more variables within them. This is BDD! We’re uncovering more information and it’s helping us refine and refactor the idea of the software to aid future designs, code, testing and checking activities.
So to complete the first scenario, based on the variables that I can think of regarding these properties within my scenario, the feature file might look like this:
Given the user [has] an account with [a certain access level] When the search screen is viewed Then the user [should see something] | has | a certain access level | should see something | | has | basic access privileges | be able to search and read the results, but not edit them | | has | read only access | see a message saying the page is restricted and they cannot access | | has | admin privileges | be able to search and read the results, and can edit/action them but not delete them | | has | super admin/tech support privileges | be able to search and read the results, and can edit/action them including deleting them | | has | anonymous privileges | see a message saying the page is restricted and they cannot access | | does not have | any privileges | see a message saying the page is restricted and they cannot access | | | | |
The idea with example tables within a feature file is that you read each row of the table in place of the text within the square brackets… E.g. Our first row in the table would verbally read as : “Given the user has an account with basic access privileges, when the search screen is viewed, then the user should be able to search and read the results, but not edit them”.
At this point the conversations should still be flowing…
– Any other account levels?
– Anything else that each level should see?
– Anything else that each level shouldn’t see?
– Is there team type restrictions?
– Is there any other risks or properties we haven’t thought about here?
– Should we expand what we mean by “user” into the table and use different personas?
– Do we want to add any more expectations?
– What else have we not thought about yet?
– What useful heuristics can we use to stem more ideas?
– Is there anything in here that we can’t set a “then” statement for since we don’t have an expectation? (we need to create a test charter for that!)
(Do you see what we are doing here? We are exploratory testing the idea and translating the info that we discover from that exploratory testing into more examples within the feature file that we can use to stem design, coding, more testing and checking, etc)
The feature file is also living documentation until we are “done” (based on our definition of done).
So the primary purpose of writing the feature file is to stem mote conversations. The secondary purpose is that it’s a useable document for aiding our design, development, testing and checking activities. And a third purpose is that we can then use glue code and create step definition files that contain automation code that will assert our explicit expectations that we have formed in our “then” statements.
In the discussion group, I then set the challenge to the group to great a second “given when then” declarative sentence with an example table based on the following second scenario related to our context:
Scenario: Searching based on search criteria data
The group was split into sub groups for this exercise, and all the participants did really well!
I didn’t share this with the group since we ran out of time, but here is my feature file that I would write for the second scenario:
Given [data] is/are entered into [the field] via [an input method] When [the button] is clicked Then [the outcome should] display to the user
| data | the field | an input method | the button | the outcome should | | "Dan" | the first name field | typing on a physical keyboard | "Search" | all users with the first name "Dan" should | | "McDonald-O'Malley" | the surname field | the touch screen keyboard | "Search" | all users with the surname "McDonald-O'Malley" should | | the wildcard character(??) | all of the text fields | pasting from the keyboard | "Search" | all of the users registered on the system should | | Dan"; DROP TABLE Users | the first name field | keyboard typing | "Search" | the SQL injection should be handled with the users table not being deleted and no results should | | ASCI255 characters | the user bio field | pasting from the file menu | "Search" | (How should this data be handled???????) | | a single space | the user location field | voice to text 3rd party tool | "Search" | (How should this data be handled???????) | | 100K characters | each of the free text fields | pasting from the mouse | "Search" | (How should this data be handled???????) | | any data | all text fields | any input method | "Clear" | all of the data in the search criteria fields should clear and no results should display | | no data | the mandatory fields | any input method | "Search" | the a mandatory fields' "please enter data" message should | | | | | | |
Again, I’m using the BDD processes to uncover information, then forming the outcome of the discussions into a scenario example to help us stem more conversations which will refactor our ideas and expectations, as well as uncover more unknown information that we can test and investigate. And there are tons of things that we have not mentioned yet:
– Any other buttons?
– Any other search criteria fields?
– Any other important data variables?
– Any other things we should think of?
So, let us discuss and collaborate further (i.e. “using BDD”), and we can refactor the “idea” of each feature and sub feature to find bugs in our thinking, dispel assumptions and prevent bugs in our designs and code.
Our lateral thinking skills should be utilised when we are thinking about the scenarios to cover too. For example, some other scenarios that we should discuss for the concept of a search screen might be:
– Scenario: Results table display and sorting
– Scenario: Results pagination
– Scenario: Result editing actions (single action individual results / multi-action many results at once)
– Scenario: exporting results
– Scenario: saving searches
Any other sub features?
Any other risks we should think about?
Anything that we need to create some test charters to focus more exploratory testing?
Let’s focus on the information. Let’s use BDD processes to stem a deeper understanding and clarification of our idea for the features and software. Let’s use that information that we learn about to form examples to help us better understand them and to avoid making incorrect assumptions about the features when it comes to design, development, testing and checking activities.
And then when we are happy that we have enough information, then let’s reuse the expected behaviour from the feature files for a secondary purpose, using glue code to hook it into Cucumber Step Definition files to automatically assert those expectations.