← Назад к вопросам

Расскажи про стандартные сценарии тестирования Unit тестами

1.7 Middle🔥 251 комментариев
#Тестирование

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Стандартные сценарии тестирования Unit тестами

Unit-тестирование — это фундаментальная практика разработки программного обеспечения, направленная на проверку корректности отдельных изолированных модулей (функций, классов, методов) приложения. Цель — убедиться, что каждая "единица" кода ведёт себя ожидаемо в различных условиях. Стандартные сценарии можно разделить на несколько ключевых категорий.

1. Тестирование базовой функциональности (Happy Path)

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

Пример на JavaScript (Jest):

// Функция для тестирования
function sum(a, b) {
    return a + b;
}

// Unit-тест
test('should return sum of two numbers', () => {
    expect(sum(2, 3)).toBe(5);
    expect(sum(-1, 1)).toBe(0);
});

2. Тестирование граничных условий (Boundary Testing)

Анализ поведения на краях допустимых диапазонов. Часто ошибки возникают именно здесь.

  • Минимальные и максимальные значения: пустые строки, нули, максимальные числа (e.g., Number.MAX_SAFE_INTEGER).
  • Крайние индексы массива: первый (0) и последний (array.length — 1) элементы.
  • Пограничные состояния: переход через ноль, работа с null или undefined.

Пример:

function getFirstElement(array) {
    if (!Array.isArray(array) || array.length === 0) {
        throw new Error('Invalid or empty array');
    }
    return array[0];
}

test('handles boundary conditions for array', () => {
    expect(() => getFirstElement([])).toThrow('Invalid or empty array');
    expect(getFirstElement([42])).toBe(42);
    expect(getFirstElement([1, 2, 3])).toBe(1);
});

3. Тестирование негативных сценариев (Error Path)

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

  • Неверный тип данных (строка вместо числа).
  • null или undefined аргументы.
  • Некорректный формат данных (не JSON строка).
  • Нарушение предусловий (деление на ноль).

Пример:

function divide(a, b) {
    if (typeof a !== 'number' || typeof b !== 'number') {
        throw new TypeError('Arguments must be numbers');
    }
    if (b === 0) {
        throw new RangeError('Division by zero');
    }
    return a / b;
}

test('throws errors on invalid input', () => {
    expect(() => divide('10', 2)).toThrow(TypeError);
    expect(() => divide(10, 0)).toThrow(RangeError);
});

4. Тестирование асинхронного кода

Проверка функций, возвращающих Promise или использующих async/await. Важно убедиться, что тест дожидается завершения асинхронной операции.

Пример:

async function fetchUserData(userId) {
    // Имитация асинхронного запроса
    const response = await Promise.resolve({ id: userId, name: 'John' });
    return response.name;
}

test('resolves with user name', async () => {
    await expect(fetchUserData(1)).resolves.toBe('John');
});

5. Тестирование с использованием моков (Mocking)

Для изоляции тестируемого модуля от его зависимостей (внешние API, базы данных, файловая система) используются моки, стабы или шпионы. Это позволяет:

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

Пример мокинга модуля с помощью Jest:

// users.js
export async function getUserFromAPI(id) {
    // Реальный HTTP-вызов
}

// userProcessor.js
import { getUserFromAPI } from './users';
export async function processUser(id) {
    const user = await getUserFromAPI(id);
    return `User: ${user.name}`;
}

// userProcessor.test.js
import { processUser } from './userProcessor';
import { getUserFromAPI } from './users';
jest.mock('./users');

test('processUser formats name correctly', async () => {
    // Мокируем зависимость
    getUserFromAPI.mockResolvedValue({ id: 1, name: 'Alice' });

    const result = await processUser(1);
    expect(result).toBe('User: Alice');
    expect(getUserFromAPI).toHaveBeenCalledWith(1); // Проверка вызова
});

6. Тестирование состояния и поведения

  • Состояние (State-based): Проверка, что после выполнения метода объект перешёл в ожидаемое состояние (значения полей изменились корректно).
  • Поведение (Behavior-based): Проверка взаимодействия между объектами — какие методы были вызваны, с какими параметрами и сколько раз. Используется при тестировании с моками.

Ключевые принципы хороших юнит-тестов (FIRST)

  • Fast: Должны выполняться быстро.
  • Isolated: Тестируют одну функциональность, изолированы от окружения и других тестов.
  • Repeatable: Результат детерминирован и не зависит от внешних факторов.
  • Self-validating: Тест сам определяет успех/провал (assertions).
  • Timely (или Thorough): Пишутся своевременно (часто до кода — TDD) и покрывают ключевые сценарии.

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

Расскажи про стандартные сценарии тестирования Unit тестами | PrepBro