The goals of BDD are to do with communication. This is a 2-way street. When we encounter the idea of BDD, it is often viewed only from one direction: Allowing the specifications to be communicated properly down to development and provide a translation layer from business-speak to executable tests that will let developers know when they have successfully satisfied the criteria and can move on to the next thing. There is some irony in the fact that most of the tooling is made for developers. In this article we’ll be leaving out the still very important topic of the Ubiquitous Language and focus on the mechanics. These specifications are run in much the same manner, and often relying on the same tooling, as unit tests. When the specification run it shows what is implemented – often in very readable and user friendly manner than what is the output of typical unit or integration test runs.
Educate the Business, not Just the Developers
The 2-way street is defined as these 3 goals:
- Allow the business to specify the success criteria to the developers easily
- Allow developers to communicate what is already possible using current functionality.
- Provide an artefact that is easily authored by both sides.
There is plenty of information out there on the first goal. The second and third ones are where the industry is lacking. Jeremy Miller has been one of the few people in the industry to successfully address the second point with StoryTeller. It is highly recommended reading as well as all links there-in.
The communication of what the system can already do is captured in what is referred to as a fixture. A fixture is the piece of code that translates the human readable specification into the actual method call on an object in the system. Fitnesse was one of the first frameworks for BDD and relied on some dashes and pipe characters to be used in a wiki to draw tables in ASCII-art style for the specifications. The contents of these “tables” was then interpreted as instructions of what parameters to pass to methods and what to expect as the return value to verify behaviour. Each row was a separate test, using different parameters.
When someone is going to specify a new piece of functionality for an existing system, they should be able to pick from a set of operations already available. Let’s say the system includes a way to log in and log out of the website. The steps would be stated as “Login with user _____ and password ____” and “Logout” The person specifying something in that area should be able to do 2 things:
- Find these steps already, choose the template for them, fill in the blanks
- Specify a new step that the system should provide
The second part is where some of the interesting communication happens between business and development. When someone from the sales side or product management sticks in a step that says “Provide visa card #________” the system currently does not have that functionality yet and this specification will fail. This falls right into the agile way of doing things and fixing the one thing that’s broken. In this case, to make this specification pass, the developers will write:
- the fixture so that the new instruction written by the “specifier” will call some API or method on a class,
- and the class with the method or API that will provide the functionality called by the above
To verify, fixtures that inspect the result of SUT (system/class/object/function under test) can be written as a separate fixture or included in a fixture that provides the parameters and checks the result in one go. The topic of keeping the “specification scope” arises as the results of previous fixtures need to be kept around for the following fixtures. This may be abstracted as the setup for the specification where a service is spun up or an object is created.
SpecFlow and other widely accepted tools already instrument intellisense so that a developer has a drop down of current fixtures. So what’s missing? It’s only the developer. The specifier is not involved. Sure, the specifier can artificially be made to sit with the developer to type this up. Or, the developer can be forced to sit in a business meeting to note these specifications using one of these tools. But this rarely happens because of many organisational factors. The key to continuous delivery is to get the input from business or development into automated specifications easily whether both are available or not.
Side note: A good system should be abstracted so well so that there is no need for a translation between “business speak” and “tech speak”. Mike Stockdale developed his own specification tooling to do precisely this. The production code needs to be human readable (at least at the “API level”) so when the specification is written, it is using the constructs exposed by the classes within the actual production system. The sad truth is that most systems don’t exhibit good enough abstraction in code to use Mike’s approach.
See Things Work
It is a very common practice to combine the specification tests with user interface automation. This way, the system can be treated as a black box as much as possible which is preferable in some instances. Fixtures in this case will be grouped by possible actions from pages and include functionality that facilitates inspection of the properties of a page to make it easier to check for success criteria.
Collaboration: It is intended for a BDD tool to be used – hopefully in most cases – by both business people and developers sitting side by side. This is why BDD is an important practice in developing a united organization where everyone is building the same thing. It produces an artefact that crosses the boundaries in an org chart. Another practice that brings the communication to another level is event-centric architecture which was the subject of the last post and shows how some of these mechanics are made easier by a better convention for storing state in the system. Fixtures are much easier to write if they are only facilitating the communication of messages in the system. It also brings us a step closer to what Mike is pushing for.
No Framework Please, Just a Convention
StoryTeller is amazing but unfortunately, like other tooling, is tied to a specific tech stack – in its case, .NET and other libraries like react. A light weight solution is always preferable. By ignoring existing tooling, developing a simple system will show the important parts. The utilities that allow a convention for this should be written in something that will easily consumable on multiple platforms – especially Linux. The needs of a BDD system are:
- store the catalog of fixtures available
- represent the fixtures catalog in some editing page where the specifier can easily find and pick available steps
- add new fixtures by non-technical authors
- store the fixtures picked and the data entered into them for a particular spec
- a plug-in for the tech of choice for implementation
- run the set of steps in a spec and report back the successes and failures
In the next post, a simple convention with some utilities will be developed to facilitate the above.