Product Engineering

Jest – Fast and Furious Unit Testing Framework

blog_framework_testing

Jest is an open source JavaScript unit testing framework, used by Facebook to test all JavaScript code including React applications. Jest is built on top of Jasmine. Unit testing of JavaScript code without jest framework needs Test runner such as Mocha or Jasmine, assertion library such as Chai, mocks, stubs, mocking library such as Sinon. But Jest is having in built all features available.

Due to zero configuration, test execution time using Jest is very less as compared to other existing frameworks. It automatically finds and executes tests with file extensions like .spec.js, .test.js. Jest provides great integration with Babel, which is helpful for applications which are using ES6 features. With Fast interactive watch mode, it runs only the tests that are relevant to the changes made in the files. No additional setup needed for the generation of code coverage report. Also, it is very easy to migrate JavaScript test files from other frameworks into Jest using Code mods tool.

One of the additional feature provided by Jest is Snapshot testing. Initially, during the first run, Jest will render UI layout, actions of application component and captures a snapshot in .snap file. If anything changes in a component, then Jest will fail the unit test cases by comparing with saved snapshots. Then the developer can update the snapshot by jest –updateSnapshot command. The size of a snapshot file is very less than 300KB. Also, Jest can save snapshots in a human-readable format by the use of external plugins like pretty-format, eslint-plugin-jest etc.

Installation Steps:

  • Add Jest in the devDependencies part of the package.json file, so that it will only be installed in the development environment and not in production.
  • Use the terminal to run the following commands.
    npm install --save-dev jest or
    
    yarn add --dev jest
  • Add a .babelrc file in the project’s root folder. If the application is made using ES6 and React.js, then add babel-preset-env and babel-preset-react presets in .babelrc file as shown below.
    {
      “presets”: [“env”, “react”]
    }
  • Add the following code to your package.json file
    “Scripts”: {
         “test”: “jest”
     }

    Following is the basic syntax for writing any test case.

    describe('Test Suite Description', () => {
      test(Test case description, () => {
        expect(1+1).toBe(2)
      })
    })

 

Following are the common list of assertion methods provided by Jest.

  • toBe returns true is expected value is equal to defined value.
  • toEqual returns true if the expected object is equal to the defined object.
  • toBeNull returns true if the value is null
  • toBeUndefined returns true if the value is undefined
  • toBeDefined returns true if the value is not undefined
  • toBeTruthy returns true if the expected value is true
  • toBeFalsy returns false if the expected value is false
  • toBeGreaterThan returns true if the expected value is greater than the defined value.
  • toBeLessThan returns true is value is expected value is less than defined value.
  • toMatch returns true is expected value matches with the regular expression.
  • toContain returns true if the array contains the defined value.

 

Example:

In the application folder hierarchy, Create a folder named tests which will contain all the test files.

First, in the src folder, create a mathUtility.js file and write a couple of functions using ES6 syntax for which we want to write unit test cases.

export const addition = (c, d) => c + d
export const multiplication = (a, b) => a * b
export const subtraction = (a, b) => a - b
export const division = (a, b) => a / b
export default { addition, multiplication, subtraction, division }

Now create a mathUtility.test.js file, in the tests folder, and there we’ll use Jest to test the functions defined in mathUtility.js:

import { addition, multiplication, subtraction, division } from ‘../tests/mathUtility’
describe("math utilities", () => {
  test("addition : should add given two numbers", () => {
    expect(addition (4, 2)).toBe(6)
  })
  test("multiplication : should multiply given two numbers ", () => {
    expect(multiplication (4, 2)).toBe(8)
  })
  test("subtraction : should subtract given two numbers ", () => {
    expect(subtraction (4, 2)).toBe(2)
  })
  test("division : should return division of given two numbers", () => {
    expect(division (4, 2)).toBe(2)
  })
})

After running yarn test or npm test in a command line, it will execute all the test cases and returns the number of passed or failed test cases as shown in below screenshot.

yarn test –watch will run the test cases and stay in watch mode to re-run them whenever any code changes are made.

Yarn test

After execution of unit test cases, jest creates coverage folder which contains test execution report as shown below.

unit test

all files

Jest provides beforeAll and beforeEach functions if we want to perform some initialization before execution of tests.

beforeAll (() => {   // perform initializations before all the tests run
})
beforeEach (() => {  // perform initialization before every test runs
})

Also, Jest provides afterAll and afterEach functions if we want to perform restoring or resetting after tests.

afterEach (() => {   // perform something after each test runs
})
afterAll (() => {  // perform something after all tests end
})

 

Benefits:

For one of the client we have implemented Jest unit testing framework and we see following benefits.

  • Jasmine/Karma framework used earlier used to take 7-8 minutes to execute 1800 test cases, with Jest the total time has come down to 3-4 minutes as shown in below coverage report.

benefits

  • Due to the reduction in test case execution time, the CI-CD execution time also gets reduced. This saves lot more time for the day to day development as well as deployment to different environments.
  • Using the Jest Snapshot feature, we can baseline the component, which reduces analysis time and code redundancy.