How should I unit test my code-Part 1 (Setup)

Anuradha Kumari
May 18 · 9 min read

To keep the articles shorter, the HOW topic for unit testing has been split into two parts. In this article, which is the first part, we will setup Jest and Enzyme to get started with. In the second(yet to publish) part, we will see examples for testing the React, Redux code.

Configuring Jest and Enzyme for React application

Getting started

Hi everyone, today we are going to create a new React project using create-react-app and setup Jest and Enzyme to test our code. We will also configure our application to generate code coverage.

If you are new to unit testing, you might also want to take a look at the article Why should I unit test my code?

For a quick start, I have created a repo at GitHub which contains all the setup and examples which we will be going through in this tutorial and next following tutorial(yet to be published). Feel free to clone the repo or to refer to it any point you get stuck while following through the below steps.

To clone the repo, use:

So, let’s get started 😎

Step 1 — Create a React project

We will be creating a new project using the tool provided by the React team.

npx above is a package runner tool that comes with npm 5.2+

If we use npm 5.1 or earlier, we can't use npx. Instead, we can install create-react-app globally:

Then we can run create-react-app to create our new project:

Now, we should have the basic setup done for us out of the box, and we can see App.js and App.test.js files in `app/src` folder.

Jest

We are going to use Jest as our testing framework which is already installed for us through the `create-react-app`.

However, if you have preferred to do the whole setup from scratch, you can go ahead and add Jest through npm like below

Check out Getting Started documentation of Jest for more details

Alternatively, you can add Jest as devDependency in your package.json file and run npm install command to pull the package into your node_modules folder.

Step 2 — Add Enzyme

Now, before we start adding unit tests, let’s add Enzyme to our application too. It is a JavaScript test utility for React provided by airbnb, which will allow us to assert, manipulate and traverse react components.

Let’s start by installing Enzyme and enzyme-adapter-react-16, which is required to connect Enzyme to a project using react v16 and above.

We can add it by executing below command:

Note: enzyme-adapter-react-16 has peer dependencies on react, react-dom, and react-test-renderer. You can check more details here.

At this point in time, our package.json file should look more or less like below:

"dependencies": {
  "react": "^16.8.6",
  "react-dom": "^16.8.6",
  "react-redux": "^7.0.2",
  "react-scripts": "2.1.8",
  "redux": "^4.0.1",
  "redux-mock-store": "^1.5.3",
  "redux-thunk": "^2.3.0"
 },"devDependencies": {
  "enzyme": "^3.9.0",
  "enzyme-adapter-react-16": "^1.12.1",
  "enzyme-to-json": "^3.3.5",
  "react-test-renderer": "^16.8.6"
 },"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "test": "react-scripts test",
  "eject": "react-scripts eject"
 }
}

Step 3 — Running tests

Now, we are almost there. I will tell you in a while why we are not yet done completely with the setup.

So, let’s open the terminal, and if we are not already into the app folder, navigate to it, and then simply run below command to run tests:

The above command runs the test watcher in an interactive mode as you can see in the following snapshot

Running the test in terminal

Till now, we have not written any code and hence we only have one unit test file(App.test.js), which was created by the create-react-app tool. When we ran npm test command, we should see this test passing. You can press a form keyboard to re-run all the tests (at this point, we only have one as mentioned above.)

Testing a new component

Let’s add one more file to our application. I have created a file namedloading-spinner.jsx which returns a functional Component, as below:

const LoadingSpinner = () => {
  return (
     <div>
        {'...loading'}
     </div>
  );
}export default LoadingSpinner;

To test this component, we need to create a test file, which generally has same name as the component with .test.js or .spec.js as its extension. So, for our Loading Spinner component, we can create either loading-spinner.test.js or loading-spinner.spec.js file and Jest identifies the file as test file.

I personally prefer using test.js extension, but you can choose as per your preference or project requirements.

So, let’s go ahead and create that test file in the same folder where our component lies. Now, let’s add one basic test case which will check if the component is rendered correctly. We will use Enzyme’s shallow rendering for our purpose.

import LoadingSpinner from './loading-spinner';describe("LoadingSpinner component", () => {
  it("should render correctly", () => {
    const wrapper = shallow(<LoadingSpinner />);
    expect(shallowToJson(wrapper)).toMatchSnapshot();
  });
});

Some keywords to discuss in the above test:

  • shallow — it is the rendering util provided by Enzyme which only renders the component passed to it as node, without rendering any of its children, and hence, hence helps in unit testing the targeted component.
  • shallowToJson — it converts Enzyme wrappers to a format compatible with Jest snapshot testing.
  • Jest snapshot testing — it renders the component, takes a snapshot, then compares it to a reference snapshot file stored alongside the test. The test will fail if the two snapshots do not match.

Please click on the links for each of the above items to check more details about them.

Now, let’s run the tests now to check the results, and you will notice that there is an error in the test execution. Oh no!! 🤦‍♀️

Error while executing test without configuring Enzyme adapter

Let’s try to inspect the error, and we see also a link to the error details here.

Step 4— Configure Enzyme Adapter

We have already installed the enzyme adapter during our setup, but we have not used it yet. I deliberately skipped this setup to show you the reason before we go ahead and use it.

So, now let’s go ahead and configure the adapter to be able to use the Enzyme’s utilities in our tests. While we can set up this configuration locally in our test file, but that will not be the ideal way, since we will be using shallow and other Enzyme utilities very frequently in our test cases.

So, let’s go ahead and create that setupTests.js file in our root folder, which is/src folder for our current application.

import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

Note: When using TypeScript with Babel, all your files need to have at least one export, otherwise you will get the error Cannot compile namespaces when the ‘ — isolatedModules’ flag is provided. To fix this, you can add export default undefined to src/setupTests.ts.

Now, we are done with all the test setup 😃

Step 5— Generate Code coverage

Now that our setup for unit testing is complete, let’s talk about code coverage.

So what is it, you shall ask.

As Wikipedia states — it is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs.

So let’s go ahead and set up our application to measure the code coverage.

We can configure the settings in our package.json file, or alternatively in jest.config.js file which will then be referenced by in our package.json. For this tutorial, let’s keep things simple, and we will add the configuration to package.json file. For that, we need to add configuration for jest as below:

  "coverageThreshold": {
     "global": {
     "branches": 80,
     "functions": 80,
     "lines": 80,
     "statements": 80
    }
  },
  "coverageReporters": ["lcov"]
}

Let’s take some time to talk about the configurations:

  • collectCoverageFrom —Our application contains many files and folders, some of which are external dependencies and libraries which we do not want to include in our coverage report. So, in this option, we define which all files need to be included/excluded in the coverage report. For our React application, we want to include the .js/.jsx files inside our root folder. We will also need to include .ts/.tsx file if we are using TypeScript for our project. Also, you can see some files and folder paths starting with !<rootDir>/ These are the ones which we want to exclude from our coverage report.
  • coverageThreshold — This contains the coverage criteria, to measure what percentage of code has been covered by unit tests. The numbers defined here are the minimum criteria for the tests to pass. Here, we have configured it to be 80% for each of the categories, which you can reconfigure it based on your requirements.
  • coverageReporters — there are different types of coverage reporters like ‘text’, ‘json’, ‘lcov’, etc. We will use ‘lcov’ reporter because it creates html file with coverage report which is much easier to use and quite readable. Also, I have not much explored other types of reporters, so you can configure it to be the reporter of your choice.

With this, we have configured our application to generate code coverage too.

To generate coverage, run below command:

After the successful test run, we can see the Coverage summary in terminal:

Coverage summary

You can see here that it compares the coverage percentage for each of the categories (statements, branches, etc.) against the percentage set in our package.json file. And also, it gives an error if we did not meet that limit.

The execution of this command also creates a folder named coverage at the same level of our application where /src lies.

Folder structure

Now, if we want to increase coverage, we need to know which of the files have low coverage. For that, you can open the index.html file present from the path /coverage/lcov-report/index.html in the web browser, and then you can see the detailed coverage report for each file. It should look something like below:

Code coverage report as seen in browser

Here, we can easily see coverage for each file/folder which is included in our test coverage configuration.

Now, in the above screenshot, we can see that src/components/user has the least coverage for functions and then we can navigate to that file by clicking on the File name in the left-most column of the table.

Coverage report of user.jsx file

There we can see that a function named testFunction is highlighted in red. It simply means that it has not been covered by any unit test case yet. So, we know now exactly what code block we missed to test, and we can go and add test cases for it right away.

Remember, code coverage percentage is no measure for the test quality and it does not imply, in any way, that a better coverage would mean better code. So, it is suggested to use it wisely and not to rely upon this number for quality assurance.


Note: This article covers the configuration for unit testing and coverage before we move ahead to unit test the React and Redux code. PFB the series topics:

  1. Why should I unit test my code?
  2. How should I unit test my code? 2.1. Setup (this article) 2.2. Examples
  3. What should I unit test in my code?

Stay tuned and catch you in the next article !! Any feedback is highly appreciable.

If you run through any issues while setting up with Jest and Enzyme, please drop me comment and I will be happy to help. 😊

Thanks for reading, have a great day!!

Anuradha Kumari

Written by

Tech enthusiast, UI developer @Globant. My motto - 'Choose RIGHT over easy, always!'