Jest Tutorial – JavaScript Unit Testing Using Jest Framework

In this Jest tutorial, we will learn about various Jest features, Jest Matchers, and how to use the Jest framework for JavaScript Unit Testing:

Jest is a Javascript Testing framework built by Facebook.

It is primarily designed for React (which is also built by Facebook) based apps but could be used to write automation scenarios for any Javascript-based codebases.

In this Jest testing tutorial, we will learn about various features of Jest, its matchers and see how we can use Jest with an end to end example. We will also explore about code coverage using Jest.

Jest Tutorial

List Of Tutorials In This JEST Series

Tutorial #1: Jest Tutorial – JavaScript Unit testing With Jest Framework
Tutorial #2: How To Test React Apps Using Jest Framework
Tutorial #3: Jest Configuration And Debugging Jest Based Tests


Getting Started With Jest Testing

Some of the advantages/features of Jest are given below:

  1. Zero configuration required.
  2. Fast: Jest tests run in parallel – this in turn greatly reduces the test execution time.
  3. Built-in code coverage: Jest supports code coverage out of the box – this is a very useful metric for all CI-based delivery pipelines and overall test effectiveness of a project.
  4. Isolated and sandboxed tests: Each Jest test runs in its own sandbox, which ensures no two tests can interfere or impact each other.
  5. Powerful Mocking support: Jest tests support all types of mocking – be it functional mocking, timer mocking, or mocking individual API calls.
  6. Support snapshot testing: Snapshot testing is relevant from the React perspective. Jest supports capturing a snapshot of the react component being tested – this can validate with the component’s actual output. This greatly helps in validating the component’s behavior.

Jest Framework For JavaScript Unit Testing

In this section, we will see an end to end example to write tests using the JEST framework for a simple Javascript function. Firstly, let’s see how to install the JEST framework in our project

JEST Installation

Jest is simply a node package and can be installed using any node-based package manager. Example, npm or yarn.

Let’s see some sample commands that can be used to install Jest package.

yarn add --dev jest
npm install --save-dev jest

For installing the Jest module globally, you can simply use the ‘-g’ flag along with the npm command. This will enable you to use Jest commands directly without configuring the package file for npm tests.

npm install -g jest

Using Jest In A Node-based Project

To use Jest in a node-based project, simply use the commands from the above section to install the node package for Jest.

Follow the below steps, in order to create a node project from start and then install Jest into it.

#1) Create a folder/directory with a name as your project name, for example, myFirstNodeProject

#2) Now using the terminal or command line, navigate to the project created in the above step and execute the npm init script using the below command.

npm init

#3) Once the above command is executed, it will prompt for different questions/parameters.

For example, the name of the project, version, etc. Simply keep pressing enter (and accept the default values). Once completed, you will see a package.json file created in your project. This is a mandatory configuration file for any node-based project

#4) Now execute the command to install the Jest package into the newly created project using the below command.

npm install --save-dev jest

This will install the Jest module (as well as its dependencies).

#5) Now, we have a node project ready with Jest bindings. Let’s configure the npm test script to run the Jest tests i.e. when the command ‘npm test’ is executed, the script should run all the Jest framework based tests.

To do that, update the package.json file and add a script section as shown below.

"scripts": {
  "test": "jest"
 }

The final package.json file will look as shown below.

{
 "name": "jest-e2e",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
   "test": "jest"
 },
 "author": "",
 "license": "ISC",
 "dependencies": {
   "jest": "^25.1.0"
 }
}

Writing Tests For A Javascript Function

In this section, we will create a simple Javascript function code for addition, subtraction, and multiplication of 2 numbers and write the corresponding Jest based tests for it.

First, let’s see how the code for our application (or function) under test looks like.

#1) In the node project created in the above section, create a js file named calculator.js with contents as shown below

const mathOperations = {
   sum: function(a,b) {
       return a + b;
   },
  
   diff: function(a,b) {
       return a - b;
   },
   product: function(a,b) {
       return a * b
   }
}
  module.exports = mathOperations

#2) Now, create a test file in the same folder for these tests, named calculator.test.js – this is the convention expected by the Jest framework to look for all the files that contain Jest based tests. We will also import the function under test, in order to execute the code in the test.

This is how the file would look with just import / require declaration.

const mathOperations = require('./calculator');

#3) Now, let’s write tests for different methods in the main file i.e. sum, diff, and product.

Jest tests follow BDD style tests, with each test suite having one main describe block and can have multiple test blocks. Also, please note that the tests can have nested describe blocks as well.

Let’s write a test for adding 2 numbers and validate the expected results. We will be supplying the numbers as 1 & 2 and expecting the output as 3.

describe("Calculator tests", () => {
 test('adding 1 + 2 should return 3', () => {
   expect(mathOperations.sum(1, 2)).toBe(3);
 });
})

Please refer to the below points w.r.t the test above:

a) The describe block is an outer description for the test suite i.e it represents a generic container for all the tests that we are going to write for the calculator in this file.

b) Next, we have an individual test block – this represents a single test. The string in quotes represents the name of the test.

c) Refer to the code in the expect block – “expect” is nothing but an assertion. The statement is calling the sum method in the function under test with inputs 1 & 2 and expecting the output to be 3.

We can also rewrite this in a simpler way to understand it better.

Please see below, now we have separated the function call and assertion as 2 separate statements to make it more succinct.

describe("Calculator tests", () => {
 test('adding 1 + 2 should return 3', () => {
   // arrange and act
   var result = mathOperations.sum(1,2)

   // assert
   expect(result).toBe(3);
 });
})

d) In order to run this test, simply run the command “npm test” in the terminal or command prompt at the project location.

You will see the output as shown below.

Run the command “npm test” in the terminal - Output

#4) Let’s try some more tests.

a) First, write a failing test and see what output we get. Let’s just change the result to some incorrect value in the same test that we wrote in the last section. See how the test looks like.

describe("Calculator tests", () => {
 test('adding 1 + 2 should return 10', () => {
   // arrange and act
   var result = mathOperations.sum(1,2)

   // assert
   expect(result).toBe(10);
 });
})

Here we are expecting a sum of 1 and 2 to return 10 which is incorrect.

Let’s try executing this and see what we get.

detailed output when a test is failed

You can see the detailed output when a test is failed i.e. what was actually returned and what was expected and which line caused the error in the function under test etc.

b) Let’s write more tests for the other functions i.e difference and product.

The test file with all the tests will look as shown below.

const mathOperations = require('./calculator');

describe("Calculator tests", () => {
 test('adding 1 + 2 should return 3', () => {
   // arrange and act
   var result = mathOperations.sum(1,2)

   // assert
   expect(result).toBe(3);
 });

 test("subtracting 2 from 10 should return 8", () => {
   // arrange and act
   var result = mathOperations.diff(10,2)

   // assert
   expect(result).toBe(8);
 });

 test("multiplying 2 and 8 should return 16", () => {
   // arrange and act
   var result = mathOperations.product(2,8)

   // assert
   expect(result).toBe(16);
 });
})

When the above tests are executed, the output given below gets generated.

Tests output for functions - difference and product

Video Tutorial: What Is Jest

Jest Matchers

Jest assertions use matchers to assert on a condition. Jest uses matchers from the expect Api. The expect API doc can be referenced here.

Let’s walk through some of the most commonly used matchers along with Jest tests.

#1) Equality

These are the most commonly used matchers. They are used for checking equality or inequality and is mostly used for arithmetic operations.

Let’s see some examples below:

Here we have written 2 matchers using toBe and not.toBe which are analogous to equals and not equals.

test("equality matchers", () => {
   expect(2*2).toBe(4);
   expect(4-2).not.toBe(1);
 })

#2) Truthiness

Here we will see, matchers for null, falsy, and truthy i.e. false and truth values. It’s important to note that anything that’s not logically true is falsy.

For example, number 0, null, empty string, NaN are all examples of falsy w.r.t Javascript.

test("truthy operators", () => {
   var name="Software testing help"
   var n = null
   expect(n).toBeNull()
   expect(name).not.toBeNull

   // name has a valid value
   expect(name).toBeTruthy()

   //fail - as null is non success
   expect(n).toBeTruthy()
  
   // pass - null treated as false or negative
   expect(n).toBeFalsy()

   // 0 - treated as false
   expect(0).toBeFalsy()
 })

#3) Number Matchers

These matchers could be used for general arithmetic operations.

For example, greaterThan, lessThan, greaterThanOrEqual, etc.

Check the below examples for more details

test("numeric operators", () => {

   var num1 = 100;
   var num2 = -20;
   var num3 = 0;

   // greater than
   expect(num1).toBeGreaterThan(10)

   // less than or equal
   expect(num2).toBeLessThanOrEqual(0)

   // greater than or equal
   expect(num3).toBeGreaterThanOrEqual(0)
 })

#4) String Matchers

A lot of times we need strings to match a regular expression as an assertion in a Unit test. Jest provides matchers for strings to be matched against a regular expression.

test("string matchers",() => {
   var string1 = "software testing help - a great resource for testers"

   // test for success match
   expect(string1).toMatch(/test/);

   // test for failure match
   expect(string1).not.toMatch(/abc/)
 })

Video Tutorial: Jest Matchers

Jest Hooks – Setup And Teardown

Just like all other xUnit based unit test frameworks, Jest framework also provides hooks for setup and cleanup methods. These hook methods are executed before and after each test in the test suite or before and after the testSuite execution.

Totally there are 4 hooks that are available to use.

  • beforeEach and afterEach: These hooks are executed before and after each test in the test suite.
  • beforeAll and afterAll: These hooks are executed just once for each test suite. i.e. if a test suite has 10 tests, then these hooks will just be executed once for every test execution.

Let’s see an example: We will add these hooks to the same test example of adding 2 numbers.

We will set the inputs in beforeEach hook for illustration. The test file would look with test hooks as shown below.

describe("Calculator tests", () => {
  var input1 = 0
 var input2 = 0

 beforeAll(() => {
   console.log("beforeAll called");
 });

 afterAll(() => {
   console.log("afterAll called");
 });
  beforeEach(() => {
   console.log("beforeEach called");
   input1 = 1;
   input2 = 2;
 });
  afterEach(() => {
   console.log("afterEach called");
 });

 test('adding 1 + 2 should return 3', () => {
   // arrange and act
   var result = mathOperations.sum(input1,input2)

   // assert
   expect(result).toBe(3);
 });
})

Tips & Tricks

#1) The command line reports are good but not very readable. There are libraries/modules available to generate HTML based test reports for Jest tests. It can be achieved as shown below.

  • Add node package for jest-html-reporter using the below command.
npm install --save-dev jest-html-reporter
  • Now add Jest configuration for the reporter in the package.json file of the node project.
"jest": {
   "reporters": [
     "default",
     [
       "./node_modules/jest-html-reporter",
       {
         "pageTitle": "Test Report"
       }
     ]
   ]
 }
  • Once configured now, execute the tests using the “npm test” command.
  • If the setup is successful you should be able to see an Html based report getting created in the project directory.

Test Report

#2) Creating Code coverage report: Code coverage is one of the most important metrics from a unit testing perspective. It essentially measures what percentage of statements/branches are covered for the application under test.

Jest provides out of the box support for code coverage. In order to get the Jest coverage report, Jest configuration needs to be added in the package.json file.

Add the configuration as shown below:

"jest": {
     "collectCoverage":true
   }

Once this configuration is done, try running the tests using the command “npm test”, and you can see the code coverage details just below the test execution results as shown below.

code coverage details

Video Tutorial: Jest Coverage & HTML Report Generation

Conclusion

In this Jest tutorial, we walked through the basics of the Jest framework. We learned how to install the Jest framework, and saw how it can be used for testing simple Javascript files.

We also explored the different types of matchers supported by Jest and covered Html reporters and code coverage reports too.

NEXT Tutorial