From the course: JavaScript: Test-Driven Development (ES6)

The purpose of unit testing - JavaScript Tutorial

From the course: JavaScript: Test-Driven Development (ES6)

Start my 1-month free trial

The purpose of unit testing

- [Instructor] So, now that we've covered the three main types of tests in TDD, we're going to look in a lot more detail at the most granular level of testing, unit testing. As I mentioned before, the purpose of unit tests is to test the smallest possible chunks of functionality in our production code. In most cases what this will mean is writing tests for individual functions that check whether given a specific set of inputs, the test produces the correct output. So, for example, if we wanted to write an addition function, not that we would ever actually have to do this but just for the sake of example, we would want to test that given the inputs, say four and five, the function produces the output nine. We also want to make sure that the tests we write check our functionality with diverse enough inputs to ensure that they actually test what they're supposed to test. And here's what I mean by that. Imagine that we only tested our addition function with the inputs two and two, to see that our function gives us the output four, well, that's great until we discover that we can also make this test pass by multiplying our arguments together, which is not what we want at all. So, in general, we want to make sure that our tests cover a representative range of possible inputs. Representative range here is sort of a fuzzy term but here's a rule of thumb I like to follow with regards to figuring out what a representative range of inputs means for tests. The rule of thumb is this, when you think you've been thorough enough in testing a piece of production code, check to see if it's possible to make breaking changes to your production code without breaking your tests. If it is, your tests aren't thorough enough and you need to write a test case that does break for whatever change you just made. So, in our example from before, if we had only tested our addition function with two plus two, we could see that we'd be able to break our addition function without actually making the test fail by multiplying the arguments together instead of actually adding them and we'd need to add another test case that makes sure our code is actually doing what it's meant to do. We also need to make sure our tests cover any edge cases that might come up in our application. For example, if we're writing a division function, you'd want to make sure to test it with zero as well as other numbers since dividing by zero is a special case in division. Or if you're writing a combined strings function, we need to think about how should it behave if we pass in a number. Or what about a Boolean? Of course, we only need to test these situations if we mean to actually use our functions in this way, in our code. With our addition function from before, we would never want to pass in a string or a Boolean as an argument so, the way that we express that our function doesn't support this is by simply not having tests to say that our function should work in that way. Or if there's a serious risk that the developers on your team will try to use the addition function in ways it wasn't meant to be used, you could always write a test to make sure that the function throws an error in those situations. So, I imagine that right now some of you may be starting to wonder if TDD is really worth the trouble. You may be thinking, how could TDD possibly be helpful to us if it means we have to spend our whole day thinking about our code and writing tests for every little situation? Again, what might at first seem like a terrible hindrance of TDD, the fact that it takes a little more time, at least at first, is actually one of the main sources of its benefits. It forces us as developers to really put a lot of thought into the code we write. Personally, I can't even begin to tell you how many times I've seen software break just because of some situation that developers didn't think of. And it's been stuff as simple as the examples we just saw. So then, in summary, the purpose of unit testing is to make sure that the smallest, most granular pieces of our code, this will usually be functions, work as we expect them to. If we imagine that we're building a house, the functions are the bricks and the unit tests make sure that these bricks are all sturdy and won't break wherever we put them.

Contents