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

Модульное тестирование моментальных снимков можно рассматривать как форму регрессионного тестирования, которое фиксирует текущее состояние выходных данных и сравнивает его с ранее сохраненным моментальным снимком.

Чем оно отличается от функционального модульного тестирования

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

2. Создание тестового случая:

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

3. Подход к тестированию:

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

Примеры кода

  1. Тестирование выходных данных функции

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

// code

function getGreeting(name) {
  return `Good Morning, ${name}!`;
}
// test

import { getGreeting } from './greeting';

test('getGreeting returns a greeting message', () => {
  const result = getGreeting('Sanchit');
  expect(result).toMatchSnapshot();
});

2.Тестирование простого компонента React

В этом примере мы тестируем компонент React, Button. Проверка моментального снимка гарантирует, что визуализированный вывод компонента соответствует сохраненному снимку.

// code

import React from 'react';
const Button = ({ text }) => <button>{text}</button>;
export default Button;
//test

import React from 'react';
import { render } from '@testing-library/react';
import Button from './Button';

test('Button renders correctly', () => {
  const { container } = render(<Button text="Click Me" />);
  expect(container.firstChild).toMatchSnapshot();
});

3. Тестирование компонента реакции с помощью реквизитов

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

Функция render из библиотеки @testing-libraray/react используется для рендеринга компонента UserCard и получения результирующего контейнера. Контейнер представляет визуализированный вывод компонента.

Функция toMatchSnapshot вызывается для первого дочернего элемента контейнера. Эта функция сравнивает текущий вывод компонента UserCard с ранее сохраненным снимком. Если выходные данные совпадают со снимком, тест проходит успешно; в противном случае он терпит неудачу.

// code

import React from 'react';

const UserCard = ({ name, email }) => (
  <div>
    <h2>{name}</h2>
    <p>{email}</p>
  </div>
);

export default UserCard;
// test

import React from 'react';
import { render } from '@testing-library/react';
import UserCard from './UserCard';

test('UserCard renders correctly', () => {
  const user = {
    name: 'Sanchit',
    email: '[email protected]',
  };

  const { container } = render(<UserCard {...user} />);
  expect(container.firstChild).toMatchSnapshot();
});

4. Тестирование ответа API

В этом примере мы имитируем модуль axios, используя функцию Jest jest.mock для имитации ответа API. Затем мы используем axios.get.mockResolvedValue, чтобы предоставить фиктивные данные для вызова API. Функция getUserData тестируется, чтобы убедиться, что она правильно извлекает и возвращает фиктивные пользовательские данные. Тест моментального снимка сверяет полученные пользовательские данные с сохраненным моментальным снимком.

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

// code

import axios from 'axios';

async function getUserData(userId) {
  const response = await axios.get(`/users/${userId}`);
  return response.data;
}
// test

import axios from 'axios';
import { getUserData } from './api';

jest.mock('axios');

test('getUserData retrieves user data from API', async () => {
  const userId = 1;
  const mockUserData = {
    id: userId,
    name: 'John Doe',
    email: '[email protected]',
  };

  axios.get.mockResolvedValue({ data: mockUserData });

  const userData = await getUserData(userId);
  expect(userData).toMatchSnapshot();
});

5. Тестирование динамически сгенерированного

Предоставленный код включает функцию generateMarkup, которая принимает массив элементов в качестве параметра. Внутри функции он использует метод map для создания нового массива, в котором каждый элемент заключен в HTML-элемент ‹li›. Полученный массив затем объединяется с помощью метода соединения, чтобы сформировать единую строку HTML-разметки. Эта функция по существу генерирует список HTML на основе заданного массива элементов.

// code

function generateMarkup(items) {
  return items.map((item) => `<li>${item}</li>`).join('');
}

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

//test 

import { generateMarkup } from './generateMarkup';

test('generateMarkup generates HTML markup correctly', () => {
  const items = ['Item 1', 'Item 2', 'Item 3'];
  const markup = generateMarkup(items);
  expect(markup).toMatchSnapshot();
});

6. Тестирование запроса API с параметрами запроса

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

//code 

import axios from 'axios';

async function searchUsers(query) {
  const response = await axios.get('/users/search', { params: { query } });
  return response.data;
}
//test

import axios from 'axios';
import { searchUsers } from './api';

jest.mock('axios');

test('searchUsers retrieves user data based on query parameter', async () => {
  const query = 'John';
  const mockUserData = [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Johnny Smith' },
  ];

  axios.get.mockResolvedValue({ data: mockUserData });

  const userData = await searchUsers(query);
  expect(userData).toMatchSnapshot();
});

Может ли моментальное тестирование заменить функциональное тестирование

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

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

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