Developers of automation, and even technically oriented testers, have lost sight of the original intent of Cucumber; to support Behavior Driven Development (BDD) in its goal of reducing requirement ambiguity and the misunderstanding between software developers and those who order the software. It was meant bridge the gap, while also making automation of the Feature files possible. When the audience for Cucumber is indeed business partners and/or testers, the symptom of this loss of direction is the prevalence of Cucumber scripts (Feature files) that look like code and are confusing to interpret for those non-technical audiences. Not to mention that they are also difficult for the developers to maintain and extend. We will be taking a look at the several ways possible to make the Feature file more readable and comprehensible to its audiences.
Consider an enterprise event planning and management application. It encompasses two applications: a centralized, desktop browser based application used to create and oversee the events, and a mobile app that event attendees use to get information (schedules, maps, presenters, sponsors, and etc.) to help them navigate the event. All of the mobile functionality is also available on the desktop application.
Let’s take the example of a notification, or alert, that needs to be sent to all attendees of an event to let them know of a time change for one of the sessions.
- The event manager creates the alert and sends it to all event attendees.
- Each attendee receives the message on the mobile app
- If an attendee opens the alert and has the choice to respond to it or not.
- The response is returned to the main application and reported
Here is what this might look like in a Cucumber feature file with the repetitions replaced by ellipses in succeeding scenarios:
Even with the omitted repetitions this is hard to grasp even for an experienced programmer. The large number of steps make the high level use case (send alert, acknowledge alert, confirm acknowledgement) hard to discern. And even if the scenarios are much tighter, they all do the same thing with variations only in the type of alert being sent.
The first thing to do is condense the Scenario itself. We’ll further refactor the step definitions to raise the level of abstraction and reduce the imperative steps and try to leave only declarative steps (I log on, I send, I should see, and etc.) Another way to think of this is to refactor the ‘how’ down into step definitions or code so only the ‘what’ is in the scenario.
Imperative and declarative boil down to a question of granularity.
- Imperative implies an instruction to do one action: a click, type something into a field.
- Declarative describes an activity that takes several actions to accomplish: log on, send an alert, acknowledge an alert.
We’ll use the step at line 10 to see how the step can be defined:
At the next level of abstraction the step definition is clearly imperative:
Now we need to address the repetition of the Scenarios. We can repeat a Scenario by renaming it to Scenario Outline and providing an Example: section table and substitution identifiers:
With this we can reduce hundreds of lines to 30 or so. This allows for better understanding of the use case as well as covering variations that may cause different, and undesirable, behavior in the application.
The Bottom Line
Two ways to raise the abstraction in the feature file are:
- Refactoring the step definitions to separate activity (use case) from action (mechanics: clicks, keystrokes) or declarative from imperative.
- Using the Cucumber Scenario Outline construct to reduce repetition.
These both contribute to the clarity and maintainability of the Cucumber features and step definitions when used with careful consideration of the needs of the audience(s) using them.