Testing in JavaScript with Jest
A common way to make sure code works is through the use of console.log, comparing its output to the expected result. This works, but there is another way that is more formulaic (and also often desired by companies) to test code, and that is through Jest.
Jest is a JavaSript testing framework that works with alot of things, including Babel, TypeScript, Node, React, Angular, and Vue. Install by entering:
npm install --save-dev jest
Example Test
Create a file called “sum.js”. Then copy the following code into the file:
function sum(a, b) {
return a + b;
}
module.exports = sum;
Now create a file called “sum.test.js”, then copy the following into it:
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
The test can be run with:
npm run test
At this point it is possible that you will encounter an error about an incorrect version. You can fix the error by:
- delete the package-lock.json file
- delete the node_modules folder
- open the package.json file and under“devDepencies” delete “jest”:“version_number”
- run npm install
- It should work now!
Your test will pass. If you instead changed your function in sum.js to be:
function sum(a, b) {
return a -b;
}
module.exports = sum;
the test will fail. For eahc test failed there will be an “Expected”” value and a “Received” value. You can look t these two values to try to figure out what went wrong with your code.
The general format is:
const variableName = require('./fileName')
test('test description', () => {
expect(functionName(arguments)).Matcher(result);
});
The . statement after the expect(function) is called a matcher. Matchers allow you to test a function for different things.
- If you expect a function to return a value you use “.toBe(value)” .
- If you expect a function to not return a value you use “.not.toBe()” with a value inside it.
- If you expect a function to return an object you use “.toEqual({key1: value1})” .
Truthiness Matchers
- “toBeNull()” will return true if the value is null.
- “tobeUndefined()” will return true if the value is undefined,
- “toBeDefined()” will return true if the value is defined,
- “toBeTruthy()” will return true if the return value is something an if statement will return “true” for,
- “toBeFalsy()” will return true if the return value is something an if statement will return “false” for
Number Matcher
- “toBeCloseTo(value)” is the version of “toBe(value)” for a float.
String Matcher
- “toMatch(/word/)” will return true if the return the return value contains the word
Array
- If the return value is an array, “toContain(item)” will return true if the array contains the item.
However, if there are multiple functions that you wish to test, based on what we had above you would have to make an individual file for each one. That is obviously a pain and we don’t want to do that. There is a way to instead have on file with a bunch of functions though; we just have to change the way we export.
Time to edit the sum.js file from earlier (this won’t be the proper name for it anymore though). This will contain multiple formulas which we will export, and will look something like this:
function sum(a, b) {
return a + b
}
function difference(a, b) {
return a - b
}
module.exports = {sum: sum, difference: difference}
We change the export so that instead of exporting the single function directly under the name sum, it exports an object which contains multiple functions.
We will have to change the test file a bit now too. It should look something like:
const formulas = require('./sum.js')
test('adds 1 + 2 to equal 3', () => {
expect(formulas.sum(1, 2)).toBe(3);
});
test('adds 7 - 3 to equal 4', () => {
expect(formulas.difference(7, 3)).toBe(4);
});
We set “formula” to equal the object that we exported from “sum.js”, and when we want to test one of the individual function we call formula.functionName.
Testing like this helps ensure that your code is working even for situations you may not have accounted for, so long as you use multiple tests for each function covering a wide range of possible inputs. To test what a function returns in react you have reset the page and trigger the conditions for the console.log() every time and examine the output, but this can be tedious, especially if the code in questions is only run after a long process is done. But with jest you just have to account for the different types of inputs your functions will get, and the tests will update the results automatically as you change your functions, make things much faster.
Happy code testing with Jest!