Either you are in a deep love with unit testing or hating it to the core, but the bottom line is to do it anyway. So just like many things in our life, let us deal with it; in this article we will start exploring the realm of unit testing along with JEST.
If you ask me what I think about unit testing in general, then I would say it's another kind of drug that is available in the market. Don't get me wrong, nothing negative here; but at first you hate it and cry in the initial phases. You don't, and never want to judge your own code; because your code is super awesome and will never going to break. As a developer we are no different, we share the same initial thought process in our early phases of our coding journey. But a mature developer knows he/she is human after all, and definitely going to make mistakes; but rather than denying it accept and learn from our mistakes. Unit testing comes from that learning and realization only. So, in order to make our code robust and reliable we need to make it go through some harsh and soft test cases that helps to prove worthiness of written code. Enough of prep talk! Now if we are all on boarded to explore some ABCD of unit testing will start with the super popular JEST unit testing framework.
JEST is a delightful JavaScript unit test framework, which is quite popular among the dev squad. In this article our goal will be to get started with JEST and understand the ecosystem and write a dumb unit test case that actually runs. So, if you are already familiar with JEST then this article might not be a right fit for you since you are already a meta! But surely it will make you feel nostalgic. Without further ado will get our hands dirty.
We will gonna use Node.js for running our JavaScript code and of course pre-requisite will be Node.js to be avail in your system.
Create a fresh directory and initialize using NPM initialize command:
mkdir jest-started
cd jest-started
npm init
After providing necessary detailing to your package.json file its time to add JEST dependencies:
npm i jest -D
npm i @types/jest -D
Make sure to install them as dev-dependencies -D, since unit testing is something for dev and not for production. Otherwise, it will increase the bundle size of your project at the time of production.
For starter we are just adding one command to at least run our test case in the script property of package.json file. Later, we will explore some more version of the below command:
package.json
"scripts": {
"test": "jest"
},
Let's be very gentle and write super simple program that a school student can write and understand:
index.js
const sum = (num1, num2) => num1 + num2;
module.exports = {
sum,
};
Its time to write a test case/spec for the sum function, for this create a file with same name "index.test.js" but ends with test.
index.test,js
const { sum } = require('./index');
// test suite
describe('Index', () => {
// test spec
it('should add two numbers', () => {
// arrange
const expected = 30;
// act
const received = sum(10, 20);
// assert
expect(received).toBe(expected);
});
});
Here, we are writing a test suite using the describe() and a test spec using it() methods of JEST. Inside of the it() method, just like any other test case we are doing some arraignment of data, acting upon the code and finally doing an assert operation on our expectation using expect() method of JEST, followed by a matcher function toBe() to prove our expectation.
Congratulations! You have written your first JavaScript unit test case code without dropping a single sweat or blood. Keeping the code this much only let us now explore the surroundings.
Now its time for the actual show down, run your unit test with the beautiful npm script:
npm test
> jest-started@1.0.0 test
> jest
PASS ./index.test.js
Index
v should add two numbers (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.511 s, estimated 1 s
Ran all test suites.
Here, it runs your test for your index.test.js file and provide you the passed/fail status. It shows the total passed test suits and specs. You can try to tweak the code by making the expected value to be different, this will show result as below:
npm test
> jest-started@1.0.0 test
> jest
FAIL ./index.test.js
Index
× should add two numbers (3 ms)
? Index › should add two numbers
expect(received).toBe(expected) // Object.is equality
Expected: 40
Received: 30
12 |
13 | // assert
> 14 | expect(received).toBe(expected);
| ^
15 | });
16 | });
17 |
at Object.toBe (index.test.js:14:22)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.68 s, estimated 1 s
Ran all test suites.
Here, clearly mentions what it was expected and what actually received along with the line number it failed.
JEST has a couple of options that come along with the default JEST command. These options allow us to make a command that suites our project needs and requirements. Let us create some new custom commands inside package.json file using these options:
package.json
"scripts": {
"test": "jest",
"test-watch": "jest --watchAll",
"test-verbose": "jest --verbose",
"test-coverage": "jest --coverage",
"test-fat": "jest --watchAll --verbose --coverage"
},
Here, we have added a command called "test-watch" with option named "--watchAll", this will make the jest runs in the background to continuously watch your folder for any change in your test/spec files and runs the result. This one is pretty handy if you are doing continuous changes. The second command provides detailing to individual test specs even if you have multiple test files, otherwise the default command just shows the pass/fail status of each file. The coverage command generates a coverage report the get displayed on the console and also creates an entire HTML report (Istanbul Coverage) that helps to explore all of the test cases present inside a folder at project level. The last and final command is just for fun to have all of these options combined together. Explore more such CLI options.
A coverage report provides you an overall picture of unit test case coverage project/folder wide. This helps to determine missed statements, lines, branches and functions. By default, 80% or above coverage is a green.
npm run test-coverage
> jest-started@1.0.0 test-coverage
> jest --coverage
PASS ./index.test.js
Index
v should add two numbers (1 ms)
---------------|------------|----------------|---------------|------------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|------------|----------------|---------------|------------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
---------------|------------|-----------------|---------------|------------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.84 s
Ran all test suites.
Here, the console report shows the files present in the folder, and percentage of the mentioned factors. At the end it shows total number of passed/failed test suites/cases. This even created the Istanbul report, generated at coverage\lcov-report\index.html folder; every time you runs the command it will re-generate the "coverage" folder.
There are couple of tools available for the debugging; but here our focus is on VS Code only; there is this awesome VS Code extension named Jest available using which we can debug the written test cases. Once installed it automatically runs all the test cases, you can add breakpoints and press run/debug button on all or individual test cases to debug the test. Apart from this just to speed up the coding speed of unit test cases we can use Jest Snippets VS Code extension to have short hands for JEST related methods.
December 31, 2020
October 19, 2020
March 02, 2022