Нужно ли покрывать тестами весь код проекта?

Ответ

Нет, стремиться к 100% покрытию тестами всего кода — контрпродуктивно. Цель тестирования — снижать риски и повышать уверенность в изменениях, а не достигать абстрактных метрик. Ресурсы следует направлять на тестирование наиболее важных и рискованных частей системы.

Что обязательно нужно тестировать (высокая отдача):

  • Бизнес-логика и доменные правила: Алгоритмы расчётов, валидация, сложные преобразования данных.
  • Критические пути (Happy Path): Основные сценарии использования приложения.
  • Сложные условия и ветвления: Код с множеством if/else, switch.
  • Интеграционные точки: Взаимодействие с базами данных, внешними API, файловыми системами (через абстракции).
  • Код, подверженный частым изменениям: Чтобы рефакторинг и новые фичи не ломали существующую функциональность.

Что можно не тестировать или тестировать минимально (низкая отдача):

  • Простые геттеры/сеттеры или свойства автореализации без дополнительной логики.
  • Шаблонный код, сгенерированный инструментами (например, DTO, части ORM).
  • Тривиальные мапперы или конвертеры, где связь между входом и выходом очевидна и прямолинейна.
  • Внешние библиотеки и фреймворки. Предполагается, что они уже протестированы своими разработчиками. Нужно тестировать интеграцию с ними, а не их внутреннюю работу.

Пример приоритизации:

// ВЫСОКИЙ ПРИОРИТЕТ для тестов: Сложная бизнес-логика.
public class DiscountCalculator
{
    public decimal Calculate(User user, Order order)
    {
        if (user.IsPremium && order.Amount > 1000)
            return order.Amount * 0.85m; // Скидка 15%
        if (order.Items.Count > 5)
            return order.Amount * 0.9m; // Скидка 10%
        return order.Amount;
    }
}
// Для этого метода нужны юнит-тесты, проверяющие все ветки условий.

// НИЗКИЙ ПРИОРИТЕТ для тестов: Простой маппер данных.
public class UserDtoMapper
{
    public UserDto MapToDto(User entity) => new UserDto 
    { 
        Id = entity.Id, // Прямое присваивание
        Name = entity.Name 
    };
}
// Тест для этого метода, по сути, будет дублировать его код, принося мало пользы.

Практическое правило: Стремитесь к 70-85% покрытия по branch/condition для ключевых модулей. Это обычно обеспечивает хороший баланс между надежностью и затратами на поддержку тестов. Качество тестов (их читаемость, поддержка и способность ловить реальные баги) всегда важнее процента покрытия.

Ответ 18+ 🔞

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

Это ж надо, реально, как с этими метриками заигрались! Цель-то какая? Чтобы когда ты код меняешь, у тебя сердце не ёкало, что всё нахуй развалится. А не чтобы какой-то циферки в отчёте достичь, которая начальнику понравится. Ресурсы-то не резиновые, понимаешь? Ты будешь месяц писать тесты к какому-нибудь тупому DTO, а в это время в самом ядре логики сидит баг, который на продакшене клиентов оставит без штанов.

Так, вот на чём надо концентрироваться, если не хочешь быть идиотом:

Что тестируем так, будто от этого зависит наша зарплата (потому что так и есть):

  • Ядро, блядь, бизнес-логики. Все эти алгоритмы расчёта денег, проверки, можно ли юзеру что-то сделать, сложные правила. Вот это вот всё, где мозг надо включать. Ошибка тут — это сразу пиздец и потеря бабла.
  • Основные сценарии. То, чем люди реально пользуются каждый день. Купил товар — получил чек. Загрузил файл — он сохранился. Вот эту прямую дорогу надо вылизать до блеска.
  • Лес из if-ов и else-ов. Видишь код, который похож на ёлку — сразу покрывай тестами все ветки. Потому что одна неохваченная — и какой-нибудь левый кейс вылезет в пятницу вечером.
  • Места, где мы лезем куда-то наружу. В базу, во внешний API, в файловую систему. Тут важно проверить не сам драйвер базы данных (его разработчики уже протестировали, будем надеяться), а то, как мы с ним работаем: правильные ли запросы шлём, корректно ли ошибки обрабатываем.
  • Код, который постоянно трогают. Если модуль каждый спринт правят три разных человека — без плотного кольца тестов там будет бардак. Тесты тут как бронежилет для разработчика.

А на что можно забить болт (или почти забить):

  • Глупые геттеры и сеттеры. Ну серьёзно, ты будешь писать тест, который проверяет, что UserName = "Вася" после присваивания равно "Вася"? Да ты издеваешься? Это же прямо в коде видно!
  • Шаблонный код, который сгенерировала IDE. ORM-сущности, какие-нибудь RecordDto. Тестировать это — всё равно что тестировать компилятор. Бесполезная трата времени.
  • Простые мапперы-копировальщики. Где просто поля из одной структуры в другую перекладываются один-в-один. Тест для такого будет точной копией самого метода — ни ума, ни пользы.
  • Чужие библиотеки. Наша работа — проверить, что мы используем их правильно, а не перепроверять, что функция Math.Sqrt() внутри себя работает. Это уже кто-то сделал за нас.

Смотри, вот тебе живой пример, чтобы в голове уложилось:

// ВНИМАНИЕ, ТРЕВОГА! ЭТО ТЕСТИРУЕМ В ПЕРВУЮ ОЧЕРЕДЬ.
// Тут же денежки считаются, ебать его в сраку! Накосячим — нам потом клиенты голову оторвут.
public class DiscountCalculator
{
    public decimal Calculate(User user, Order order)
    {
        if (user.IsPremium && order.Amount > 1000)
            return order.Amount * 0.85m; // 15% скидка
        if (order.Items.Count > 5)
            return order.Amount * 0.9m; // 10% скидка
        return order.Amount;
    }
}
// Для этого пишем кучу тестов: а что если премиум и сумма большая? А если не премиум, но много товаров? А если ни то, ни сё?

// А ЭТО... Да похуй, честно.
// Это просто перекладывание из одного кармана в другой. Ошибка тут может быть только если я с клавиатурой не дружу.
public class UserDtoMapper
{
    public UserDto MapToDto(User entity) => new UserDto 
    { 
        Id = entity.Id, // Ну что тут тестировать-то? Что равно равно?
        Name = entity.Name 
    };
}
// Писать тест для этого — это признать, что ты себе не доверяешь в написании одной строчки кода. Пиздец.

Вывод, блядь, простой: Гонись не за сотней процентов в отчёте, а за тем, чтобы твои тесты реально ловили косяки. Если у тебя в ключевых модулях 80% покрытия по ветвлениям — уже охуенно. Остальные 20% — это, как правило, какие-то левые кейсы или тот самый шаблонный код, париться над которым себе дороже. Качество важнее количества, запомни эту простую истину, а то так и будешь как дурак время тратить на ерунду.