DEV Community

Kristijan Pajtasev
Kristijan Pajtasev

Posted on • Originally published at kristijan-pajtasev.Medium

Unlock the Power of Node.js Testing with the New Node Test Runner Feature

Node.js has recently released a new version (v20). In it, Node.js announced that its new feature, the Node Test Runner, has become officially stable. This new feature offers developers a standardized way to test their Node.js applications, ensuring that their code is reliable and bug-free. In this article, we will be taking a look at the basics of the Node Test Runner and how it can be used to make testing Node.js applications easier and more efficient.

NodeJS logo

Initial setup

The great thing about the built-in test runner feature, there is no need for installation. If you ever tried to introduce anything in a software project, especially in the JavaScript world, you probably already know. Things can get messy. Complicated setups, incompatible versions, and missing features are just some of the problems that often make you start regretting your decision to improve your code. This is not the issue here. Do you want to make a test? Just import the node:test module, and you will get commands like describe, test, and it.

import {test, describe} from 'node:test';

describe("test suite", function() {
  test("test if works correctly", function() {
    // run some test
  })
})
Enter fullscreen mode Exit fullscreen mode

I am assuming you already have at least some basic experience with testing, so I am not going into too much detail. But very short, the describe function is for your test suit. It is a good way to group your tests based on functionality for better readability, and the test function is a place where your test is executed.

First test

The first test will be very simple. It will be redundant but the focus now is how to test something. This is done by using the assert command. This command is part of Node.js as well but under a different module. You can import it from the node:assert module. Once you import the object from there, it contains many different assertion commands. In the next code example, I am just using one checking equality.
import {test, describe} from 'node:test';
import assert from 'node:assert';

describe("example test suite", function() {
  test("test true is equal to true", function() {
    assert.equal(true, true);
  });
});
Enter fullscreen mode Exit fullscreen mode

As already said, this example above is a simple one. But there are many other assertion functions provided in the node:assert module like strictEqual. The difference is that strict also checks the type of value, and that is something used when comparing number values. The function used above would pass for both the number value 1 and the string value 1.

Example

This example will be quite simple as well. In it, I do want to demonstrate some simple ways to write tests against the real function that returns the sum of two numbers. That function is in the following code snippet.

function addNumbers(first, second) {
  if(typeof first !== "number") 
    throw new Error("Invalid first parameter type");

  if(typeof second !== "number") 
    throw new Error("Invalid second parameter type");

  return first + second;
}
Enter fullscreen mode Exit fullscreen mode

As you can see, simple function. Just adds two numbers, and in case any of them is invalid, it throws an error with the appropriate message. There are three scenarios we would want to test here. First is that if we call it with the right parameters, it will return the correct result. The other two are error scenarios. One for the first parameter being invalid, and the second for the second parameter being invalid.

describe("helpers function addNumbers", function () {
  test("adds two numbers", function () {
    assert.strictEqual(addNumbers(1, 1), 2);
    assert.strictEqual(addNumbers(1, 2), 3);
    assert.strictEqual(addNumbers(1, 3), 4);
  })

  test("throws error when first parameter invalid", function () {
    assert.throws(() => {
      addNumbers("invalid value", 2)
    }, {message: "Invalid first parameter type"});
  })

  test("throws error when second parameter invalid", function () {
    assert.throws(() => {
      addNumbers(1, "2")
    }, {message: "Invalid second parameter type"});
  })
})
Enter fullscreen mode Exit fullscreen mode

In the error scenarios, you might notice that the function call is wrapped inside of the function. That is needed because you can’t assign thrown error to a variable, and it would just exit the test function before even running it.

Running tests

Running node tests is quite simple. All you need to do is run node --test command. When running it, you can specify explicitly which test files you want to run. If you don’t, Node will look into all files in folders named test and all files in other folders whose basename starts with test, test- or ends with test, -test and _test.

Conclusion

Node test runner was only released as stable in version 20, released just a few days before writing this article. So it is not surprising that it is still a bit limited in possibilities, but there is still quite a lot more than I covered in this article. There are mocking capabilities, reporting, and code coverage feature which is still experimental. But I do hope it was enough just to help you get started and try it out. And you can download the code from my GitHub repository.


For more, you can follow me on Twitter, LinkedIn, GitHub, or Instagram.

Top comments (0)