Гид по технологиям

Тестирование Next.js-приложения с Jest — пошаговое руководство

5 min read Программирование Обновлено 14 Dec 2025
Тестирование Next.js с Jest
Тестирование Next.js с Jest

Мужчина за рабочим столом печатает на ноутбуке, на экране — код.

Введение

Главная цель любого процесса разработки — довести приложение до продакшен-готового состояния. Для этого код должен не только реализовывать бизнес‑логику, но и оставаться стабильным при дальнейших изменениях. Тесты помогают зафиксировать ожидаемое поведение и предотвратить регрессии.

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

Тестирование Next.js-приложений

Писать тесты — важная и часто недооценённая часть разработки. Легко поддаться соблазну напрямую выкатывать изменения в продакшен, полагаясь на то, что «я писал этот код, значит он работает». Но такой подход ведёт к неожиданным сбоям.

Подход TDD (test-driven development) или просто регулярное добавление юнит‑ и интеграционных тестов значительно повышает уверенность в изменениях и экономит время на отладке.

Ноутбук с кодом на экране

Важно: тесты не заменяют E2E‑покрытие и наблюдаемость в продакшене, но они минимизируют тривиальные регрессии и облегчают рефакторинг.

Что такое Jest?

Jest — популярный фреймворк для тестирования JavaScript/TypeScript приложений. Он включает раннер тестов, систему моков и поддержку snapshot‑тестов. В паре с React Testing Library Jest позволяет писать понятные и стабильные тесты компонентов.

Кратко: Jest — это инструмент для запуска тестов, утверждений и моков; React Testing Library — для взаимодействия с компонентами как с пользователем.

Создание примера: To‑Do приложение на Next.js

Мы пройдём пример создания простого To‑Do и написания для него тестов. Предполагается, что у вас установлен Node.js и npm.

Шаги для запуска проекта и установки зависимостей:

  1. Создайте новый проект Next.js:
npx create-next-app@latest nextjs-test-tutorial
  1. Перейдите в директорию проекта:
cd nextjs-test-tutorial
  1. Установите dev‑зависимости:
npm install --save-dev jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom

Примечание: ставьте зависимости как devDependencies — они нужны только для тестирования.

После установки можно приступить к реализации компонента и тестов.

Создаём компонент To‑Do

В папке проекта откройте файл src/pages/index.js, удалите boilerplate и замените код на следующий. Сначала импортируем React‑хуки и стили, затем определим функции addTodo и deleteTodo.

import { useState } from "react";
import styles from "../styles/Home.module.css";

export default function Home() {
  const [todos, setTodos] = useState([]);
  const [newTodo, setNewTodo] = useState("");

  const addTodo = () => {
    if (newTodo.trim() !== "") {
      const updatedTodos = [...todos, newTodo];
      setTodos(updatedTodos);
      setNewTodo("");
    }
  };

  const deleteTodo = (index) => {
    const updatedTodos = [...todos];
    updatedTodos.splice(index, 1);
    setTodos(updatedTodos);
  };

  return (
    
setNewTodo(e.target.value)} />
    {todos.map((todo, index) => (
  • {todo}
  • ))}
{todos.map((todo, index) => (
))}
); }

Пояснение: useState управляет массивом todos и текущим вводом newTodo. addTodo добавляет непустую строку, deleteTodo удаляет элемент по индексу.

Конфигурация Jest

Создайте в корне проекта файл jest.config.js и добавьте конфигурацию для Next.js:

const nextJest = require("next/jest");
const createJestConfig = nextJest({
  dir: "./",
});

const customJestConfig = {
  moduleDirectories: ["node_modules", "/"],
  testEnvironment: "jest-environment-jsdom",
};

module.exports = createJestConfig(customJestConfig);

Откройте package.json и добавьте скрипт test, чтобы запускать Jest в режиме наблюдения:

"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "next lint",
  "test": "jest --watchAll"
},

Теперь можно писать и запускать тесты.

Пишем тесты для To‑Do

Создайте папку tests в корне проекта и файл index.test.js внутри неё.

Импорты и базовая настройка:

import Home from "../src/pages/index";
import "@testing-library/jest-dom";
import { fireEvent, render, screen, waitFor, act } from "@testing-library/react";

Тест на рендеринг элементов:

describe("Todo App", () => {
  it("renders the todo app", () => {
    render();

    expect(screen.getByTestId("todo-input")).toBeInTheDocument();
    expect(screen.getByTestId("add-todo")).toBeInTheDocument();
  });
});

Запуск тестов:

npm run test

Если всё настроено правильно, вы увидите, что тесты проходят.

Скриншот терминала с успешным тестом

Тестирование действий: добавление и удаление задач

Тест на добавление задачи. Мы симулируем ввод текста и клик по кнопке «Add Todo».

it("adds a todo", async () => {
  render();

  const todoInput = screen.getByTestId("todo-input");
  const addTodoButton = screen.getByTestId("add-todo");
  const todoList = screen.getByTestId("todo-list");

  await act(async () => {
    fireEvent.change(todoInput, { target: { value: "New Todo" } });
    addTodoButton.click();
  });

  await waitFor(() => {
    expect(todoList).toHaveTextContent("New Todo");
  });
});

Чтобы смоделировать ошибку, можно изменить data-testid кнопки и запустить тест — он упадёт, сигнализируя о несоответствии тестовой инфраструктуры.

Ошибка теста добавления Todo

Тест на удаление задачи:

it("deletes a todo", async () => {
  render();

  const todoInput = screen.getByTestId("todo-input");
  const addTodoButton = screen.getByTestId("add-todo");

  fireEvent.change(todoInput, { target: { value: "Todo 1" } });
  fireEvent.click(addTodoButton);

  const deleteTodoButton = screen.getByTestId("delete-todo-0");
  fireEvent.click(deleteTodoButton);

  const todoList = screen.getByTestId("todo-list");
  await waitFor(() => {
    expect(todoList).toBeEmptyDOMElement();
  });
});

Советы по стабильности тестов

Важно следовать нескольким простым правилам для надёжных тестов:

  • Тестируйте поведение, а не реализацию. Ориентируйтесь на видимый интерфейс.
  • Избегайте жёстких зависимостей от внутренних хелперов компонента.
  • Используйте data-testid только там, где другие селекторы ненадёжны.
  • Старайтесь, чтобы тесты были быстрыми и детерминированными.

Когда тесты не помогут

  • Тесты не обнаружат проблем с инфраструктурой (сеть, база данных) без соответствующей интеграции или моков.
  • Они не заменят E2E‑тесты для проверки реальных пользовательских сценариев.
  • Неправильно написанные тесты могут дать ложное чувство безопасности.

Альтернативные подходы

  • Cypress / Playwright — для E2E‑тестов и тестирования пользовательских сценариев.
  • Vitest — быстрый тестовый раннер для проектов с Vite.
  • React Testing Library + Jest — лучше всего подходит для unit/integration в React/Next.js.

Модель мышления при проектировании тестов

  1. Сценарии пользования (user stories) → 2. Критерии приёмки → 3. Юнит/интеграционные тесты для бизнес‑логики → 4. E2E‑тесты для ключевых путей.

Чек-листы для ролей

Разработчик:

  • написать тесты на новую логику;
  • обеспечить тестируемость (чёткость data-testid или семантические селекторы);
  • запускать локально перед PR.

Код‑ревьювер:

  • проверить покрытие ключевых сценариев;
  • убедиться, что тесты проверяют поведение, а не реализацию;
  • проследить за стабильностью тестов.

CI/DevOps:

  • запускать тесты на merge/PR;
  • настроить отчёты и артефакты тестирования;
  • отделять быстрые unit от долгих интеграционных тестов.

Критерии приёмки

  • Основной поток работает: добавление и удаление задач;
  • UI‑элементы присутствуют и доступны для взаимодействия;
  • Тесты запускаются в CI и проходят стабильно;
  • В pull request присутствуют тесты на изменённую логику.

Шпаргалка команд и Snippet

Команды:

  • npm run dev — локальная разработка
  • npm run build — сборка
  • npm run start — запуск продакшен‑сборки
  • npm run test — запуск jest в watch‑режиме

Полезный snippet для Jest + RTL:

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

// render
render();
// взаимодействие
await userEvent.type(screen.getByRole('textbox'), 'text');
userEvent.click(screen.getByRole('button', { name: /add/i }));
// ожидание
await waitFor(() => expect(screen.getByText('text')).toBeInTheDocument());

Decision tree для выбора типа теста

flowchart TD
  A[Новая функциональность?] --> B{Покрытие UI или логики}
  B --> |UI| C[Написать юнит/интеграционные тесты с RTL]
  B --> |Бизнес-логика| D[Юнит-тесты для функций/хуков]
  C --> E{Требуется симуляция реального сценария}
  E --> |Да| F[Добавить E2E 'Cypress/Playwright']
  E --> |Нет| G[Оставаться на unit/integration]
  D --> G
  F --> H[Запуск в CI и локально]

Краткий глоссарий

  • Юнит‑тест: проверяет одну функцию или компонент в изоляции.
  • Интеграционный тест: проверяет взаимодействие нескольких компонентов или модулей.
  • E2E‑тест: проверяет полный пользовательский путь в приложении.

Резюме

Это руководство показало, как добавить Jest и React Testing Library в Next.js‑проект, создать простой To‑Do‑компонент и написать тесты на рендеринг, добавление и удаление задач. Тесты повышают стабильность кода и ускоряют безопасные изменения. Расширяйте набор тестов по мере роста приложения: добавляйте интеграционные и E2E‑тесты для критичных сценариев.

Важно: автоматизация тестов в CI и дисциплина команды — ключевые факторы успеха.

Дополнительные ресурсы

Jest вывод тестов в терминале

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как включить TPM 2.0 в BIOS — ASUS, Dell, HP, Lenovo
Windows

Как включить TPM 2.0 в BIOS — ASUS, Dell, HP, Lenovo

Папка профиля Firefox: где найти и как восстановить
Руководство

Папка профиля Firefox: где найти и как восстановить

Исправить: USB-устройство не распознано — контроллер Xbox One
Техподдержка

Исправить: USB-устройство не распознано — контроллер Xbox One

Сборка Ender 3 V2 — пошаговая инструкция
3D-печать

Сборка Ender 3 V2 — пошаговая инструкция

Добавить Google Alerts в RSS-ленту
Руководство

Добавить Google Alerts в RSS-ленту

Идеальное резюме в Canva: поиск и настройка
Карьера

Идеальное резюме в Canva: поиск и настройка