Lesson notes

Tests are pieces of code that check if other code works correctly. assert is a common name for such testing functions, and it's also a name of a JavaScript testing library. Library means a collection of helper functions, some code from other people you can add to your program and simplify your work.

Assert accepts an expression and complains if it's not true. Here a test is checking if square(2) is 4:

assert(square(2) === 4);

And here — if square(6) is not 4:

assert(square(6) !== 4);

If the asserted expression is true, then the test passes.

And this is how it complains if the expression is not true:

Assertion error: false == true
  at square (/home/rakhim/code/planets.js:4:3)
  at surfaceArea (/home/rakhim/code/planets.js:8:10)

There is a special separate function to check equality:

assert.equal(square(2), 4);

And this is how it complains when the test fails:

Assertion error: 6 == 4
  at square (/home/rakhim/code/planets.js:4:3)
  at surfaceArea (/home/rakhim/code/planets.js:8:10)

This is better, because you can see the actual result (6) and the expected result (4), and how they don't match.

Recommended watching


Lesson transcript

So you're programming, writing code, functions, and all that stuff. You want it to work, of course, so you make sure your code is correct, doesn't have any errors and does what you think it does. You're not too worried about syntax or type errors because you'll find them right away when you run your programs.

But there is one sneaky type of error that doesn't really show up explicitly, and computers have no way of finding them really without us. Logic errors.

Suppose you've written a square function. It takes a number and returns it squared. Give it 2, you suppose to get 4. Give it 6, you suppose to get 36.

If you made a mistake, and this function returns the wrong value, the computer or the programming language interpreter wouldn't be able to see it as a mistake. They just do what you tell them to do, so if you tell them that square of 2 must be 11, then it will be 11, and that's it.

One obvious way to make sure your function does what you want is to run it and see.

We can do console.log(square(2)); and if it prints 4 then it's all good. Well, maybe, not all good, just to be safe, let's also check square(6). It's 36, okay, good. Well, one more, square of 100. Ten thousand, good.

At this point, you can be pretty sure that your square function is indeed finding a square. This function is simple, and you won't spend hours testing it. But not all of your functions are simple like that. Even a factorial function from few lessons ago is much much more complex.

Oh, and you know what? 2, 4 and 100 are not enough, really. You also have to check negative numbers, right? -2 squared should be 4, not -4, and we didn't check it. Oh, and 0 squared. Oh, wait! Another thing: we have to check that this square function doesn't explode when you pass it something wrong, like a string. It should probably say that "dog" squared is not a number.

Writing all these things and printing them by hand is kind of weird, especially considering we have this powerful machine that does what we tell it to do. So let's tell it to test our functions for us. We know what those functions SHOULD return. So the computer can check if they DO return it.

Consider a function called assert that takes an expression involving three things:

  • the function we want to test
  • the argument this function takes
  • the value we THINK this function should return

assert will tell us if the function really does return the value we expect.

Let's call assert to see if the square function returns 4 when called with 2:

assert(square(2) === 4);

If our square function is correct for the case of 2, then it will return 4, and since 4 is equal to 4, assert will not complain. We say: this test passed.

Another scenario: square of 6 definitely should not be 4. So:

assert(square(6) !== 4);

This test will pass if the square function returns something other than 4.

What happens when the function in question doesn't work properly? For example, it says that 2 squared is 6, not 4. Then the first test will fail and we'll see an error like this:

Assertion error: false == true
  at square (/home/rakhim/code/planets.js:4:3)
  at surfaceArea (/home/rakhim/code/planets.js:8:10)

It looks very much like a syntax error or a type error, and thanks to that magic assert function we see a new type of error here — assertion error. It means some test didn't pass, failed, so we need to fix our code.

Here it says Assertion error: false == true. This is because the test expected the expression to be true, but it was false. square(2) === 4 suppose to be true, but since our broken square function returns 6, the expression becomes false. false is not true, hence — the error.

There is a stack trace below, it shows you where to find the failing test — the filename, the line number in that file and the position on that line.

There are other assert functions for convenience and better, more readable results. Here is one:

assert.equal(square(2), 4);

assert.equal is a special function to test equality, and it takes two arguments: the thing you want to test and the value you expect. Passing test will just pass, but failing test will give you some information:

Assertion error: 6 == 4
  at square (/home/rakhim/code/planets.js:4:3)
  at surfaceArea (/home/rakhim/code/planets.js:8:10)

You can see what the actual result was and what the expected result was, and the particular case where they don't match.

This assert function is not just something I imagined, it's a testing library for JavaScript programs. Library means a collection of helper functions, some code from other people you can add to your program and simplify your work.

There exist other libraries for testing code in JavaScript and similar libraries in other programming languages. Testing code is very important and often a big chunk of all the code a company produces is just tests. For example, this website, hexlet.io, consists of tens of thousands of lines of code, and one third of them are tests, basically lines like that — "assert something is what we think it is".

And every time we make changes — add new features or change existing ones — we run tests to make sure nothing is broken.

Go ahead and start the exercise. You will write some tests yourself!