In week 3 Intro to Programming we learned about Behavior-Driven Development. As you recall, Behavior-Driven Development is the practice of breaking a program down into the series of smaller behaviors that create it. We then use these behaviors to drive the course of development. We begin addressing the simplest behavior, implement just enough code to get it functioning, confirm it works, then begin addressing the next simplest behavior.
In this lesson we'll review the benefits of Behavior-Driven Development. In the next lesson, we'll walk through the exact workflow of using Behavior-Driven Development in conjunction with automated tests. Finally, we'll learn how to install and utilize automated testing tools into our applications.
If you'd like to refresh your memory check out the following lessons:
Behavior-Driven Development assists in tackling complex problems. If you were told to build a Pig Latin Translator you may not immediately know where to begin. You might start by writing one function, realize you need something else in place before this function can work, and your approach quickly becomes disorganized.
Sure, you likely already created a Pig Latin translator in Intro to Programming, so perhaps this challenge doesn't seem quite so difficult now. That's great! But what about an even larger program. How would you begin re-creating Facebook? Or the code behind a self-driving car?
It'd be difficult to even determine where to begin, right?
Let's consider an example. Imagine you're training to become a chef instead of a developer. As a chef, you've been tasked to bake a lemon meringue pie.
Let's assume you've never actually made lemon meringue pie. Perhaps you've seen one, eaten one, or have a general idea what it looks like, but you've never done it yourself.
Now, if you wanted to learn the most about baking lemon meringue pie, and create the best product in a reasonable amount of time, which of the following recipes would be the most helpful?
Bake a lemon meringue pie. It should have a crust, lemon filling, and a meringue topping.
* Preheat oven to 350 degrees. * Whisk together 1 cup sugar, 2 tablespoons flour, and 1/4 teaspoon salt in a saucepan. Stir in 1 1/2 cups water, and the juice of two lemons. * Cook over medium-high heat until mixture boils. Stir in 2 tablespoons butter. * Place 4 egg yolks in a small bowl and gradually whisk in the hot sugar mixture. Pour this filling into pie crust. * In a large bowl, whip 4 egg whites until foamy. Add 6 tablespoons sugar. Continue whipping until stiff peaks form. * Spread this meringue mixture over pie filling. * Bake in preheated oven for 10 minutes, or until meringue is golden brown.
No contest, right? The second recipe is absolutely superior. Not only does it lay out what you'll need to complete the task, but it details step-by-step instructions.
We can even consider just the first step in each recipe. Which one of these individual tasks is clearer and easier to accomplish?
Bake a lemon meringue pie. It should have a lemon filling, and a meringue topping.
Preheat oven to 350 degrees.
As you can see, by breaking down difficult, complex, or foreign tasks into small behaviors we can get much further in much more quickly. And by taking time to focus on each individual behavior, we often learn more too!
Now, consider a coding project instead. Again, let's imagine you've been tasked to create a Pig Latin translator. Similar to the pie example, we'll pretend you've never made one before. You have an idea of what this program looks like and what it should do...but how do you get there?
Take a peek at the following two "recipes". Which one would be the most helpful? Which one would help finish the project faster? Which organizes the workflow better, and likely results in a better end product?
* Build a Pig Latin translator. It should take any English word, sentence, or paragraph and return its Pig Latin translation.
* First, make sure it can translate really basic, single-character words beginning with a vowel. * For example: "I" should come out as "Iay". * Once that's working, move onto multiple-character words beginning with a vowel. * "oats" should come out as "oatsay" * Then, work on translating single words beginning with consonants. * "cat" should turn into "atcay". * When you have that, move onto full sentences. * "I am a boat" should become "Iay amay aay oatbay"
Again, this is no contest. The second clearly outlines where to start, and what each step along the way looks like. Using this "recipe" would make the process of developing a Pig Latin application far quicker, easier, and better organized.
As you can see, there are countless benefits to using the Behavior-Driven Development process. Let's review:
By taking time to think through a program, identify behaviors, and tackle the simplest first, you're creating a gameplan. You're laying out each step you'll need to take in detail, like the superior Recipe Two above.
As cliche as it may sound; climbing a huge mountain is daunting. But taking a single step isn't. Even the most experienced senior developers can struggle with approaching complex issues. By starting small and working our way up we can make a seemingly-daunting task much more approachable. And we can get moving much quicker. As you begin coding small behaviors, the larger picture will likely come into focus.
By implementing a single behavior, testing it, and confirming it works before coding the next behavior we're preventing errors. Testing each behavior before moving on allows us to spot bugs the moment they're introduced.
If we didn't use BDD, we probably wouldn't spot bugs until they actually broke our application. And, if we added more code after the bug was introduced, other behaviors will likely rely on the buggy code. To solve the problem we'd have to comb through everything, locate the bug, resolve it, and also alter code depending on that buggy code. That's a lot of work!
Starting a complex project can be daunting. Even if you aren't sure how to code the more difficult features of your application, you can get moving by implementing smaller, identifiable behaviors. As you work, the bigger picture will come into focus.
By testing behaviors as they're implemented, and ensuring previous tests still pass when new behaviors are introduced, new features are always built on a foundation of reliable, tested code.
By implementing the least amount of code to pass each test, you're keeping code DRY. And by approaching each behavior individually, you're creating more modular code. Modular code is easier to maintain, update, and debug.
If you're here, you're likely training to become a professional web developer. Testing is something you'll likely be expected to do at future internships and jobs. By developing good BDD habits now, you're gaining skillsets employers value. You'll also begin building a portfolio that contains many demonstrations of these skillsets.
In Intro to Programming, we "tested" each behavior by inserting sample input into our program and double-checking we received the correct output.
However, as our programs grow in complexity, manually testing an ever-growing list of specs will take more and more time. And it's not the way professionals test their code, either.
In this course we will level up our BDD skills by writing automated tests for each behavior. While writing coded tests may take longer at first, you'll be able to test every single one of your programs' behaviors with a single command. And it only takes seconds!
In the next few lessons, we'll learn about how the BDD process differs when tests are coded, and how to begin writing coded tests.