TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3172 1.87K
День 2645. #ЗаметкиНаПолях
Тестовая Пирамида — Ложь (и Что Делать Вместо Этого). Начало

Автор оригинала: Milan Jovanović

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

Откуда взялась пирамида
Пирамида была популяризирована Майком Коном в 2009 году, когда интеграционные тесты означали общий сервер БД, нестабильный CI и 20-минутные сборки. Модульные тесты с моками были прагматичным компромиссом.

Этот мир ушёл в прошлое. С помощью Testcontainers можно быстро запустить PostgreSQL, Redis и RabbitMQ в новом контейнере для каждого тестового класса. Aspire Test Host идёт ещё дальше, подключая весь граф вашего приложения. Аргумент о том, что реальные зависимости слишком затратны, по сути, больше не актуален. Но рекомендации не обновились.

Ошибка, которая меня убедила
Пару лет назад у меня был сервис с 94% покрытием модульными тестами. Все тесты были «зелеными». Но в один прекрасный день пользователь сообщил, что удаление учётной записи на самом деле не приводит к удалению его данных. Метод был проще некуда:
public async Task Handle(DeleteAccountCommand command, CancellationToken ct)
{
var account = await _repo.GetByIdAsync(command.AccountId, ct);
account.MarkAsDeleted();
}

Да, в нём забыли вызвать SaveChangesAsync(). И тест для этого случая просто не был написан. Можно проверить, был ли вызван SaveChangesAsync в методе с помощью мока. Но в кодовой базе, где этот тест — один из сотен тестов обработчиков, каждый со своей настройкой мока и своим списком проверок, про это просто забыли. И покрытие тестами показывало, что всё в порядке.

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

В чём на самом деле хороши модульные тесты
Модульные тесты оправдывают себя, когда логика нетривиальна, чиста (без операций ввода-вывода, без асинхронности, без случайности) и сложна для проверки от начала до конца. Это вариантов кода вроде объектов-значений и сложных моделей домена, расчётов цен и налогов, парсеров, мапперов, сериализаторов и т.п.

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

Что же делать вместо этого?

Окончание следует…

Источник:
https://www.milanjovanovic.tech/blog/the-test-pyramid-is-a-lie-and-what-i-do-instead
  • 👍 7
More from @netdeveloperdiary
  1. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  2. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  3. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  4. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  5. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →