Testing Library: More than a Great Name
Published: 2021-03-22 14:01:51

For much of my coding bootcamp experience, I've done a lot of test-driven development, but those tests have mostly, if not always, targeted the algorithms and individual parts of the components rather than the behaviors triggered by someone who is interacting with the app. There's a tool available with perhaps the most genius name, making it easily searchable even if you can't remember it: Testing Library (That's probably what you entered into the search bar, right?).

[Kent C. Dodds](https://kentcdodds.com/) created React Testing Library in 2018. He had been using and teaching Airbnb's Enzyme, a library with a lot of different capabilities. With so many options available in Enzyme, he found that he spent a lot of time trying to teach which parts of Enzyme were considered the current best practice before he could begin to teach functionality. Instead of continuing to waste time, he shifted his focus. He wanted to build a smaller library that encouraged better testing practices, and so React Testing Library was born. Realizing that most of the APIs were not React-specific, he eventually released its core as DOM Testing Library as well.

Note that it is a utility library, not a framework, so it doesn't replace suites like Mocha and Jest but rather works alongside them. Its purpose is to test the UI, or how the user interacts with the app. In the example below that is included in [Testing Library's documentation](https://testing-library.com/docs/example-react-router), this test is specifically targeting a route built with React Router.

```js
test('full app rendering/navigating', () => {
  renderWithRouter(<App />)
  expect(screen.getByText(/you are home/i)).toBeInTheDocument()

  const leftClick = { button: 0 }
  userEvent.click(screen.getByText(/about/i), leftClick)

  expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
})

test('landing on a bad page', () => {
  renderWithRouter(<App />, { route: '/something-that-does-not-match' })

  expect(screen.getByText(/no match/i)).toBeInTheDocument()
})

test('rendering a component that uses useLocation', () => {
  const route = '/some-route'
  renderWithRouter(<LocationDisplay />, { route })

  expect(screen.getByTestId('location-display')).toHaveTextContent(route)
})
```

How is this different from Enzyme? Testing Library is checking the DOM nodes, so it's testing the behavior of your application from a user's perspective. Enzyme, on the other hand, checks the actual components for things like props and state. A typical user isn't concerned with props or state but rather that their expectations are met when they navigate to a page, open a modal, or click a button. With Testing Library, though the code may change within the components, the functionality should remain intact, which means you won't have to refactor the tests every time you refactor the components.

Testing the UI can be done by manually navigating and clicking around the site to test its functionality, but as an app increases in size, so does the time it takes to check all of the necessary behavioral aspects. Testing Library is a great tool to automate these checks by mimicking the interactions a user may have while using an app. I look forward to implementing it in future projects.

The [React Testing Library](https://www.npmjs.com/package/@testing-library/react) can be installed with
`npm install --save-dev @testing-library/react`

and the [DOM Testing Library](https://www.npmjs.com/package/@testing-library/dom) can be installed with
`npm install --save-dev @testing-library/dom`