Testing with Node.js: Understand and Choose the Right Tools
What are the tools you need for testing with Node.js and which ones to choose for your purpose?
If you’re here today, there is a 99% chance you want to get started with testing in a higher-level environment, but lack the low-level knowledge. You might be working on Frontend or Backend with Node.js, but don’t know where to start. Congratulations, you’re in the right place.
Test types
If you are not familiar with testing, you might get a bit lost. There are a lot of test types, but some are more common.
The following article from Atlassian provides a good starting point.
As we will take our first step in the Node.js test environment, our scope will revolve around unit and integration tests.
Different tools
Now, you might be wondering about where to start. You’ve seen a Node.js project that uses Jest, heard about Mocha or Chai but you are not sure what those are about.
Great, that’s exactly what we will be discussing today. To have a clearer picture, we can separate the different kinds of tools we need.
Test runners
You have this vague idea of writing tests but how do you organize and run them? This is the role of test runners. Some of their functionalities are:
Finding test files and running tests
Reporting a test success or failure
Configuring which tests to run or re-run when updated
Setting up an environment
And a lot more.
Here is a graph comparing the most popular Node.js test runners by download:
Assertions
Now that you have an environment where you can write your tests, we come to the most important question: How do I write my first test?
From our previously cited article, Atlassian says the following about unit tests:
They consist in testing individual methods and functions of the classes, components, or modules used by your software.
From a practical perspective you can view it as the following:
Get the result from your individual unit (function for example) in a situation (with defined parameters).
Ensure the given result match the expected one.
That’s what assertions are about: comparing the received result with the expected one to report the test as a success or failure.
Like tests runners, there are several libraries helping you with assertions:
Spies
With unit and integration testing comes a difficulty:
You might want to unit test a function that relies on an external dependency.
For unit as well as integration tests, your function can have a native dependency you cannot use in a JS environment.
Your function is making an API call but your server is not set up in your testing environment.
That’s where spies are used. They help you create fakes (or mock objects) and replace dependencies with an object you defined.
In the same way, several spy libraries can help you:
Making a choice
Great, you now have a general idea of what tools you need and a list of the most popular ones. Now comes the hardest part: which tools to choose?
Test runner
To be honest, I never really considered Jasmine, Ava, and QUnit.
I first started testing with Backend projects. At the time, Mocha was the more widely used, that’s the only reason why I started using it (with Chai).
Mocha worked great for a few years and then two changes happened:
I started to specialize in React
Jest started to overthrow Mocha
At this point, I had to do a serious comparison.
Mocha is a test runner that lets you choose an external assertion and spy library. It doesn’t restrict you but gives you more flexibility.
Jest is a whole testing framework, shipped with React and maintained by Facebook. From the previous sections and graphs, you might have noticed that more than a test runner, Jest includes its own assertion and mock libraries.
It’s interesting to note that Jest was built on top of Jasmine.
Both are very similar. Of course, their APIs change, and you need to get used to it when going from one to the other.
I’m a big fan of having a single library/framework/utility that fulfills a given role. After trying out Jest and experimenting with React, I definitely adopted it.
Afterward
Once you understand how to write tests, your best move would be to write great tests.
Test-Driven Development is a software development process that will definitely help you in writing great tests. Another useful tool is Code Coverage.
I would like to complete the article from Atlassian on Code Coverage by saying the following:
If your Code Coverage is below 100% you can be sure you didn’t test everything. If it’s 100% … you don’t know.
Code Coverage can tell you if your code has been executed during your tests. Sometimes, you’ll end up executing code without really testing it. To be sure that you really tested everything, you must resort to Mutation Testing.
Mutation Testing is great but really expensive, and cannot be used as much as unit/integration testing.
Once you get into testing, you often see the following pyramid:
What this represents is how many tests you should have. As unit tests are cheap to write and run, you should have plenty of them.
Still cheap but less than unit tests are: integration tests. It’s expected for an application to have a lot of integration tests but less than unit tests.
Finally, you’ll have e2e tests but in fewer numbers, as those are expensive to set up, write, and run.
Good luck on your testing journey.
Cover photo by flowforfrank on Unsplash