Тестирование сценариев пользователя

Тестирование сценариев пользователя (или user scenarios) — это важная часть процесса тестирования, которая направлена на проверку того, как приложение будет вести себя в реальных условиях. Jest предоставляет удобные инструменты для создания таких тестов, которые симулируют действия пользователей и позволяют выявить ошибки и улучшить качество кода. В этой части рассмотрим, как правильно тестировать сценарии пользователя с использованием Jest, начиная от базовых концепций до более сложных случаев.

Подготовка к тестированию пользовательских сценариев

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

Для тестирования таких сценариев потребуется:

  1. Модели компонентов: Основные элементы, которые будут подвергаться тестированию.
  2. Интеракции: Последовательность шагов, которые должен выполнить пользователь.
  3. Состояние приложения: Как изменяется приложение после выполнения каждого шага.

Jest поможет организовать тесты с использованием mock-функций, симуляции событий и проверки состояний компонентов. Один из самых удобных инструментов для работы с такими тестами в Jest — это использование библиотек, таких как @testing-library/react, которая предоставляет функции для удобной работы с DOM и симуляции действий пользователя.

Симуляция действий пользователя

Для тестирования взаимодействий пользователя с интерфейсом часто требуется симуляция кликов, ввода текста и других действий. Jest предоставляет несколько способов для этого.

Пример теста, который имитирует клики и ввод текста:

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

test('Пользователь успешно отправляет форму', () => {
  render(<UserForm />);
  
  // Симуляция ввода текста в поля формы
  fireEvent.change(screen.getByLabelText(/Имя/i), { target: { value: 'Иван' } });
  fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'ivan@mail.com' } });
  
  // Симуляция отправки формы
  fireEvent.click(screen.getByText(/Отправить/i));
  
  // Проверка состояния компонента после отправки
  expect(screen.getByText(/Форма отправлена/i)).toBeInTheDocument();
});

В данном примере используется библиотека @testing-library/react для рендеринга компонента и симуляции действий пользователя, таких как ввод текста и клик по кнопке. После выполнения этих действий проверяется, что форма была отправлена и что отображается соответствующее сообщение.

Тестирование сложных сценариев

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

Пример теста для проверки обработки ошибок:

import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import UserForm from './UserForm';
import { postData } from './api'; // Функция для отправки данных

jest.mock('./api'); // Мокаем функцию postData

test('Обработка ошибки при отправке формы', async () => {
  render(<UserForm />);
  
  fireEvent.change(screen.getByLabelText(/Имя/i), { target: { value: 'Иван' } });
  fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'ivan@mail.com' } });
  
  postData.mockRejectedValueOnce(new Error('Сервер недоступен'));
  
  fireEvent.click(screen.getByText(/Отправить/i));
  
  await waitFor(() => {
    expect(screen.getByText(/Ошибка при отправке данных/i)).toBeInTheDocument();
  });
});

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

Использование асинхронных тестов

Часто в реальных приложениях взаимодействие с сервером или внешними сервисами является асинхронным. Jest позволяет легко работать с такими случаями, используя методы, такие как async и await. Для асинхронных операций важно использовать утилиты Jest для ожидания завершения работы асинхронных действий перед проверкой результатов.

Пример асинхронного теста с использованием async и await:

import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import UserForm from './UserForm';
import { fetchUserData } from './api';

jest.mock('./api');

test('Загрузка данных пользователя перед отправкой формы', async () => {
  render(<UserForm />);
  
  fetchUserData.mockResolvedValueOnce({ name: 'Иван', email: 'ivan@mail.com' });

  // Симуляция загрузки данных пользователя
  fireEvent.click(screen.getByText(/Загрузить данные/i));
  
  await waitFor(() => expect(screen.getByText(/Имя: Иван/i)).toBeInTheDocument());
  await waitFor(() => expect(screen.getByText(/Email: ivan@mail.com/i)).toBeInTheDocument());
});

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

Работа с состоянием приложения

Часто в процессе тестирования необходимо убедиться, что состояние приложения корректно меняется в ответ на действия пользователя. Jest в сочетании с @testing-library/react предоставляет удобные средства для работы с состоянием и проверки его изменений. Состояние компонента может меняться как в результате действий пользователя, так и в ответ на асинхронные запросы.

Пример теста, проверяющего изменение состояния:

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

test('Пользователь увеличивает счётчик', () => {
  render(<Counter />);
  
  // Проверка начального значения счётчика
  expect(screen.getByText(/Счётчик: 0/i)).toBeInTheDocument();
  
  // Симуляция клика по кнопке увеличения
  fireEvent.click(screen.getByText(/Увеличить/i));
  
  // Проверка изменения состояния после клика
  expect(screen.getByText(/Счётчик: 1/i)).toBeInTheDocument();
});

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

Сложные пользовательские сценарии

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

Пример сложного сценария:

import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import CheckoutPage from './CheckoutPage';

jest.mock('./api');

test('Пользователь проходит весь процесс оформления заказа', async () => {
  render(<CheckoutPage />);
  
  // Шаг 1: Ввод данных о доставке
  fireEvent.change(screen.getByLabelText(/Имя/i), { target: { value: 'Иван' } });
  fireEvent.change(screen.getByLabelText(/Адрес/i), { target: { value: 'Москва, ул. Пушкина, д. 10' } });
  
  // Шаг 2: Выбор метода оплаты
  fireEvent.click(screen.getByText(/Кредитная карта/i));
  
  // Шаг 3: Отправка данных
  fireEvent.click(screen.getByText(/Оформить заказ/i));
  
  // Проверка завершения оформления заказа
  await waitFor(() => expect(screen.getByText(/Заказ успешно оформлен/i)).toBeInTheDocument());
});

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

Заключение

Тестирование сценариев пользователя — это важный аспект обеспечения качества веб-приложений, который позволяет убедиться в том, что приложение работает так, как ожидается, при реальных условиях использования. Jest и вспомогательные библиотеки, такие как @testing-library/react, позволяют легко симулировать действия пользователя и проверять различные состояния компонентов. Создание тестов для пользовательских сценариев помогает улучшить качество кода, ускорить процесс разработки и предотвратить появление багов.