I tested a React app with Jest, Enzyme, Testing Library and Cypress. Here are the differences.

Finally, a side-by-side code comparison between the most popular testing tools for React. Watch as we attempt to write the exact same tests with Jest, Enzyme, Testing Library, and Cypress.

Sunil Sandhu
Oct 24, 2019 · 24 min read
Image for post
Image for post
Jest vs Testing Library vs Cypress: The results of the tests are in!

You’ve probably know — or at least have heard — that knowing how to test your code is important.

A lot of jobs in tech will require knowledge of testing with at least one testing tool/framework/library.

What’s Jest?

According to their website, “Jest is a JavaScript testing framework designed to ensure correctness of any JavaScript codebase. It allows you to write tests with an approachable, familiar and feature-rich API that gives you results quickly. Jest is well-documented, requires little configuration and can be extended to match your requirements.”

What’s Testing Library?

According to their website, “the Testing Library family of libraries is a very light-weight solution for testing without all the implementation details. The main utilities it provides involve querying for nodes similarly to how users would find them. In this way, testing-library helps ensure your tests give you confidence in your UI code.” Their philosophy is that “the more your tests resemble the way your software is used, the more confidence they can give you”.

What’s Cypress?

According to their website, Cypress is an end-to-end (e2e) “test runner built for humans”, with tests that “are easy to read and understand” and can be run in your browser and “run as fast as your browser can render”. Finally, Cypress provides “readable error messages [that] help you to debug quickly”. As you may have noticed, there wasn’t a nice chunk of text that I could pick up from the website, but rather I had to pick out sentences from their Features page.

What’s the difference between them?

A key difference I should mention here is that Jest and Testing Library are typically what you might refer to as Unit Testing and Integration Testing libraries, whereas Cypress is typically used for End-To-End (e2e) testing. This means that you would test your application from start to finish, as if you were a user using your application (with all the clicks and page navigations included and so on).

Before we look at the tests, let’s take a quick review of our React To Do app and make a list of all of the functionality that we will be testing.

We have three files: App.js, ToDo.js, and ToDoItem.js.

What will we be testing?

We will be looking to test that our app is able to do the following:

  1. Render two default ToDo items
  2. Render an input field for typing up new ToDo items
  3. Render an ‘Add’ button for adding ToDo items
  4. If the ‘Add’ button is pressed but the input field is empty, prevent a new ToDo item from being created
  5. If the ‘Add’ button is pressed but the input field is empty, show an alert to the user
  6. If the ‘Add’ button is pressed and the input field has content, add a new ToDo item
  7. When the ‘Delete’ button is pressed for a single ToDo item, remove that ToDo item from the App
  8. From the two default items in ToDo, if the first ToDo item has been removed from the app, the second item should now become the first (and only) item.
  9. For the data being passed down from ToDo to ToDoItem as props, each ToDoItem should render the text that was passed down to it.
  10. Each ToDoItem should render a ‘Delete’ button.
Image for post
Image for post

Jest

Let’s take another look at our file structure:

Image for post
Image for post
Image for post
Image for post
App.test.js, tested with Jest

setupTests.js

This file basically signals to our testing environment to include this code in any test file. This set isn’t necessary, as we could just add this to every test file. However, in the spirit of keeping our code DRY, we’ve opted to create this file. One thing to note is that we don’t have to tell our app to pick this up as create-react-app already has an internal set up to look out for this file in the src directory. So in our case, we just create the file and add the following lines of code:

Image for post
Image for post

Testing Library

Let’s take another look at our file structure, then we’ll get into each file and review what is going on:

Image for post
Image for post
Image for post
Image for post
App.test.js, tested with Testing Library

setuptests.js

As with our Jest setup, we have opted to keep our code as DRY as possible by creating this file.

Image for post
Image for post
<input
data-testid=”todo-input”
type=”text”
value={toDo}
onChange={handleInput}
onKeyPress={handleKeyPress}
/>

Cypress

Let’s take another look at our file structure, then we’ll get into each file and review what is going on:

Image for post
Image for post
Image for post
Image for post
cypress/integration/App.test.js
Image for post
Image for post
App.test.js, tested with Cypress

All our tests use describe() blocks and it() functions

A similarity you will notice from the tests across all of our examples is that they all follow the same pattern of having a describe() block with some it() statements inside for each test. There are other ways to structure these, such as using test() instead of it(), but we’ve opted for this approach as it is typically the most common and means that we can better structure our tests to look as similar to one another as possible.

Anyway, we’ve covered a lot of stuff here so far and we haven’t really reviewed the tests side-by-side.

So let’s step through each of the criteria we wanted to test and see how each testing tools handles it.

1. Render without crashing.

This is typically known as a “smoke test” where we just make sure that our app doesn’t throw an error and actually loads up as expected. In this case, you might see people check to see whether our component returns a length of 1. I really don’t like those tests as they aren’t expressive enough. Therefore, I’ve opted to check whether the title tag from the header of our To Do app has rendered.

Jest

Testing Library

Cypress

2–4. Render two default ToDo items; Render an input field for typing up new ToDo items; Render an ‘Add’ button for adding ToDo items.

Jest

Jest
Testing Library

Cypress

Cypress

5–7. If the ‘Add’ button is pressed but the input field is empty, prevent a new ToDo item from being created; If the ‘Add’ button is pressed but the input field is empty, show an alert to the user; If the ‘Add’ button is pressed and the input field has content, add a new ToDo item.

Jest

Image for post
Image for post
Image for post
Image for post
Image for post
Image for post

Testing Library

Image for post
Image for post
Image for post
Image for post

Cypress

8–9. When the ‘Delete’ button is pressed for a single ToDo item, remove that ToDo item from the App; From the two default items in ToDo, if the first ToDo item has been removed from the app, the second item should now become the first (and only) item.

Jest

Testing Library

Image for post
Image for post

Cypress

10–11. For the data being passed down from ToDo to ToDoItem as props, each ToDoItem should render the text that was passed down to it; Each ToDoItem should render a ‘Delete’ button.

Jest

Image for post
Image for post
Remember that our item variable is an object with a key of text and a value of “Clean the pot”.

Testing Library

Cypress

We don’t have tests for this. The reason being that we run these tests in a real browser, and therefore, cannot simulate passing dummy data in this way. This is not really a problem though as being able to visually see our two previous To Do Items in the browser sufficiently demonstrates that our data is being passed in properly and in the correct format.

And there we have it 🎉

We have shown you how to write over ten equivalent tests written with three different testing tools!

Interested in checking out the code?

Here are the repos:

A note from JavaScript In Plain English

We are always interested in helping to promote quality content. If you have an article that you would like to submit to JavaScript In Plain English, send us an email at submissions@javascriptinplainenglish.com with your Medium username and we will get you added as a writer.

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store