Why Use Test-Driven Development
Understand why test-driven development is useful.
We'll cover the following
Test-driven development uses
Test-driven development (TDD) is sometimes defined as writing tests first. Although that’s an important part of the methodology, it’s not the essence. The essence of TDD is rapid iteration. You’ll find that you learn more quickly from iterating than you would from trying to plan out a complex program from the ground up. You’ll discover bad assumptions and potential pitfalls before you invest too much work. And you’ll find the process more enjoyable. It’s a smooth, incremental progression rather than an alternation between bursts of inspiration and plateaus of “What do I do next?”
The project for this chapter will be a solver for the classic programming challenge Fizz Buzz. Here are the rules of Fizz Buzz:
Write a program that prints the numbers from 1 to 100. But for multiples of three, print “Fizz” instead of the number, and for the multiples of five, print “Buzz.” For numbers that are multiples of both three and five, print “FizzBuzz.”
In this section, you’ll apply the TDD process to implement a function that takes a number and returns the appropriate Fizz Buzz output. First, you’ll write a single test, knowing that it’ll fail. Second, you’ll write an implementation that satisfies the test. Once the test is passing, you’ll use Git to save your progress.
Starting from failure
-
Create an
index.js
with a placeholder implementation offizzBuzz()
, so that your tests will have a valid referent:// index.js module.exports = (num) => `${num}`;
-
Now add an
index.test.js
with a test for a single Fizz Buzz rule:// index.test.js const fizzBuzz = require('./index'); describe('fizzBuzz()', () => { it('returns "FizzBuzz" for multiples of 3 and 5', () => { expect(fizzBuzz(15)).toBe('FizzBuzz'); expect(fizzBuzz(30)).toBe('FizzBuzz'); }); });
-
Run the test:
$ npm test ... FAIL ./index.test.js fizzBuzz() ✕ returns "FizzBuzz" for multiples of 3 and 5 (7ms) ● fizzBuzz() › returns "FizzBuzz" for multiples of 3 and 5 expect(received).toBe(expected) // Object.is equality Expected value to be: "FizzBuzz" Received: "15" 3 | describe('fizzBuzz()', () => { 4 | it('returns "FizzBuzz" for multiples of 3 and 5', () => { > 5 | expect(fizzBuzz(15)).toBe('FizzBuzz'); 6 | expect(fizzBuzz(30)).toBe('FizzBuzz'); 7 | }); 8 | }); at Object.it (index.test.js:5:32) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 0.771s, estimated 1s Ran all test suites.
You may have cringed when you saw that glowing red FAIL
. After all, having tests fail against production code is bad. But having tests fail during development can be a good thing. It means that you’ve anticipated some way your code could fail. Think of every failing test you see during development as a potential bug you’ve preemptively squashed.
Run the
npm test
below, to see your test cases failing, and explore why it failed using all the feedback from thenpm test
.
Get hands-on with 1400+ tech skills courses.