Jest JavaScript Testing Framework
Jest is an open-source testing framework that has become increasingly popular recently. Developed by Facebook and built into the popular packagecreate-react-app
. Jest comes with built-in mocking and assertion abilities. In addition, Jest runs your tests concurrently in parallel, providing a smoother, faster test run.
Setting up a new project with Jest
Setting up a new project with Jest
Using npm: npm i -D jest
Using yarn:yarn add --dev jest
Simple Jest Test:
In package.json
{
"scripts": {
"test": "jest"
}
}
In functions.js file
const functions = {
add: (num1, num2) => num1 + num2
};
module.exports=functions;
In functions.test.js file
const functions=require('./functions');
describe("Addition", () => {
it("should add two numbers ", () => {
expect(functions.add(2,2,)).toBe(4);
});
});
Run yarn test or npm test, see the results below
PASS ./functions.test.js
Addition
✓ should add two numbers (11ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.035s
Ran all test suites.
Failure scenario:
const functions=require('./functions');
describe("Addition", () => {
it("should add two numbers ", () => {
expect(functions.add(2,2,)).toBe(5); #here expecting 5 instead of 4.
});
});
FAIL ./functions.test.js
Addition
✕ should add two numbers (9ms)
● Addition › should add two numbers
expect(received).toBe(expected) // Object.is equality
Expected: 5
Received: 4
4 | describe("Addition", () => {
5 | it("should add two numbers ", () => {
> 6 | expect(functions.add(2,2,)).toBe(5);
| ^
7 | });
8 | });
9 |
at Object.toBe (functions.test.js:6:33)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 3.692s
Ran all test suites.
npm ERR! Test failed. See above for more details.
Adding Multiple Tests
In this section, will see how to add multiple tests and add multiple data sets to validate a function.
In functions.js file
const functions = {
add: (num1, num2) => {
if (typeof(num1) !== 'number' || typeof(num2) !== 'number'){
return null;
}
return num1 + num2;
}
};
module.exports=functions;
In functions.test.js file
const functions=require('./functions');
describe("Addition", () => {
it("should add two numbers ", () => {
expect(functions.add(2,2,)).toBe(4);
expect(functions.add(23,44,)).toBe(67);
expect(functions.add(15,20,)).not.toBe(25);
expect(functions.add(-5,5,)).toBe(0);
expect(functions.add(30,-10,)).toBe(20);
expect(functions.add(8,0,)).toBe(8);
});
it("should not add string ", () => {
expect(functions.add(2,"2",)).toBe(null);
expect(functions.add("-10",10,)).toBe(null);
});
it("should not add objects ", () => {
expect(functions.add(20,[],)).toBe(null);
});
it("should not add arrays ", () => {
expect(functions.add(5,{},)).toBe(null);
});
});
Results:
PASS ./functions.test.js
Addition
✓ should add two numbers (6ms)
✓ should not add string (1ms)
✓ should not add objects
✓ should not add arrays (1ms)
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 1.595s
Ran all test suites.
Using Matchers
In functions.js
const functions = {
add: (num1, num2) => {
if (typeof(num1) !== 'number' || typeof(num2) !== 'number'){
return null;
}
return num1 + num2;
},
isNull: () => null,
checkValue: x => x,
createUser: () => {
const user = {firstname: 'Dave'};
user['lastname'] = 'McDowell';
return user;
},
getusers: () => ['Barbabas','Jennette','Cathlene','Ogden','Larry','Adrian'],
};
module.exports=functions;
In functions.test.js
describe("Matchers", () => {
it("Should use toBe", ()=> {
expect(functions.add(2,2)).toBe(4);
});
it("Should use not toBe", ()=> {
expect(functions.add(10,30)).not.toBe(50);
});
it("Should use toBeNull", ()=> {
expect(functions.isNull()).toBeNull();
expect(functions.checkValue(0)).not.toBeNull();
expect(functions.checkValue("Ping Pong")).not.toBeNull();
});
it("Should use toBeDefined", ()=> {
expect(functions.checkValue(null)).toBeDefined();
expect(functions.checkValue(0)).toBeDefined();
expect(functions.checkValue(5)).toBeDefined();
});
it("Should use toBeUndefined", ()=> {
expect(functions.checkValue(null)).not.toBeUndefined();
expect(functions.checkValue(0)).not.toBeUndefined();
expect(functions.checkValue(10)).not.toBeUndefined();
});
it("Should use toBeTruthy", ()=> {
expect(functions.checkValue(null)).not.toBeTruthy();
expect(functions.checkValue(0)).not.toBeTruthy();
expect(functions.checkValue(20)).toBeTruthy();
});
it("Should use toBeFalsy", ()=> {
expect(functions.checkValue(null)).toBeFalsy();
expect(functions.checkValue(0)).toBeFalsy();
expect(functions.checkValue(10)).not.toBeFalsy();
});
it("Should use toEqual", ()=> {
expect(functions.createUser()).toEqual({ firstname: 'Dave', lastname: 'McDowell' });
});
it("Should use toBeGreaterThan, toBeGreaterThanOrEqual, toBeLessThan, toBeLessThanOrEqual", ()=> {
expect(functions.add(5,6)).toBeGreaterThan(7);
expect(functions.add(5,3)).toBeGreaterThanOrEqual(8);
expect(functions.add(4,2)).toBeLessThan(10);
expect(functions.add(3.5,4.5)).toBeLessThanOrEqual(8.5);
});
it('Should use toBeCloseTo', () => {
expect(functions.add(2.331,3.223)).toBeCloseTo(5.55); //Expected difference: < 0.005
});
test('Should use toMatch', () => {
expect('Jest').not.toMatch(/k/);
expect('Jest').toMatch(/j/i); //ignore case sensitive
expect('megaphone').toMatch(/GAP/i);
});
test('Should use toContain (Arrays)', () => {
expect(functions.getusers()).toContain('Larry');
expect(functions.getusers()).not.toContain('Peter');
});
});
PASS ./functions.test.js
Matchers
✓ Should use toBe
✓ Should use not toBe (1ms)
✓ Should use toBeNull (1ms)
✓ Should use toBeDefined (1ms)
✓ Should use toBeUndefined (1ms)
✓ Should use toBeTruthy
✓ Should use toBeFalsy (1ms)
✓ Should use toEqual (2ms)
✓ Should use toBeGreaterThan, toBeGreaterThanOrEqual, toBeLessThan, toBeLessThanOrEqual (2ms)
✓ Should use toBeCloseTo
✓ Should use toMatch (2ms)
✓ Should use toContain (Arrays) (1ms)
Test Suites: 1 passed, 1 total
Tests: 12 passed, 12 total
Snapshots: 0 total
Time: 1.364s, estimated 2s