In a previous article, I introduced the Testing Matrix. In this article, we’ll see how Behavior Driven Development / Acceptance Test Driven Development (BDD/ATDD) can apply all the way from the Customer / User Tests to Unit Tests. These are the tests in the left column of the matrix. To illustrate this process, I’ll use the example of an on-line ordering system.
BDD/ATDD at the Customer/User level involves a triad – people with three different perspectives – the customer, the developer, and the tester. They collaborate on a requirement, e.g. a story, to ensure a shared understanding. That understanding is typically expressed as scenarios – a flow through a system. An example of this might be:
Scenario: Compute taxes and shipping on an order Given a customer | Name | Shipping ZipCode | | Sam | 27701 | And customer has created an order | Quantity | Item | Price | | 1 | Widget | $10.01 | When the user submits the order Then tax and shipping are added to the order | | Tax | Shipping | Total Charge | | $ .70 | $5.00 |$15.71 |
The implementation that is created to pass this acceptance test may involve multiple components, such as microservices. The context diagram below illustrates how the components fit within the context of an application and the units within a component. Note that every application consists of this simple organization.
For larger applications, there may be an overall design team (developers, architects, testers) that determines the responsibilities of each component. They can use BDD/ATDD to specify the behavior of each of these components. In this example, there could be a tax component that calculates the taxes. A scenario might be:
Scenario: Compute taxes Given an order from | Shipping ZipCode | | 27701 | When order has | Item Total | | $15.00 | Then tax is | Tax | | $ .70 |
The detailed design team (which may be the same as the overall design team) can allocate the component responsibilities to individual units (e.g. classes or methods). Again, BDD/ATDD can help to specify the behavior of these units. This is analogous to what Dan North stated in his initial description of BDD concerning how the tests define the behavior of the system. A unit might determine the tax rate for a particular locale. So, the scenario might look like:
Scenario: Determine tax rate Given jurisdiction is | Shipping ZipCode | | 27701 | When tax rate is retrieved Then tax rates are | State Tax Rate | Local Tax Rate | | 6.0% | 1.0% |
This scenario could be automated using Gherkin or the unit testing framework for the implementation language. If there were multiple values that needed to be tested, a scenario outline would be used, such as:
Scenario Outline: Determine tax rate Given jurisdiction is | Shipping ZipCode | | <zipcode> | When tax rate is retrieved Then tax rates are | State Tax Rate | Local Tax Rate | | <staterate> | <localrate> | Examples: | zipcode | staterate | localrate | | 27701 | 6.0% | 1.0% | | 27798 | 6.0% | 0.5% | | 96555 | 0.0 % | 0.0% |
The method could be developed incrementally by applying one example at a time using the Test-Driven Development red-green-refactor cycle. Notice that Given/When/Then parallels the Arrange/Act/Assert template for TDD unit testing.
BDD/ATDD’s Given-When-Then scenarios can be applied from the Customer/User test levels all the way down to the Unit level.