Author - Aryan Raj
Software companies are striving to provide a seamless digital experience to their users, for which they are happily investing on research, development, and most importantly on testing.
As per Stackshare report, almost 11000+ companies around the globe are using React in their technology stack. Companies like Instagram, Wix, Uber Eats, Pinterest, and Dropbox are some big names that use React.
To make testing React components easier there are several testing libraries out there, which are used by most of the companies using React. In the past few years I have seen a lot of my fellow developers struggle to choose a testing library for their different projects. This blog is an attempt to make this selection easier.
In this blog, I will introduce you to some popular React testing libraries and compare them to help you see how these testing libraries stack against each other.
Developed by Google, Puppeteer is a Node.js library that allows the users to have the access to Chrome through the DevTools Protocol. Puppeteer has a default nature on running headless Chrome, but by doing small configurations, it can be made to execute in non-headless Chrome.
I’ll simplify the term “headless” for you. Headless Chrome simply means to run Chrome without actually opening the Chrome. This headless feature comes in very handy to execute automated testing and server environments.
Because of this default nature of Puppeteer, the user can do almost anything you can normally do in browsers with Puppeteer. Actions like creating pre-rendered content from SPAs, form submissions, keyboard inputs, etc can be done via Puppeteer.
When it comes to executing the scripts in headless chrome and accessing the window objects, Puppeteer is one of the first libraries that comes into the mind of a web developer. It allows you to test apps that demand access to web resources like cookies or localStorage.
Users can fully automate the testing of web applications with the help of Puppeteer. Simply automate the testing of web applications and witness the results in real-time terminals. Also many times, the combination of Puppeteer and Jest is used for the purpose of end-to-end testing of React applications.
One of the main advantages it offers is that it has the access over the DevTools Protocol, and these DevTools comes with numerous of benefits such as analysing the performance, gives access to the browser internals, cross-browser compatibility, and integration with other tools, it can even alter them whenever in need.
We will also look at a comparison between Puppeteer and Cypress to look more into these libraries and understand what extra features are present in them and which ones are absent.
Besides performing end-to-end testing, Cypress also supports other types of testing such as Unit testing, API testing, and Integration testing. Since the Cypress works in the actual browser, developers are open to using the in-built dev tools of browsers alongside.
With Cypress, the user can make the test changes automatically reload, debug the code easily, capture the time-travel snapshots, and wait for the assertions.
Cypress supports a parallelization feature which makes it possible to execute multiple tests simultaneously ultimately reducing the text execution time. Along with this, Cypress IO also comes with a load balancing property which helps to evenly distribute the workload in resources while performing multiple tests. This results in the optimized utilization of resources.
When it comes to the other frameworks, writing test cases in Cypress is much easier and quick because it runs the tests directly on the browser. Not just this, Cypress can be integrated with any Cypress IO tool to perform the test in the headless environment.
Later on this blog, we will also look at a comparison between Cypress and Puppeteer to dig deeper in the characteristics of Cypress.
React-testing-library (RTL) is a type of testing library or testing tool that helps to perform testing on theReact web apps and check their working. Behind the scenes, RTL basically tests the DOM tree rendered by the browser as the webpage loads. React-testing-library comes in very handy when there is a need to replicate the user behaviour in the test cases.
RTL covers almost every React DOM testing utility having the main intention to replicate the actions taken by users and workflows. Even the refactoring or restructuring of whole code becomes a lot much easier with the use of RTL.
RTL is one of those libraries that focuses on executing the testing purpose from end-user’s experience instead of testing on implementation. One of the biggest perks RTL comes with, is that it offers to perform testing over web apps as a real-life user would interact with it.
I would say RTL has some competition in the market. Enzyme is also a popular library that can be used instead of RTL. We will also study a brief comparison between RTL and Enzyme later in this blog. But first let’s understand how Enzyme works.
Enzyme is basically a testing utility library that makes the whole process of performing tests on React component’s output a lot much easier. Created by the tech team of Airbnb, Enzyme offers us to add some extra functionalities for the rendering of elements, performing interaction with the elements, and finding the elements.
Using Enzyme as a helping hand, perform some basic operations on given output such as traversal, manipulate, and in some sense we can even mimic the runtime of the whole code.
Enzyme comes with an extraordinary capability where Enzyme can run the tests in normal or headless browsers with the help of the node-bases testing tool named Karma. Alternatively, Enzyme can also run the tests in Node by making the jsdom behave as an implementation of APIs.
Enzyme basically captures the snapshots of the UI components to carry out the testing. But instead of capturing and comparing the snapshots (which leads to unnecessary noisy code), Enzyme simply renders the component in memory. After that, it offers a series of APIs to test the properties of components. This makes Enzyme one of the most recommended testing library for React.
We will also analyze a brief differentiation between Enzyme and React-testing-library to see what parallels do they have.
Jasmine has a remarkable version especially designed for Ruby named as “jasmine-gem”. To install it, the user needs to gem ‘jasmine’ to the Gemfile and run the bundle install. It comes with a server for executing the test cases, generators, and a CLI script.
Later on in this blog, we will look at a brief comparison between Jasmine and Jest to better understand the characteristics of Jasmine.
Jest comes with a whole bundle consisting of an assertion library, a built-in mocking library, and a test runner. Not just this, Jest is itself a complete testing library. It can perform operations like spy, mock, and make assertions by itself. The user does not need to install and embed any additional libraries.
To more deeply grasp the traits of Jest, we will compare Jest with the Jasmine and TestCafe libraries, later in the blog.
TestCafe is fully compatible with MacOS, Windows, and Linux. TestCafe comes along with several benefits, therefore, it is highly popular when it comes to executing tests. Even the setup process of TestCafe is extremely easy, just needs to run a few commands and you are good to go.
Unlike other testing libraries, TestCafe does not require any third-party library such as external jars, webdriver, Chai, etc, making it a fully independent library. Furthermore, TestCafe supports command chaining techniques which eventually help developers to increase their productivity. The number of lines of code gets decreased from 40-50% when using TestCafe.
Moving ahead, we will also look at a brief comparison of TestCafe with Jest and Cypress.
Till now we have discussed the most admired React testing libraries in the developer community. We understood the features of each testing library, and how they can be handled for the testing. Now, let’s compare these libraries one by one.
Since Enzyme is three years older than React-testing-library, therefore the applications and solutions of Enzyme library are available at almost every popular website like Stack OverFlow. In comparison to Enzyme, React-testing-library gives a more accurate and similar real life user interaction. For example, react-testing-library comes with a fireEvent, which gives us the same result as when the user interacts or clicks on a button.
Enzyme works a little bit differently. The code demands the use of states and props that are one of the key concepts of React. Therefore, the creation of test cases is done slightly less or high from a real life developer’s perspective.
The table below compares Enzyme and react-testing-library side by side.
In the majority of the scenarios, use of React-testing-library is suggested. React-testing-library comes with an exported API, this API restricts the user to use the component’s internal API. This encourages the user to write better and cleaner tests. That means, there is no need to perform any sort of configuration to run the test cases.
On the other hand, Enzyme allows the user to use the internal API that covers lifecycle models and states. This makes the user perform some configuration eventually degrading the quality of the testing process.
If we summarise, both Enzyme and RTL are effective testing libraries. But RTL’s user centric approach and ease of use has turned it into a favourite of many developers. Interestingly some developers even chose to migrate from Enzyme to React testing library.
Cypress and TestCafe both were launched around the same time in 2015. However, we have seen both these libraries evolving dramatically in the last few years. For example, Cypress now supports Component testing for React and now TestCafe comes with a native-automtion flag which allows it to streamline every Chromium-based browser.
When it comes to working, the Cypress library works on the actual test code residing in the browser that allows the Cypress test cases to use the real DOM elements. On the other hand the TestCafe library works on Node.js environment as well which restricts the test cases to have a serialised communication with the DOM.
Both the Cypress and TestCafe are excellent at executing test cases. But just like other testing libraries, they both have some pros and cons too. Let’s now look at their tabular comparison
Cypress does not come with built-in support for mobile applications. To make it work, Cypress demands the use of some other third party libraries to make it work. It requires the help of an assertion library such as Chai, Jest, Should.js, etc along with the Mocha to run the tests and Sinon for mocking. Cypress also voluntarily adds some spice of promise queueing which makes the asynchronous code to synchronous one.
No third party library is required for the use of TestCafe. It has everything built in it. Testcafe comes with its own test runner. The use of TestCafe is highly suggested because it allows the user to explicitly call the async/await and promises to handle the execution.
Both these testing libraries work very well in their own space. So, to select among them, it would be ideal to go back to your project requirements, and see which one fits your needs.
When it comes to the popularity factor, you will find the majority of the developer community recommend Jest for the testing of ReactJS and Nextjs applications whereas the Jasmine is recommended for the Angular based applications. Although it is not necessary that you should go with the most popular library, understand your project’s requirements, and then select the testing library.
Just like the above discussed comparisons, in this case also, both the Jest and Jasmine libraries come with their own advantages and disadvantages.
Let’s take a look at a tabular comparison between Jest and Jasmine.
Jest simplifies the creation of mock functions and objects for testing as it is capable enough to perform auto-mocking. This ability of Jest even streamlines the whole testing protocol and makes it very much handy to perform testing over complex applications.
Jasmine is not behind in the race of having built-in features/capabilities just like Jest. Jasmine has got some inherited assertions which ease the process of coding and significantly making the code much more readable and understandable. Adding to this, Jasmine is highly adaptive and versatile in nature which makes it compatible with the majority of the libraries and frameworks.
Some additional features that Jest comes with includes Snapshot testing support, mocking functions, Zero configuration required, and code coverage support. Similarly, Jasmine too comes with the support of mocking functions but the negative part is that the use of these mocking functions is somewhere limited. Resulting in the high recommendation of use of Jest over Jasmine.
Performing end-to-end tests on the application before publishing it is an extremely crucial part. This is where the Cypress and Puppeteer come in.
As we have discussed above, Cypress is an open source testing framework that helps to perform end-to-end testing over web applications. Cypress comes with an API to ease the work of writing tests. This API can also interact with the user interface of the web application. In addition, it also works as a dashboard to witness the results on the performed tests.
If we talk about Puppeteer, it is a Node.js library that comes with an advanced API which helps to control the headless Chrome browser. With the help of Puppeteer, developers can systemize the tasks that would generally require some manual control with the browser.
We have discussed both these libraries in detail earlier, so now let's quickly dive into their comparison.
Considering the API structure of these libraries, Cypress API can do a lot, like execute an action, query a DOM element, perform debugging, computerised tasks, and much more, all with only a few lines of code. On the other hand, Puppeteer comes with an advanced API to control Chrome and Chromium with the help of DevTools Protocol. This advanced API also has access to the browser console, it can also emulate devices, intercept network requests, and much more.
For maximum code coverage, there arises a need to mix the end-to-end test and unit tests, and for this Cypress does offer the facility of flexible code coverage. Not just Cypress, but Puppeteer also comes with the feature of code coverage support.
Puppeteer does not support server-side rendering. So if your selection criteria includes server-side rendering, Puppeteer is simply out of the game.
If we talk about Cypress, it comes with the capability to perform server-side rendering. Although Cypress does not come under the category of general automation frameworks, it is capable enough to perform testing over back-end behaviours.
Adding to this, there’s one more feature that Puppeteer lacks and Cypress has - it is fixtures. With the help of fixtures, developers can specify the states of data that can be tested locally.
Both the Cypress and Puppeteer libraries perform extremely well in their spaces. So we cannot upvote one library over another. It all comes to the essentials of your project.
Despite having a couple of similarities between these, there are some major differences in them. So let’s throw some lights on their differences and discuss them.
Since both the libraries sole purpose is to perform testing over web apps. But still they have some differences, so let’s explore them. The first difference that comes into existence is the support of server-side testing. TestCafe is incapable of performing server-side testing. On the contrary, Jest does have the feature of server-side testing. With the help of Jest, we can test the behaviour of back-end servers.
Adding more to the list of differences, the next thing comes is the group fixtures. Just like we had in the case of server-side testing, TestCafe lags behind here too. Jest comes with the support of group fixtures whereas it is absent in TestCafe.
Another difference that comes in the list is the presence of Mocks. For those who don’t know, Mocks are objects that replicate the behaviour of real objects. These duplicate objects help to perform isolation testing of some elements of the code. In TestCafe, users can use the “RequestMock” hook. In the case of Jest, it takes help of a custom resolver in the tests. The user can take advantage of mocked imports that are filled with mocked API to keep a check on function calls having readable test syntax.
In this blog, we looked at some of the popular React testing libraries and compared some of them head to head. We wanted to help you choose the right React testing library for your upcoming project, and I hope we could.