Software testing is essential in order to avoid as many errors as possible in advance during software development and to ensure a high quality. All functions and possibilities of usage are checked to identify undiscovered programming errors, problems or disturbances. Software tests can be made on different levels - from unit tests of individual methods up to acceptance tests, with which the functional expectations and requirements are tested with respect to the users need. This makes it relatively easy to document how the software operates and works in use in an understandable way, for example, in order to present it to stakeholders. This common basis of communication between the development team and stakeholders, which facilitates collaboration, is one of the core ideas of Behavior Driven Development.
Behavior Driven Development (BDD)
BDD is a software development process that can improve the collaboration across different roles. In connection with BDD, one often reads the term TDD (Test Driven Development) - a software development process in which the appropriate tests for the feature are written before the software is implemented - which we will not discuss any further here.
Along with the 20th birthday of the Agile Manifesto, an important message has arrived at most IT companies: Software is developed for the customer and his needs. It should create and add an additional value. The long phases of technical analysis should be replaced by short development and delivery cycles, in order to obtain fast feedback and to be able to react flexibly to changes in the requirements. Functional software has priority over detailed documentation. Hence, the software requirements are no longer described in a several-page-long, technical document but in the form of User Stories. Details of the requirement are communicated through examples formulated from the user’s perspective, mostly even in everyday language. This makes it easier for all roles involved to understand the desired behavior of the software, to emphasize the added value for the users more strongly, and to clarify the intentions behind the requirements. The focus here is on the goal and benefit of the software; the exact technical implementation is usually left to the development team.
BDD was developed precisely for this method of describing requirements. The technique supports agile software development and strengthens collaboration between the customer and the development team. BDD is guided by the following three core principles (according to cucumber.io):
- Encouraging collaboration across roles to build shared understanding of the problem to be solved.
- Working in rapid, small iterations to increase feedback and the flow of value.
- Producing system documentation that is automatically checked against the system’s behavior.
Through the collaboration of different roles (e.g., software developer, product owner, designer) and the stronger involvement of the stakeholders, the requirements should be understood as best as possible even before the implementation is completed and new insights gained should be shared on an ongoing basis. The focus of the software is to support the user behavior as good as possible; it is not developed to fulfill a catalog of technical requirements. To do this, the expectations and the current version of the software must be continuously compared and coordinated. For this purpose, the following process could be followed:
- Talk about a new User Story using concrete examples of behavior. Agree on details that are expected.
- Document the requirements in a way that automation can follow from them and balance them with the other roles.
- Implement the described behavior and support development and quality assurance with automated tests.
One of the most popular tools to support a BDD-oriented workflow is the framework Cucumber.
The framework consists of two layers. The first one contains a feature-file in which the functionality of the system is described. The behavior of the software is documented with the help of concrete examples. Therefore, the descriptive language Gherkin is used, which gives the description a structure by using special keywords. The test cases have approximately the form
Feature: Show blog article Scenario: I want to read the blog article “BDD & Cucumber“ Given I am visiting the cronn website When I click on the tab “Blog“ And I choose the article “BDD & Cucumber“ Then this article is shown
What exactly is being tested is not prescribed by Cucumber: from browser operations to interface tests and database operations, everything is possible. Except for the keywords, any wording can be chosen such that a common understanding of the functionality of the software is achieved. At the same time, these test case descriptions themselves serve as living documentation to record the current state of the software. In this way, the functional scope is described in an understandable way and deviations from expected behavior are quickly noticed. The strength of the Cucumber framework in contrast to other test frameworks lies exactly in this combination of test case execution and documentation.
To execute the steps of a test case described in the feature-files, Cucumber needs the so-called “glue code“. In an arbitrary programming language (in the case of Cucumber Java and Ruby are the most widely used and supported ones) the functionality behind each step is implemented. Because of this free coupling to any programming language there are (almost) no limits to the possibilities of testing and no restrictions by the features of other test tools. Of course, this increases the hurdle to use Cucumber as a test framework a little bit: for the implementation of the “glue code“ a basic understanding of the chosen programming language is required.
Thus, through the structure given by Cucumber, the principles of BDD are supported. By describing the test cases in an accessible and easily understandable way, the common understanding of how the software works is facilitated and a basis for discussion is formed in which all roles involved can participate. By describing concrete examples in natural language, many ambiguities can be identified and clarified before implementation. For example, the size of the feature-file is an indicator of the complexity of the associated User Story. Since the test cases contain documentation and test execution at the same time, the current status and functionality of the software is visible at any time and thus represents a meaningful part of quality assurance.
If you just want to try this out, check out Cucumber with JUnit 5. There Sebastian explains how to quickly set up your own Cucumber project with Java.