Testing code is always a difficult problem for every developer, because it simply takes time, effort, even you must be able to see the probable cases. Often small projects will skip this stage because of lack of resources. However, it is always necessary because it will help you feel more confident with your code, increasing labor productivity.
There is a difference in React, and in this article I will show you how to write tests for React components.
Test component in React
Test is the process of checking to see if the conditions that we set are returned correctly through the operation of the application. There are many types of testers available to developers, but here I refer to the common test models that are commonly used: unit tests, functional tests and integration tests.
Unit test
Unit testing is a very basic test for every test procedure. As the name implies, you will have to test each piece of code separately for the functions they are in charge of. Because of the component structure in React, unit tests are extremely useful. Unit tests help you break down components into separate functions. Your unit test in the component must answer the following questions:
- Is there any prop? If yes, what for?
- Which component does it render?
- Should it have a state? When and how to update the state?
- Is there any process that it must monitor when mounted and unmount or user interact?
Functional test
Functional test is used to test the reciprocal part of a system. Function tests are often written by the user’s perspective. Part of the function is not limited to just one component.
Integration test
Integration test is the process of combining separate components into a group. It is intended to check user operation, although it is longer than functional and unit tests, it is performed directly. In React, unit tests and functional tests are more popular because they are easy to write and maintain.
Which tool to use
Jest Test
Jest is a test framework that requires no customization and is easy to install. It is more famous than frameworks like Jasmine and Mocha because it is developed by Facebook. Jest is even faster than them because it uses the technique of running parallel tests in each worker. In addition, each test run is put into a separate sandbox environment to avoid conflicts with other test cases.
If you use create-react-app, it already has Jest. If not, you will need to install Jesst and a few other dependencies. Please refer to the Jest documentation here .
react-test-renderer
Even if you use create-react-app, you still have to install this part because it will render the snapshot. The snapshot test is part of the Jest. Instead of having to render the UI of the entire application, we can use test render to create a simulated output.
1 2 | yarn add react <span class="token operator">-</span> test <span class="token operator">-</span> renderer |
ReactTestUtils and Enzyme
react-dom / test-utils contains custom test parts that belong to React. Also you can use Airbnb’s Enzyme . Enzymes are better than ReactTestUtils because they are easy to use, and go back to the React Component output. We will start with React util and then switch to Enzyme.
To install Enzyme:
1 2 | yarn add enzyme enzyme <span class="token operator">-</span> adapter <span class="token operator">-</span> react <span class="token operator">-</span> <span class="token number">16</span> |
Add the following code to src / SetupTest.js
1 2 3 4 5 | <span class="token keyword">import</span> <span class="token punctuation">{</span> configure <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'enzyme'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> Adapter <span class="token keyword">from</span> <span class="token string">'enzyme-adapter-react-16'</span> <span class="token punctuation">;</span> <span class="token function">configure</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> adapter <span class="token punctuation">:</span> <span class="token keyword">new</span> <span class="token class-name">Adapter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Install Demo App and arrange Test
We will write a demo application that displays the product list. The application contains components such as ProudctContainer.js
and the 3 present components are ProductList
, ProductDetails
, and ProductHeader
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token punctuation">.</span> ├── <span class="token keyword">package</span> <span class="token operator">-</span> lock <span class="token punctuation">.</span> json ├── <span class="token keyword">package</span> <span class="token punctuation">.</span> json ├── <span class="token keyword">public</span> │ ├── index <span class="token punctuation">.</span> html │ └── manifest <span class="token punctuation">.</span> json ├── src │ ├── components │ │ ├── App <span class="token punctuation">.</span> js │ │ ├── ProductContainer <span class="token punctuation">.</span> js │ │ ├── ProductDetails <span class="token punctuation">.</span> jsx │ │ ├── ProductHeader <span class="token punctuation">.</span> js │ │ ├── ProductList <span class="token punctuation">.</span> jsx │ ├── index <span class="token punctuation">.</span> js │ └── style <span class="token punctuation">.</span> css |
You can get the demo here . Once you’ve downloaded it, create a __test__
directory inside /src/components/
.
Write Test in React
Create ProductHeader.test.js
file if you don’t already have one. Here is an example of how the test should look like
src/components/__tests__/ProductList.test.js
1 2 3 4 5 6 7 8 9 10 11 | <span class="token function">describe</span> <span class="token punctuation">(</span> <span class="token string">'ProductHeader'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">it</span> <span class="token punctuation">(</span> <span class="token string">'passing test'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">expect</span> <span class="token punctuation">(</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">toBeTruthy</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token function">it</span> <span class="token punctuation">(</span> <span class="token string">'failing test'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">expect</span> <span class="token punctuation">(</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">toBeTruthy</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
The test starts with describe
block, it is a function of Jest with two parameters. The first is the name of the cast test, the second is the part to test. The keyword it()
can be a test case or a spec. Each test case has one or more test results that check the status of the code.
expects(true).toBeTruthy();
toBeTruthy()
is a toBeTruthy()
comparison function. In Jest, each comparison function creates a comparison step with the resulting and actual values and returns the boolean value.
Run the test
The create-react-app has everything installed, so just run the test with the following command:
yarn test
You replace the toBeTruthy()
function with toBeFalsy()
to pass the test.
The comparison function in Jest
As stated above, Jest has many comparison functions as follows:
1 2 3 4 5 6 7 8 9 10 11 | <span class="token function">toBe</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toBeNull</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toBeDefined</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toBeUndefined</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toBeTruthy</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toBeFalsy</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toBeGreaterThan</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toBeLesserThan</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toMatch</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">toContain</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> |
Also you can refer to the following document to find more functions: https://jestjs.io/docs/en/using-matchers
Test react component
First we will write some test cases for ProductHeader
. src/components/ProductHeader.js
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">import</span> React <span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">ProductHeader</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> h2 className <span class="token operator">=</span> <span class="token string">"title"</span> <span class="token operator">></span> Product Listing Page <span class="token operator"><</span> <span class="token operator">/</span> h2 <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> ProductHeader <span class="token punctuation">;</span> |
To test we have two assumptions as follows:
- This component will return
h2
tag. h2
tag will have a class namedtitle
.
Back to the test file we write the following:
src/components/__tests__/ProductHeader.test.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> ReactTestUtils <span class="token keyword">from</span> <span class="token string">'react-dom/test-utils'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> ProductsList <span class="token keyword">from</span> <span class="token string">'../ProductsList'</span> <span class="token punctuation">;</span> <span class="token function">describe</span> <span class="token punctuation">(</span> <span class="token string">'ProductHeader Component'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">it</span> <span class="token punctuation">(</span> <span class="token string">'has an h2 tag'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">//Test here</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">it</span> <span class="token punctuation">(</span> <span class="token string">'is wrapped inside a title class'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">//Test here</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
To test it first, we have to render it into the document. With the help of ReactTestUtils
, write the following:
const component = ReactTestUtils.renderIntoDocument(<ProductHeader/>);
Then modify the test function as follows:
1 2 3 4 5 6 7 8 9 | <span class="token function">it</span> <span class="token punctuation">(</span> <span class="token string">'has an h2 tag'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> component <span class="token operator">=</span> ReactTestUtils <span class="token punctuation">.</span> <span class="token function">renderIntoDocument</span> <span class="token punctuation">(</span> <span class="token operator"><</span> ProductHeader <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> h2 <span class="token operator">=</span> ReactTestUtils <span class="token punctuation">.</span> <span class="token function">findRenderedDOMComponentWithTag</span> <span class="token punctuation">(</span> component <span class="token punctuation">,</span> <span class="token string">'h2'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Similarly with the second test case
1 2 3 4 5 6 7 8 | <span class="token function">it</span> <span class="token punctuation">(</span> <span class="token string">'has a title class'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> component <span class="token operator">=</span> ReactTestUtils <span class="token punctuation">.</span> <span class="token function">renderIntoDocument</span> <span class="token punctuation">(</span> <span class="token operator"><</span> ProductHeader <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> node <span class="token operator">=</span> ReactTestUtils <span class="token punctuation">.</span> <span class="token function">findRenderedDOMComponentWithClass</span> <span class="token punctuation">(</span> component <span class="token punctuation">,</span> <span class="token string">'title'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
Then see the results:
So through this article we have written a test case on React, later we will use Enzyme to write because Enzyme is easier to develop, easier to use. Thank you for watching.
Ref: