Jest Tutorial for Beginners: Getting Started With Jest for JavaScript Testing
Tags: testing, javascript, es6, beginners
Published: 2019-08-26 08:55:56

---
title: "Jest Tutorial for Beginners: Getting Started With Jest for JavaScript Testing"
published: true
description: "What testing means? How to test JavaScript code with Jest? Learn the basics of testing JavaScript with this Jest tutorial for beginners!."
tags: testing, javascript, es6, beginners
canonical_url: https://www.valentinog.com/blog/jest/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/80hckl6lvyk38sxwj95w.png
---

**Just crossed 5k follower on dev.to! Thank you everyone! What a fantastic community! Who's on Twitter too? Let's connect => [I'm here](https://twitter.com/gagliardi_vale)**.

_What means testing? How to test JavaScript code with Jest? Learn the basics of testing JavaScript with this Jest tutorial for beginners!_

## What means testing?

In tech jargon **testing means checking that our code meets some expectations**. For example: a function called "transformer" should returns the **expected output** given some **input**.

There are many types of testing and soon you'll be overwhelmed by the terminology, but long story short **tests fall into three main categories**:

- **unit testing**
- **integration testing**
- **UI testing**

In this Jest tutorial we'll cover only **unit testing**, but at the end of the article you'll find resources for the other types of tests.

## Jest Tutorial: what is Jest?

[Jest](https://jestjs.io/) is a JavaScript test runner, that is, a JavaScript library for creating, **running**, and **structuring tests**. Jest is distributed as an NPM package, you can install it in any JavaScript project. Jest is one of the most popular test runner these days and the default choice for Create React App.

## First things first: how do I know what to test?

When it comes to **testing**, even a simple block of code could paralyze beginners. The most common question is **"How do I know what to test?"**. If you're writing a web application a good starting point would be testing every page of the app and every user interaction. But web applications are also made of **units of code like functions and modules** that need to be tested too. There are two scenarios most of the times:

- you inherit **legacy code** which comes **without tests**
- you have to **implement a new functionality** out of thin air

What to do? For both cases you can help yourself by thinking of **tests** as of bits of code that **check if a given function produces the expected result**. Here's how a typical test flow looks like:

1. import the function to test
2. give an **input to the function**
3. **define what to expect** as the output
4. **check if the function produces the expected output**

Really, that's it. Testing won't be scary anymore if you think in these terms: **input - expected output - assert the result**. In a minute we'll also see an handy tool for checking almost exactly what to test. And now hands on Jest!

## Jest Tutorial: setting up the project

As with every JavaScript project you'll need an NPM environment (make sure to have Node installed on your system). Create a new folder and initialize the project with:

```bash
mkdir getting-started-with-jest && cd $_
npm init -y
``` 

Next up install Jest with:

```bash
npm i jest --save-dev
``` 

Let's also configure an NPM script for running our tests from the command line. Open up **package.json** and configure the script named "test" for running Jest:

```json
  "scripts": {
    "test": "jest"
  },
``` 

and you're good to go!

## Jest Tutorial: specifications and test-driven development

As developers we all like creativity freedom. But when it comes to serious stuff most of the time you don't have so much privilege. More often than not we've got to follow **specifications**, that is, a **written or verbal description of what to build**.

In this tutorial we've got a rather simple spec from our project manager. A super important client needs a **JavaScript function that should filter an array of objects.**

For every object we must check a property called "url" and **if the value of the property matches a given term** then we should **include the matching object in the resulting array**. Being a test-savvy JavaScript developer you want to follow **test-driven development**, a discipline which imposes to **write a failing test before starting to code**.

By default Jest expects to find test files in a folder called **__tests__** in your project folder. Create the new folder then:

```bash
cd getting-started-with-jest
mkdir __tests__
``` 

Next up create a new file called **filterByTerm.spec.js** inside **__tests__**. You may wonder why the extension includes ".spec.". It is a convention borrowed from Ruby for marking the file as a **specification** for a given functionality.

And now let's get testing!

## Jest Tutorial: test structure and a first failing test

Time to create **your first Jest test**. Open up **filterByTerm.spec.js** and create a test block:

```js
describe("Filter function", () => {
  // test stuff
});
```

Our first friend is **describe**, a Jest method for containing one or more related tests. Every time you start writing a new suite of tests for a functionality wrap it in a **describe** block. As you can see it takes two arguments: a string for describing the test suite and a callback function for wrapping the actual test.

Next up we're going to meet another function called **test** which is the actual test block:

```js
describe("Filter function", () => {
  test("it should filter by a search term (link)", () => {
    // actual test
  });
});
```

At this point we're ready to write the test. Remember, testing is a matter of **inputs, functions, and expected outputs**. First let's define a simple input, an array of objects:

```js
describe("Filter function", () => {
  test("it should filter by a search term (link)", () => {
    const input = [
      { id: 1, url: "https://www.url1.dev" },
      { id: 2, url: "https://www.url2.dev" },
      { id: 3, url: "https://www.link3.dev" }
    ];
  });
});
```

Next up we're going to define the **expected result**. As per spec the **function under test should leave out the objects whose url property does not match the given search term.** We can expect for example an array with a single object, given "link" as the search term:

```js
describe("Filter function", () => {
  test("it should filter by a search term (link)", () => {
    const input = [
      { id: 1, url: "https://www.url1.dev" },
      { id: 2, url: "https://www.url2.dev" },
      { id: 3, url: "https://www.link3.dev" }
    ];

    const output = [{ id: 3, url: "https://www.link3.dev" }];
  });
});
```

And now we're ready to write the actual test. We'll use **expect** and a Jest **matcher** for checking that our fictitious (for now) function returns the expected result when called. Here's the test:

```js
expect(filterByTerm(input, "link")).toEqual(output);
```

To break things down even further here's how you would call the function in your code:

```js
filterByTerm(inputArr, "link");
```

In a Jest test you should wrap the function call inside **expect** which coupled with a **matcher** (a Jest function for checking the output) makes the actual tests. Here's the complete test:

```js
describe("Filter function", () => {
  test("it should filter by a search term (link)", () => {
    const input = [
      { id: 1, url: "https://www.url1.dev" },
      { id: 2, url: "https://www.url2.dev" },
      { id: 3, url: "https://www.link3.dev" }
    ];

    const output = [{ id: 3, url: "https://www.link3.dev" }];

    expect(filterByTerm(input, "link")).toEqual(output);

  });
});
```

(For learning more about Jest matchers check out the [documentation](https://jestjs.io/docs/en/getting-started)).

At this point you can give it a shot with:

```bash
npm test
``` 

You'll see the test fail spectacularly:
 
```bash
 FAIL  __tests__/filterByTerm.spec.js
  Filter function
    ✕ it should filter by a search term (2ms)

  ● Filter function › it should filter by a search term (link)

    ReferenceError: filterByTerm is not defined

       9 |     const output = [{ id: 3, url: "https://www.link3.dev" }];
      10 | 
    > 11 |     expect(filterByTerm(input, "link")).toEqual(output);
         |     ^
      12 |   });
      13 | });
      14 |
```
 
"ReferenceError: filterByTerm is not defined". That's a good thing actually. Let's fix it in the next section!

## Jest Tutorial: fixing the test (and breaking it again)

What's really missing is the implementation of **filterByTerm**. For convenience we're going to create the function in the same file where the test lives. In a **real project you would define the function in another file and import it from the test file**.

For making the test pass we'll use a native JavaScript function called **[filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)** which is able to filter out elements from an array. Here's a minimal implementation of **filterByTerm**:

```js
function filterByTerm(inputArr, searchTerm) {
  return inputArr.filter(function(arrayElement) {
    return arrayElement.url.match(searchTerm);
  });
}
```

Here's how it works: for each element of the input array we check the "url" property, matching it against a regular expression with the **[match](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match)** method. Here's the complete code:

```js
function filterByTerm(inputArr, searchTerm) {
  return inputArr.filter(function(arrayElement) {
    return arrayElement.url.match(searchTerm);
  });
}

describe("Filter function", () => {
  test("it should filter by a search term (link)", () => {
    const input = [
      { id: 1, url: "https://www.url1.dev" },
      { id: 2, url: "https://www.url2.dev" },
      { id: 3, url: "https://www.link3.dev" }
    ];

    const output = [{ id: 3, url: "https://www.link3.dev" }];

    expect(filterByTerm(input, "link")).toEqual(output);
  });
});
```

Now run the test again:

```bash
npm test
```

and see it passing!

```bash
 PASS  __tests__/filterByTerm.spec.js
  Filter function
    ✓ it should filter by a search term (link) (4ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.836s, estimated 1s
```

Great job. But have we finished testing? Not yet. What it takes to **make our function fail?**. Let's stress the function with an upper-case search term:

```js
function filterByTerm(inputArr, searchTerm) {
  return inputArr.filter(function(arrayElement) {
    return arrayElement.url.match(searchTerm);
  });
}

describe("Filter function", () => {
  test("it should filter by a search term (link)", () => {
    const input = [
      { id: 1, url: "https://www.url1.dev" },
      { id: 2, url: "https://www.url2.dev" },
      { id: 3, url: "https://www.link3.dev" }
    ];

    const output = [{ id: 3, url: "https://www.link3.dev" }];

    expect(filterByTerm(input, "link")).toEqual(output);

    expect(filterByTerm(input, "LINK")).toEqual(output); // New test

  });
});
```

Run the test ... and it will fail. Time to fix it again!

## Jest Tutorial: fixing the test for uppercase

**filterByTerm** should account also for uppercase search terms. In other words it should return the matching objects even if the search term is an uppercase string:

```js
filterByTerm(inputArr, "link");
filterByTerm(inputArr, "LINK");
```

For testing this condition we introduced a new test:

```js
expect(filterByTerm(input, "LINK")).toEqual(output); // New test
```

For making it pass we can tweak the regular expression provided to **match**:

```js
//
    return arrayElement.url.match(searchTerm);
//
```

Rather than passing searchTerm straight away we can construct a **case insensitive regular expression**, that is, an expression that matches regardless of the string's case. Here's the fix:

```js
function filterByTerm(inputArr, searchTerm) {
  const regex = new RegExp(searchTerm, "i");
  return inputArr.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}
```

And here's the complete test:

```js
describe("Filter function", () => {
  test("it should filter by a search term (link)", () => {
    const input = [
      { id: 1, url: "https://www.url1.dev" },
      { id: 2, url: "https://www.url2.dev" },
      { id: 3, url: "https://www.link3.dev" }
    ];

    const output = [{ id: 3, url: "https://www.link3.dev" }];

    expect(filterByTerm(input, "link")).toEqual(output);

    expect(filterByTerm(input, "LINK")).toEqual(output);
  });
});

function filterByTerm(inputArr, searchTerm) {
  const regex = new RegExp(searchTerm, "i");
  return inputArr.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}
```

Run it again and see it passing. Good job! As an **exercise for you write two new tests** and check the following conditions:

1. test for the search term "uRl"
2. test for an **empty search term**. How the function should deal with it?

How would you structure these new tests?

In the next section we'll see another important topic in testing: **code coverage**.

## Jest Tutorial: code coverage

What is **code coverage**? Before talking about it let's make a quick adjustment to our code. Create a new folder inside your project root called **src** and create a file named **filterByTerm.js** where we'll place and **export** our function:

```bash
mkdir src && cd _$
touch filterByTerm.js
```

Here's the file **filterByTerm.js**:

```js
function filterByTerm(inputArr, searchTerm) {
  if (!searchTerm) throw Error("searchTerm cannot be empty");
  const regex = new RegExp(searchTerm, "i");
  return inputArr.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

module.exports = filterByTerm;
```

Now let's pretend I'm a fresh hired colleague of yours. I know nothing about testing and instead of asking for more context I go straight inside that function for adding a new **if statement**:

```js
function filterByTerm(inputArr, searchTerm) {
  if (!searchTerm) throw Error("searchTerm cannot be empty");
  if (!inputArr.length) throw Error("inputArr cannot be empty"); // new line
  const regex = new RegExp(searchTerm, "i");
  return inputArr.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

module.exports = filterByTerm;
```

There is a new line of code inside filterByTerm and seems it's not going to be tested. Unless I tell you "there's a new statement to test" you're not going to **know exactly what to test** in our function. It's almost impossible to imagine all the paths our code can take and so **arises the need for a tool that helps uncovering these blind spots**.

That tool is called **code coverage** and it's a powerful utensil in our toolbox. **Jest has built-in code coverage** and you can activate it in two ways:

1. via the command line by passing the flag "--coverage"
2. by configuring Jest in package.json

Before running the test with coverage make sure to **import filterByTerm** in **__tests__/filterByTerm.spec.js**:

```js
const filterByTerm = require("../src/filterByTerm");
// ...
```

Save the file and run the test with coverage:

```bash
npm test -- --coverage
```

Here's what you get:

```bash
 PASS  __tests__/filterByTerm.spec.js
  Filter function
    ✓ it should filter by a search term (link) (3ms)
    ✓ it should filter by a search term (uRl) (1ms)
    ✓ it should throw when searchTerm is empty string (2ms)

-----------------|----------|----------|----------|----------|-------------------|
File             |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------------|----------|----------|----------|----------|-------------------|
All files        |     87.5 |       75 |      100 |      100 |                   |
 filterByTerm.js |     87.5 |       75 |      100 |      100 |                 3 |
-----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
```

A nice summary of the testing coverage for our function. As you can see **line 3 is uncovered**. Try to reach 100% code coverage by testing the new statement I've added.

If you want to keep code coverage always active configure Jest in **package.json** like so:

```json
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "collectCoverage": true
  },
```

You can also pass the flag to the test script:

```json
  "scripts": {
    "test": "jest --coverage"
  },
```

If you're a visual person there's also a way to have an **HTML report for code coverage**, it's simply as configuring Jest like so:

```json
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "collectCoverage": true,
    "coverageReporters": ["html"]
  },
```

Now every time you run npm test you can access a new folder called **coverage** in your project folder: **getting-started-with-jest/coverage/**. Inside that folder you'll find a bunch of files where **/coverage/index.html** is a complete HTML summary of the coverage for your code:

![Jest HTML code coverage report summary](https://thepracticaldev.s3.amazonaws.com/i/g7qyq5x65m6ndzczn57n.png)

If you click on the function name you'll also see the exact untested line of code:

![Jest HTML code coverage report single file](https://thepracticaldev.s3.amazonaws.com/i/oqmfwqfuk33h20fcctr7.png)

Neat isn't? **With code coverage you can discover what to test** when in doubt.

## Jest Tutorial: how to test React?

**React** is a super popular JavaScript library for creating dynamic user interfaces. Jest works smoothly for testing React apps (both Jest and React are from Facebook's engineers). Jest is also the default test runner in Create React App.

If you want to learn how to test React components check out **[Testing React Components: The Mostly Definitive Guide](https://www.valentinog.com/blog/testing-react/)**. The guide covers **unit testing components**, class components, **functional components with hooks**, and the new Act API.

## Conclusions (where to go from here)

**Testing is a big and fascinating topic**. There are many types of tests and many libraries for testing. In this Jest tutorial **you learned** how to configure Jest for coverage reporting, how to organize and write a simple **unit test**, and how to test JavaScript code.

To learn more about **UI testing** I highly suggest taking a look at [JavaScript End to End Testing with Cypress](https://www.valentinog.com/blog/cypress/). 

Even if it's not JavaScript related I also suggest reading [Test-Driven Development with Python](https://www.obeythetestinggoat.com/) by Harry Percival. It's full of tips and tricks for all the things testing, and covers in depth all the different kind of tests.

If you're ready to take the leap and learn about **automated testing and continuous integration** then [Automated Testing and Continuous Integration in JavaScript](https://www.valentinog.com/blog/ci-js/) is for you.

You can find the code for this tutorial on Github: [getting-started-with-jest](https://github.com/valentinogagliardi/getting-started-with-jest) alongside with the solution for the exercises.

Thanks for reading and stay tuned!