New features were coming thick and fast, so we thought it was time to build on our development process with behaviour-driven development (BDD). Here’s what we were hoping to achieve:
- Reduce ambiguity around new features before we start the work by discussing exactly how the product should behave, making it less likely that we would build the wrong thing.
- Help us to “know when we were done” while building new features, with clear testable outcomes defined.
- Consolidate features we already had and new features as they were added by describing their behaviour and adding tests to confirm they were still present (ie, to avoid regression).
Part 1: Collaborative Discussion
And so, on a wet Tuesday morning, Duncan (agile coach) and Martin (development lead) arrived at the office to begin the implementation. Learning from our experience of applying BDD in previous organisations, we knew that it would be easy to implement the technical side without really getting the full benefit of this collaboration tool. With this in mind we spent our first 90 minutes establishing a test strategy by utilising examples and case studies from our BDD training course. We discussed:
- That BDD is a collaboration tool to help bridge the gap between business and IT, so in order to benefit, everyone needs to be involved.
- The principle of specifying how the feature should work by providing examples of how it should behave in different scenarios, using the “Given… When… Then…” format (called Gherkin).
- How the communication gap between business and technology can be bridged by starting with these clear, universally understandable scenarios and then building automated tests around them using Cucumber (or other similar tools).
It’s important not to skip this first step. Many of our clients struggle to benefit from this tool because only the test specialists understand it. In some cases testers were the only people who ever saw the scenarios. This misses the point.
Next, we set ourselves a goal for the end of the day: write one scenario to describe the behaviour of an existing feature, and get this automated through our development environment. We chose the login function as it’s easy to understand and test. We started off by describing how the product should behave when an admin user entered valid details:
We discussed the level of detail appropriate here: should we specify that it’s an admin user? Should we write “valid details”, or spell it out more explicitly? There’s no hard rules here, other than that the primary goal is to produce simple, understandable phrases that everyone can understand. We decided that different user types see different results so this was important to differentiate, but we could encode the login particulars behind the scenes with no loss of meaning. Having thought about the way the product worked, we realised that getting to the login page to begin with could be described by another scenario:
With these basic scenarios defined and well understood, Martin moved on to the technical implementation.
Part 2: Test Automation with Protractor and AngularJS
1) login.feature
We created a login.feature file to hold the scenarios for our login tests. This acts as a human-readable description of what we were hoping to achieve and is also the hook for the tests to be run. With a small set of key words (given, when, then, scenario, etc) we can gradually build up a domain-specific test language by defining what free text such as “I am not logged in” means for our system.
2) login.steps.js
Next we created a JavaScript file that would implement the login.feature file. The Protractor library we used to run the tests uses RegEx pattern matching on the feature file and tried to match what it finds to functions implemented in the relevant steps.js file, turning the human-readable code in the feature file into executable instructions.
3) loginFeature.Conf.js
The only other file that Protractor needs is a config file. This includes the path to both the feature file and the related step.js file plus some other initialisation metadata such as the url of the Selenium WebDriver service to use and which browser the tests should be run against (in this case ‘Chrome’)
4) Starting a local Selenium WebDriver session
Protractor needs an instance of Selenium WebDriver to feed instructions to so we started an instance of that in the command line on my local machine. (Protractor and Selenium WebDriver can be easily installed via Node Package Manager after cloning the github repository from https://github.com/angular/protractor.git)
5) Running Protractor
Next we ran Protractor in a separate command prompt. The only input parameter we needed was the name of the configuration file as defined in 3) above.
6) Checking the results
There are three possible outputs per test step from Protractor: ‘Success’, ‘Failure’, or ‘Skipped’. Obviously the net result we are looking for in a growing stack of BDD implementations is a boolean (ie: either all the tests passed and we can deploy the product, or they didn’t). Interestingly where Protractor cannot match a feature line to the JavaScript implementation function (ie ‘skipped’ tests) it does at least provide some example stubs of JavaScript to show what it was expecting to find.
7) Repeat…
Having successfully implemented our first BDD test we intend to build on this so that all future development work adopts an ATDD methodology. Eventually we envisage having many .feature files and associated *.steps.js implementation files. This will have the added benefit of code-reuse as there will be common features and steps throughout the test scripts (for example – logging in to the system is a pre-requisite for most of our tests).
Summary
Overall implementing ATDD/BDD using Protractor within an AngularJS environment is relatively straightforward. It is our opinion that BDD strikes a good balance of ‘sensible testing’ against ‘line-for-line’ type TDD approach and is clearly a vast improvement in speed and accuracy compared to manual testing, particularly when multiple OS, devices and browsers are involved.
Next Steps
BDD is a collaboration tool designed with all stages of the development lifecycle in mind from deciding what to build, checking when features have met requirements, and confirming that features have not regressed by later updates. This guide gives an overview incorporating BDD into a product management and planning operation. A great way to get started or to validate an existing approach is to arrange for an in-house BDD training course from Agility in Mind.