When Dana Scheider, a software engineer at New Relic and member of Cucumber’s core team, decided to teach herself to code, she started with a book about behavior-driven development (BDD). The more she read, the more it made sense.
We sat down with Dana for a Q&A about her experience with BDD, and her take on its benefits and challenges.
Let’s start with a definition. What exactly is behavior-driven development?
Behavior-driven development is a software development method that focuses on creating tests using concrete, real-life examples. These examples use natural language constructs (English-like sentences) to express the behavior and the expected outcomes.
It’s especially helpful when you’re working with a cross-functional team. By involving both technical and non-technical team members in defining how your software should behave, you can reap a lot of benefits.
How did you first hear about BDD?
I got into tech when my ex encouraged me to do so because I was completely disabled at that time. I needed to work in an industry that would accommodate my disability without resentment. He gave me a stack of books that he thought would put me on the right track, and in one of those books was an introduction to behavior-driven workflows. Once I started reading about them, they seemed really intuitive to me.
I’ve been on Cucumber’s core team for about a year, specifically on the Ruby implementation. I started contributing because I was looking for a way to build up my resume since I didn’t have any work experience or any formal qualifications. I shopped around for open-source projects and found the one with the friendliest group of maintainers.
What are the benefits of using BDD?
BBD keeps the focus on the end user and their needs. It’s easy for engineers to get bogged down in implementation details and architecture choices. They can lose sight of the fact that all those things ultimately have to serve the user of the software. BDD forces you to take a step back and look at the application from the end user’s perspective.
Another great thing about BBD is that documentation is built in. By writing a high-level list of specifications, you’ll provide a description of what your application actually does in simple terms that every member of your team can understand. You can use these specs to create living documentation that can be viewed by everyone working on the project.
Also, both BDD and test-driven development (TDD) allow you to refactor code really well. I feel like a lot of times, with refactoring, it’s easy to take the “Jenga approach:” does everything break if I delete this line of code? Having comprehensive test coverage enables you to edit things very efficiently without having to worry about what breaks. Your tests will tell you what breaks right away. If I’m not sure if I need a module, I’ll delete the whole thing and see what happens. Provided I have the right coverage and the tests provide meaningful feedback, it’ll tell me what broke, so I can fix those things and leave the rest.
What about the drawbacks?
Many companies are founded by engineers who had a cool idea and put something together. And a lot of times, extensive testing isn’t a part of that. There are conflicting schools of thought on the best way to implement testing, even within a single organization. And everyone is very passionate about their particular point of view.
It can be hard to get the whole team on the same page. Everyone notices problems with the new thing more than they notice problems with the status-quo — which is typical when you’re implementing any kind of change.
Purism is also a challenge. You get situations where the orthodox approach isn’t necessarily the best one. People aren’t great at recognizing exceptions to rules: they’re either too rigid, not allowing any exceptions at all — or they’ll let anything fly, and everything goes to hell.
Another thing: Cucumber is becoming much more opinionated, and that’s a good thing. I see people who are using Cucumber incorrectly, which causes them to dislike the tool. Historically, it’s given people more than enough rope to hang themselves with. To some extent, that’s true of BDD in general. There are a lot of bad practices and poor implementations out there.
What obstacles face BDD practitioners?
The big one is the question of test data. In an ideal BDD world, tests aren't dependent on existing system state. But in reality, there are often data needs that can't be solved with simple fixtures and factories. For example, data that are retrieved from an external API or generated by a background job. Another issue that becomes a challenge is retrofitting tests to legacy codebases in order to transition to BDD workflows.
In practical terms, I also see test suites become unwieldy when teams skip refactoring their tests (and too often, even their application code). That often leads to the impression that BDD looks good on paper but isn't practical in real life. I think figuring out viable answers to these questions is going to be a critical next step for those of us who would like to see wider adoption of behavior driven workflows.