• 4 hours
  • Easy

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/7/20

Learn test driven development (TDD)

The next step after starting the BDD process will be to segue into TDD!

TDD (test-driven development) is the natural second step to complete the BDD circle.

Here's how the two play together. You'll:

  1. Identify behaviors using BDD

  2. Write tests for these behaviors using TDD

The good news is that you already did a lot of relevant work writing out behaviors that you want to test because you wrote detailed specs during the behavior driven development phase.

Test-driven development means writing the most basic solutions you can to make your tests pass. Once you get one test to pass by writing the simplest code possible, you're done -- you can then advance to the next test.

The three rules of TDD according to Robert Martin (a major TDD advocate) are as follows:

  1. You must write a failing test before you write any production code.

  2. You must not write more of a test than is sufficient to fail, or fail to compile.

  3. You must not write more production code than is sufficient to make the currently failing test pass.

These 3 rules together result in a process called the red-green-refactor cycle.

Red-green-refactor cycle

The red-green-refactor cycle will be a helpful, nicely repetitive process as you start writing your tests. Let's see how it gets its name:

Red: You write a simple test that fails before it actually has any code accompanying it. The test obviously fails. Therefore, it is red.

Green: you write the simplest code possible to make the test pass, even if it's a little ridiculous. The test passes and is therefore green.

Refactor: the code you wrote to make the test pass is perhaps illogical and messy. Clean it up now. 

Next, you'll go back and write the next failing test, starting the red-green-refactor cycle all over again.

Writing your first test that fails

Using the example in the last chapter involving comment length, the first test you'd write would check that a comment over 1000 characters returns an error message.

Ultimately, a test for this scenario might look like this:

describe("Saving a comment", function() {
    it("should throw an error if the comment is over 1000 characters", function() {
        comment.length = 1200;

        expect(function() {
            comment.save();
        }).toThrowError("comment is too long");
    });
});

Above, we:

  1. describe the feature.

  2. identify how it should behave. 

  3. set a comment length of 1200 as a hypothetical scenario.

  4. identify that we expect this comment not to save properly because it's too long.

Next, you'll run this test and hope that it will fail. Bear in mind that this is just the test though. The test will indeed fail, because it has no code associated with it! 

In order to make the code test pass, you'll write the accompanying code in another file that evaluates comment length and returns an error or not.

One way or another, that code would probably check that  comment.length < 1000  (the length of the comment is less than 1000 characters). 

Once you've written the accompanying code that makes a test pass, you can move onto the next set of code and test.

Going from less to more specific

Your tests will get more and more specific as you write them for more specific scenarios. Interestingly, this means your code will become more and more general, because you're writing it to accommodate more situations.

Looking back at the previous example, you might want to also test that comments that are exactly 1,000 characters save properly. This a modification that would enlarge the span of your code to accommodate more situations.

In your test's current state, passing a comment length of 1000 to your previous test would fail, because you defined that a comment must be less than 1000 characters. 999 would be fine, but 1000 wouldn't.

You could then update your code to check   comment.length ≤ 1000  (the length of the comment is less than or equal to 1000 characters), re-run the test, see it pass, and then move onto the next test! 😎

Recap: BDD and TDD together

BDD

To recap, your first step in the testing process will be to map out the behaviors you expect from a certain functionality. If you can't do this by yourself, involve other project stakeholders.

Write out the expected behaviors using BDD keywords like Given, When, Then, and And. Let expected behaviors clarify your coding needs beforehand.

TDD

Next, you'll write tests for the expected behaviors you defined above. The tests you write to check certain conditions will, of course, fail at the beginning because you haven't actually written the code for the functionality you're testing!

You write one test, and that test fails. You write some code elsewhere in your codebase to make the test pass, and then you're done with that test!

It's soon time to take these general testing mentalities and apply them to frontend testing next!

Example of certificate of achievement
Example of certificate of achievement