Написание тестов в React имеет решающее значение для обеспечения того, чтобы приложения работали должным образом, выявляя ошибки на ранних этапах цикла разработки и снижая общую стоимость исправления проблем.

Тесты также обеспечивают уверенность в качестве кодовой базы, упрощая ее сопровождение и рефакторинг. Тестируя код, разработчики могут убедиться, что он соответствует требованиям и спецификациям приложения, и определить области, которые могут нуждаться в улучшении или оптимизации.

В целом, тесты являются важным компонентом процесса разработки программного обеспечения, повышая качество и надежность приложений React.

Я создал шпаргалку по Основам тестирования React, не стесняйтесь скачать ее.

Типы тестов

Это множество различных типов тестов в любом серьезном программном проекте.

  • Модульные тесты проверяют функциональность отдельных модулей или модулей кода. Во многих проектах вам потребуется 80% всех ваших тестов, написанных в модульных тестах.
  • Интеграционные тесты проверяют взаимодействие между различными единицами или модулями кода. Еще 15% — 20% на интеграционные тесты.
  • Сквозные тесты проверяют функциональность всей системы или приложения. Поскольку сквозные тесты реальны, то есть для них требуется много ресурсов, а поскольку они подключают настоящие компоненты (базу данных, сеть и сторонние сервисы), они дороги, хрупки и должны использоваться только в большинстве случаев. критические пути. Обычно у вас не будет слишком много тестов (около 5%).

Больше информации о тестовой пирамиде можно найти в этой фантастической статье. В этой статье я хотел бы обсудить некоторые фундаментальные аспекты написания тестов. Здесь я в основном сосредоточусь на модульных тестах, хотя считаю, что интеграционные и сквозные тесты не менее важны.

Прежде чем погрузиться в тестирование, давайте согласуем некоторые основные термины.

Тестовый бегун

Средство запуска тестов — это инструмент, который выполняет автоматизированные тесты, написанные для программного приложения, и сообщает результаты пользователю. Он предоставляет среду для запуска тестов и сбора результатов тестов. Средства выполнения тестов можно настроить для запуска различных типов тестов, таких как модульные тесты, интеграционные тесты и сквозные тесты.

Таким образом, исполнитель тестов может планировать и запускать тесты параллельно, гарантируя, что функции настройки и демонтажа будут вызываться в нужное время и т. д. Кроме того, вы можете настроить их только для запуска небольшого подмножества ваших тестов, что полезно для более крупный проект, содержащий тысячи тестов.

Некоторые известные средства запуска тестов для приложений JavaScript и React включают Jest, Mocha и Cypress.

Тестирование

В Jest набор тестов определяется с помощью функции describe, которая принимает два аргумента: строку, описывающую набор, и функцию обратного вызова, которая содержит один или несколько тестовых случаев с использованием функций test или it. Функция describe позволяет группировать связанные тесты в один набор. Например:

describe('calculator', () => {
  test('addition', () => {
    expect(1+1).toBe(2);
  });

  test('subtract', () => {
    expect(5-3).toBe(2);
  });
});

Организация тестов в наборы позволяет группировать связанные тесты вместе, что облегчает понимание цели и области действия каждого тестового файла. Это также помогает поддерживать организованность и удобство сопровождения тестового кода, особенно по мере роста кодовой базы. Кроме того, наборы тестов могут предоставлять более детализированную информацию о выполняемых тестах, что делает отчет о тестировании более удобочитаемым и ценным.

В этом руководстве для тестирования приложения React нам понадобится React-Testing-Library. Библиотека тестирования React — это легкая библиотека для тестирования компонентов React. Он предоставляет набор утилит, которые позволяют разработчикам писать тесты, имитирующие поведение пользователя, и подтверждающие, что их компоненты правильно отображаются на основе этого поведения. Библиотека фокусируется на тестировании поведения компонентов, а не деталей их реализации, что делает тесты более устойчивыми к изменениям в реализации компонента.

Кроме того, библиотека поощряет разработчиков к написанию тестов, которые очень похожи на то, как пользователи взаимодействуют с компонентом. Это может помочь отловить ошибки, которые не могут быть обнаружены тестами, сосредоточенными только на деталях реализации.

Написание базового теста

Нашим самым первым тестом будет простой render. Этот тест использует функцию render из @testing-library/react для рендеринга компонента AComponent и ожидает, что он будет рендериться без ошибок:

import React from 'react';  
import { render } from '@testing-library/react';  
​  
import AComponent from './AComponent.tsx';  
​  
test('renders AComponent without errors', () => {  
  render(<AComponent />);  
});

Тесты компонентов React также должны проверять правильность поведения компонента в ответ на взаимодействие с пользователем, реквизиты и изменения состояния.

Например:

import React from 'react';  
import { render, fireEvent, screen } from '@testing-library/react';  
import AComponent from './AComponent';  
​  
test('updates state when button is clicked', () => {  
  const { getByText } = render(<AComponent />);
  
  const button = screen.getByText('Click me');
  fireEvent.click(button);
  expect(button).toHaveTextContent('Clicked!');
});

Этот тест использует функцию fireEvent из @testing-library/react для имитации нажатия кнопки и ожидает, что кнопка обновит свое текстовое содержимое на «Нажато!»

Примечание. Хотя метод fireEvent, предоставляемый библиотекой тестирования React, может имитировать взаимодействие с пользователем, часто более реалистично использовать библиотеку userEvent. `userEvent` обеспечивает более точную симуляцию того, как пользователь будет взаимодействовать с вашими компонентами, и может помочь выявить ошибки, которые невозможно обнаружить с помощью более абстрактного метода fireEvent.

Используйте userEvent для реалистичного действия

userEvent обеспечивает более точное моделирование того, как пользователи взаимодействуют с вашими компонентами.

import { render, screen } from "@testing-library/react";  
import userEvent from "@testing-library/user-event";  
import Button from "./Button";  
​  
test("clicking a button", () => {  
  render(<Button />);
  
  const button = screen.getByRole("button");
  userEvent.click(button);
    
  expect(button).toHaveTextContent("Clicked");
});

Тесты компонентов React также должны проверять правильность рендеринга компонента с разными значениями реквизита. Вот пример теста для компонента, который отображает список элементов на основе свойств:

import React from 'react';
import { render, screen } from '@testing-library/react';
import AComponent from './AComponent';

test('renders list of items correctly', () => {
  const items = [
    { id: 1, text: 'Item 1' },
    { id: 2, text: 'Item 2' },
    { id: 3, text: 'Item 3' },
  ];
  
  const { getAllByTestId } = render(<AComponent items={items} />);
  
  const itemsList = screen.getAllByTestId('item');
  expect(itemsList).toHaveLength(items.length);
  
  itemsList.forEach((item, index) => {
    expect(item).toHaveTextContent(items[index].text);
  });
});

Этот тест передает массив реквизитов items компоненту AComponent и ожидает, что он отобразит список элементов с правильным текстовым содержимым и длиной.

Насмешки и заглушки

В некоторых случаях может потребоваться изолировать зависимости, чтобы облегчить тестирование сложного кода. Насмешки и заглушки — это методы создания поддельных объектов или функций, имитирующих поведение реальных зависимостей.

Макеты — это поддельные объекты с предопределенным поведением, которые можно использовать для замены реальных объектов в тестах. Заглушки — это поддельные функции, которые заменяют настоящие функции в тестах и ​​возвращают заранее определенные значения. У Мартина Фаулера есть старая, более содержательная статья о моках и заглушках и некоторых практиках тестирования. Почитайте, если еще не читали.

Вот пример использования макета для изоляции зависимости в тесте:

import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from "@testing-library/user-event";  

import axios from 'axios';

import AComponent from './AComponent';

jest.mock('axios');

test('fetches data and updates state', async () => {
  const data = { id: 1, name: 'John' };
  
  axios.get.mockResolvedValue({ data });
  
  const { getByText } = render(<AComponent />);
  const button = screen.getByText('Fetch data');
  
  userEvent.click(button);
  
  const dataElement = screen.getByText(data.name);
  expect(dataElement).toBeInTheDocument();
});

Этот тест использует функцию jest.mock для создания имитации зависимости axios и использует функцию mockResolvedValue для определения ее поведения. Затем тест имитирует щелчок кнопки в компоненте AComponent, который запускает вызов зависимости axios с фиктивным поведением.

Отчет о тестировании

Вы также можете создать тестовый отчет, чтобы увидеть статистические данные и провести некоторый анализ того, как покрытие меняется с течением времени. Это отличный способ поделиться этими данными в среде непрерывной интеграции, чтобы все в команде могли это четко видеть.

Во-первых, установите пакет jest-html-reporters в корень вашего проекта. А затем в package.json добавить еще одну команду report в раздел скриптов. И каждый раз, когда вы запускаете npm run report, он будет генерировать для вас отчет.

"report": "react-scripts test --env=jsdom --reporters=default \
--reporters=jest-html-reporters"

Краткое содержание

В заключение, тестирование является неотъемлемой частью разработки программного обеспечения и имеет решающее значение для обеспечения надежности и высокого качества кодовой базы. Jest и React-Testing-Library — отличные инструменты для тестирования приложений React, и с их помощью разработчики могут выявлять ошибки на ранней стадии, снижать затраты на устранение проблем и быть уверенными в качестве своего кода.

Кроме того, при правильной настройке и отчетности разработчики могут легко отслеживать состояние своей кодовой базы и выявлять области, требующие улучшения. Включив тестирование в свой процесс разработки, разработчики могут создавать более качественные приложения React и обеспечивать лучший пользовательский интерфейс.

Если вам понравилось чтение, пожалуйста, Подпишитесь на мою рассылку. Я еженедельно делюсь методами чистого кода и рефакторинга в блогах, книгах и видео.