So I'm almost finished reading this book, BDD in Action, by John Ferguson Smart, and I think it is really a fantastic book. Despite the wacky, ugly-looking cover, this is a super-awesome software development book that pretty much revolutionized the way I think about unit testing- and I think a LOT about unit testing so this must be a pretty big deal. I would highly recommend this book to anyone trying to wrap their head around behavior driven development, but in this post I'm going to reveal the crux of BDD- spoiler alert!
The Crux of BDD is... Gherkin!
What an awful name for a programming language, "Gherkin". After looking into where the heck this name comes from, it seems to be a type of pickled cucumber. Ok then... Anyway, for our purposes Gherkin refers to a programming language. It is code that literally looks like English. It describes the features of your application, the acceptance criteria, and how it should work.
Tests for the Whole Team!
The problem with unit tests is that it takes a deep understanding of 1) the programming language the app is written in, 2) unit testing in general, and more specifically for the current app's language / framework, and 3) at least a basic understanding of the codebase, how the application works, and what the current component is supposed to do. Even when you have all that background knowledge, wading through thousands of lines of unit testing code doesn't normally make for a fun birthday party. This lack of team understanding leads to a fuzzy image of what unit tests are and how they are really helping the project in the eyes of everyone who isn't a programmer. Gherkin brings unit testing back down to their level. It gives them "executable acceptance tests" that they can understand without being bogged down by a bunch of [insert your favorite programming language here] code (and even for the programmers, reading the gherkin can be a refreshing way to get a high-level idea of a what certain of units tests are doing). Take a look at the example of some gherkin code below (yes, it is actually code!):
Single Source of Truth
Let me tell you a story about a way of developing that didn't work so well for me. I, the developer, wanted to write unit tests so I told everyone else on my team how great they are and how it'll lead to perfect code all the time being written super speedily (ok, maybe I'm promising a little too much hehe). The PM's said, "ok, sounds great!". Then we had the idea of taking the description from the unit tests and listing them in a google spreadsheet. Non-programmers are like that; they don't want to have to checkout your project from git and go digging through all your directories and code files just to see the "planning" stuff. They just want a spreadsheet, nice and clean, with everything you need laid out right there in front of you. Sure. I would like that too. But the problem is that immediately once you begin working stuff changes. Things become out of sync. You don't know what's done and what's not done, what things have been added to the spreadsheet (or the unit tests) and what things have been removed. It becomes a mess, and it may at some point become so unmanageable and wasting so much of everyone's time that the team just says, "Screw unit testing altogether". I wish I could magically appear in the room of every team going through these issues and be like, "guys, WAIT! There is a better way!". When the code directly generates your documentation and your documentation is your code then you are never scrambling to keep everything in sync.
If you are a lead developer, you might report to a technology director, a CTO, or even a CEO. Periodically, they will want to know how the project is progressing. I like to refer to this a the proverbial, "So, where are we at?" question. I've had trouble answering this in the past before. Often, I'm preoccupied with whatever issues are on my mind at the moment so I'll go into that or start talking about the last thing I was working on, but this is usually not the type of answer the CEO is looking for. He normally wants you to spare him the details and cut to the chase- just the facts, and at a very high-level (but be prepared to answer questions about specifics if he asks). what if you could just give that senior manager a snapshot of the entire project? Imagine telling the CEO of your company that if he wants to know the project status he should go read through the units tests of the project (Lol! I highly doubt that will go over well!). BUT, What if you could, right through the command line, run your whole suite of easily readable, high level unit tests, and then generate a report describing each one and showing which ones are passing and which are failing- automatically. Well, with pretty much all the runners that handle Gherkin this is really is a thing! In BDD in Action, Smart talks a whole lot about these reports. He calls them "living documentation" because they are generated by the code. You don't need to "write" these reports, you just run a command and they are there. They grow alongside your codebase and evolve with it. Indeed, the reports are necessarily a reflection of current codebase. Even better than printed reports, you can set up the reports on an internal network so that management can just check out the reports at any time by visiting a url instead of bothering you (and you can use html2pdf if you do happen to want to print them out). It can also be immensely helpful to the "Business as Usual" team (ie. the people who take over once your done coding and move on to your next big project) to be able to have these easily readable tests as a way of gently and easily getting familiar with the codebase.
A Focus on Business Value
Unit tests in the traditional sense are concerns with the functions of your program. Let's hold everything else constant (by mocking it or using spyOn), and then let's check that this one function is working as expected. This is fine, and Smart calls this low level specifications. You still have these in a BDD project. The difference is that in BDD you also have high level specifications, and these are written in Gherkin. It's the high level specifications that really drive the project, that let you know when you're done, and that help prove that you are indeed building the right software.
Given..., When..., Then... Structure
Although Gherkin looks like just regular English, there are some syntax rules to it. When defining a Gherkin Scenario, you want to specify three things: given, when, and then. The given part is the setup for your unit test. It's the beforeEach where you get ahold of your instances. Then you have the when which describes some action that I'm taking that should trigger an event in the application to happen. The then part describes this thing that should happen in response to the action of the when statement. Inside the then is where you would normally do your assertions. But what do I mean by "inside the then"? Well, each one of these lines of Gherkin is mapped to a function in your normal coding language called a step definition.
For example, your Gherkin might look like this:
And the corresponding step function might look like this:
Now hopefully you can see how we can have these very high level, easy to understand Gherkin tests while still allowing them to get deep into the nitty gritty parts of the code and truly test the codebase the way unit testing always has. I think most unit tests already follow the given, when, then pattern in some form. They don't explicitly use those words, and they are usually all thrown into a single method, but it shouldn't be too difficult to see how your unit tests can fit into this pattern.
I'm Sold. How Do I Start?
The posts on this site are written and maintained by Jim Lynch. About Jim...