Running tests using react-scripts

When you create your React application using create-react-app, you're ready to run tests right away. In fact, as part of the boilerplate code that's created for you, a unit test for the App component is created. This test is added so that Jest will find a test that it can run. It doesn't actually test anything meaningful in your application, so you'll probably delete it once more tests are added.

Additionally, create-react-app adds the appropriate script to your package.json file to run your tests. You can just run the following command in your Terminal:

npm test

This will actually invoke the test script from react-scripts. This will invoke Jest, which runs any tests that it finds. In this case, since you're working with a fresh project, it will only find the one test that create-react-app creates. Here's what the output of running this test looks like:

PASS  src/App.test.js
  renders without crashing (3ms)
    
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.043s, estimated 1s

The test that was run lives in the App.test.js module—all Jest tests should have test somewhere in their filename. A good convention to follow is ComponentName.test.js. Then, you can see a list of tests that were run in this module, how long they took, and whether they passed or failed.

At the bottom, Jest prints out summary information of the run. This is often a good starting point because if all your tests are passing, you might not care about any other output. On the other hand when a test fails, the more information, the better.

The test script from react-scripts invokes Jest in watch mode. This means that you can choose which tests are actually run when files are changed. Here's what the menu looks like on the command line:

Watch Usage
 > Press a to run all tests.
 > Press p to filter by a filename regex pattern.
> Press t to filter by a test name regex pattern. > Press q to quit watch mode. > Press Enter to trigger a test run.

When Jest is running in watch mode, the process doesn't exit as soon as all tests complete. Instead, it watches your test and component files for changes and runs tests when changes are detected. These options allow you to fine-tune which tests are run when changes take place. The p and t options are only useful if you have thousands of tests and many of them are failing. These options are useful to drill down and find the offending component as it's developed.

By default, when a change is detected by Jest, only associated tests are run. For example, changing the test or the component will result in the test being run again. With npm test running in your Terminal, let's open up App.test.js and make a small change to the test:

it('renders without crashing', () => { 
  const div = document.createElement('div'); 
  ReactDOM.render(<App />, div); 
}); 

You can just change the name of the test so that it looks like the following, and then save the file:

it('renders the App component', () => { 
  const div = document.createElement('div'); 
  ReactDOM.render(<App />, div); 
}); 

Now, take a look at your Terminal where you left Jest running in watch mode:

PASS  src/App.test.js
  renders the App component (4ms)

Jest detected the change in your unit test and ran it, producing the updated console output. Now let's introduce a new component and a new test and see what happens. First, you'll implement a Repeat component that looks like the following:

export default ({ times, value }) => 
  new Array(parseInt(times, 10))
    .fill(value)
    .join(' ');

This component takes a times property, which is used to determine how many times to repeat the value property. Here's how the Repeat component is used by the App component:

import React, { Component } from 'react'; 
import logo from './logo.svg'; 
import './App.css'; 
import Repeat from './Repeat'; 
 
class App extends Component { 
  render() { 
    return ( 
      <div className="App"> 
        <header className="App-header"> 
          <img src={logo} className="App-logo" alt="logo" /> 
          <h1 className="App-title">Welcome to React</h1> 
        </header> 
        <p className="App-intro"> 
          <Repeat times="5" value="React!" /> 
        </p> 
      </div> 
    ); 
  } 
} 
 
export default App; 

If you were to view this application, you would see the string React! rendered five times on the page. Your component works as expected, but let's make sure that we add a unit test before committing your new component. Create a Repeat.test.js file that looks like this:

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import Repeat from './Repeat'; 
 
it('renders the Repeat component', () => { 
  const div = document.createElement('div'); 
  ReactDOM.render(<Repeat times="5" value="test" />, div); 
}); 

This is actually the same unit test used for the App component. It doesn't test much other than that the component can render without triggering some sort of error. Now Jest has two component tests to run: one for App and the other one for Repeat. If you look at the console output for Jest, you'll see that both tests are run:

PASS  src/App.test.js
PASS  src/Repeat.test.js
    
Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.174s, estimated 1s
Ran all test suites related to changed files.

Pay attention to the last line in this output. The default watch mode of Jest is to look for files that haven't been committed to source control and that have been saved. By ignoring components and tests that have been committed, you know that they haven't changed, so running those tests would be pointless. Let's try changing the Repeat component and see what happens (you don't actually have to change anything, just saving the file is enough to trigger Jest):

 PASS  src/App.test.js 
 PASS  src/Repeat.test.js 

Why is the App test running? It's committed and hasn't been changed. The issue is that since App depends on Repeat, changes to the Repeat component could cause App tests to fail.

Let's introduce another component and test, except that this time we won't introduce any dependencies importing the new component. Create a Text.js file and save it with the following component implementation:

export default ({ children }) => children; 

This Text component will just render whatever child element or text that is passed to it. It's a contrived component, but that doesn't matter. Now let's write a test that will verify that the component returns the value as expected:

import Text from './text'; 
 
it('returns the correct text', () => {
  const children = 'test';
  expect(Text({ children })).toEqual(children);
});

The toEqual() assertion passes when the value returned by Text() is equal to the children value. When you save this test, take a look at the Jest console output:

PASS  src/Text.test.js
  returns the correct text (1ms)
    
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total

Now that you have a test that doesn't have any dependencies, Jest will run it on its own. The other two tests are checked into Git, so it knows that these tests do not need to run. You would never commit something that doesn't pass a unit test, right?

Let's make this test fail now and see what happens. Change the Test component so that it looks like this:

export default ({ children }) => 1;

This will fail the test because it is expecting the component function to return the value passed to the children property. Now if you go back to the Jest console, the output should look like this:

FAIL  src/Text.test.js
  returns the correct text
    
   expect(received).toEqual(expected)
    
   Expected value to equal:
     "test"
   Received:
     1
    
   Difference:
    
     Comparing two different types of values. Expected string but 
     received number.

The test failed, as you knew it would. What's interesting is that once again, this was the only test that was run because nothing else has changed according to Git. The benefit to you is that once you have hundreds of tests, you don't need to wait for all of them to run before a failing test for the component that you're currently working can run.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.203.68