Introduction to Testing Library

Get an introduction to the Testing Library.

Testing library

The philosophy behind Testing Library is:

The more your tests resemble the way your software is used, the more confidence they can give you.

This maps closely with the test pyramid we discussed earlier. Now, we can combine end-to-end tests with a testing library that closely resembles the way our software is used.

Testing library features

A very important aspect of the Testing Library is to provide the functionality to test whether our HTML is accessible. Besides the DOM tree, there is also an accessibility tree used by screen readers. To truly develop web applications that are accessible to anyone, it is important to take accessibility seriously. Please see Mozilla’s “What is accessibility?”.

For our convenience, there is a cypress-testing-library project. We will use that to bridge the gap between Cypress and the Testing Library.

If you are interested in a Testing Framework Svelte integration to test individual Svelte components rather than using the Cypress framework, you are in luck as well.

Another interesting project is the Testing Library playground. At the top, you can create your HTML and see it rendered to the right. Below, you can use the Testing Library to query elements and see details about the queried elements on the side.

Alternatives

This is a tricky one to list alternatives for. On the one hand, the Testing Library is an optional tool included in this course because of its added benefit to writing tests in the way users interact with the web application. On the other hand, it is important to highlight its accessibility capabilities. An alternative solution is unknown at this time.

Why use testing library?

To illustrate why we use the Testing Library, let’s look at a Cypress test to validate functionality related to a dialog. Here is the HTML we will write a test case for:

<body>
  <!-- 'aria-hidden = "true" ' means that the <main> tag and its children <button> regardless of whether the element is visually rendered or not, should not be exposed to the accessibility API. -->
  <main aria-hidden="true"> 
    <button>Open dialog</button>
  </main>
  <div role="dialog">
    <button>Close dialog</button>
  </div>
</body>

This HTML snippet shows three elements of interest:

  • A button to open a dialog
  • A div that represents a dialog
  • A button to close the dialog, located within the dialog div

Is the dialog open or closed right now? Well, that depends. Visually, we don’t know, because we would need to look at the CSS. From an accessibility standpoint, the dialog is open and the “Open dialog” button (and the parent <main> element) are hidden.

You may want to write a Cypress test similar to the following:

it("has open dialog button", () => {
  cy.contains("button", "Open dialog");
});

That test passes, but should it? Let’s look at a test written with the Testing Library:

it("has open dialog button - Testing Library", () => {
 cy.findByRole("button").should("have.value","Open dialog");
});

That test fails! It fails because the “Open dialog” button is a child of an element with an aria-hidden="true" attribute. To accommodate users with a screen reader, the failing test is what we want, whereas the Cypress test lets us believe everything is okay, when in fact it is not.

Remember, the more your tests resemble the way your software is used, the more confidence they can give you.

Get hands-on with 1200+ tech skills courses.