Skip to content

Instantly share code, notes, and snippets.

@andrewlinfoot
Created February 11, 2018 23:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewlinfoot/f5922c49014a8b9b55489ac3a705191e to your computer and use it in GitHub Desktop.
Save andrewlinfoot/f5922c49014a8b9b55489ac3a705191e to your computer and use it in GitHub Desktop.

Tests aren't just for catching regression bugs. A good test suite should also serve as documentation for your code. Any engineer should be able to skim over your tests and know exactly what the code is supposed to do without even looking at the implementation.

There are many different types of testing strategies for different use cases. One technique is called behavior driven development (BDD). The goal of behavior driven development is to define and write your tests in the form of expected business logic. When done properly BDD tests create a beautiful set of documentation for your code that even a non-technical reader can understand.

Let's look at a couple examples. These examples are in Javascript using Jest but regardless of the language or tools used, the concepts are the same.

Let's say we are going to test a login page. A spec might look like this:

https://gist.github.com/12148525edf6c91361da742db4c48c8b

At first glance, this spec may look fine. However, as we dive deeper, we notice we are missing some things. What about loading spinners? How about when there is an invalid email? What about logging an event in our analytics service?

BDD helps you better think through these extra user flows that you might otherwise miss. BDD is a type of test driven development, meaning you write your tests before you write your code.

Let's forget about jest for a second and just talk about what our login page should do:

It should render the login form. When the login button is clicked, it should check for a valid email. If the user entered an invalid email it should show a validation error. If the email is valid, we should show a loading spinner and try to log the user in. If the username and password are valid, it should store an auth token in local storage, add an event to Google Analytics and redirect the user to their NewsFeed. If the login credentials are invalid, it should hide the loading spinner and show an error.

Now let's break this description down a bit to make it easier to digest:

  • The login page:
    • It should render the login form
    • When the login button is clicked
      • It should check for a valid email
      • When the email is invalid
        • It should show a validation error
      • When the email is valid
        • It should show a loading spinner
        • It should log the user in
        • When login succeeds
          • It should store an auth token in localstorage
          • It should log an event in Google Analytics
          • It should redirect the user to their NewsFeed
        • When login fails
          • It should hide the loading spinner
          • It should show an error message

Now that we've broken our spec down into bullets, let's write some code. I've gone ahead and implemented an example based on testing a React component with Enzyme in this Gist.

If some of the syntax in the Gist is confusing, don't worry about it. The important part is what is follows each it and describe statement.

With Jest, you use a describe('when ... statement for each condition that could happen. You use an it('should ... statement for each thing that should happen given that condition.

https://gist.github.com/68b6e924728dbb7efc98229e773f1c98

You will notice in the Gist, our code follows the exact same format as our bulleted list and our bulleted list is just our original paragraph with extra spacing. If a reader can read a paragraph in English, they can read our code with over 100 lines of Javascript and make sense of it. No knowledge of software engineering necessary.

BDD is not an end all testing solution. Like anything in software engineering, it has a time and place. In our login page example above, one could argue that a BDD approach is overkill and that it would be more efficient to test that part of our application using Jest snapshots. If we are writing a string parser, it is probably more appropriate to use table driven tests.

However, the idea of thinking through the structure and the process of writing BDD specs before you start your code is a super powerful tool to add to your software engineering toolbelt. BDD will help you better think through the problem at hand and make sure you factor in every different logical path that your user could take.

Next time you write some tests, start with a bulleted list like our example above and see if you catch some logical edge cases you would've otherwise missed. At the very least, your co-workers will thank you for the increased readability during code review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment