Что же такое юнит-тестирование?

Что же такое юнит-тестирование?

Anton Ermak

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

Эта тотальная беспомощность крепко засела в умах разработчиков, а многие компании говорят об этом как о "фиче" (мы не тестируем наш код, а аккуратно выкладываем, страхуясь с помощью дополнительных процедур). Действительно, если речь не идёт о программировании медицинских томографов, то ошибки чаще всего простительны и их исправление может стоить не так дорого. Хотя программу без тестов часто бывает понять очень сложно разработчику из соседнего отдела.

Я всегда видел в этом что-то неправильное. В воздухе постоянно висит вопрос - насколько программирование в наши дни является инженерной специальностью? Ведь строители не говорят: "– эй, мы уже строили небоскрёбы, давайте нам кирпичи и мы начинаем уже завтра!". Процесс строительства состоит из различных стадий, в том числе стадия испытания (мосты, высотные здания) до ввода в эксплуатацию. Инженеры!

Почему же мы не умеем тестировать? Думаю, что главный ответ - мы тестируем имплементацию, а не поведение.

Подсказка о создании теста для класса

Отчасти нам об этом говорит IDE. "– <username>, ты сделал класс? Давай я сгенерирую для тебя класс для тестов! – Да, спасибо. Удобно!".

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

Под юнит-тестированием не имеется ввиду, что тестируется один метод или один класс!

Что мы делаем, если пишем тест для каждого класса? Ответ: огромное количество моков (aka стабы). Это в свою очередь ведёт к тому, что взаимодействие классов фиксируется намертво и теперь нельзя просто добавить новые аргументы, изменить выходное значение без перенастройки моков. Мы злимся, тратим время и иногда даже удаляем тесты. Нам кажется, что тесты – это оковы, которые не позволяют нам решать задачу быстро.

Классы образуют либо агрегацию, либо композицию.

Рассмотрим примеры.

  1. Логика расчёта процента по кредиту (пишем тест для InterestRateCalculator) чаще всего является сложным алгоритмом, где используется: данные заёмщика (скоринг), текущая финансовая ситуация, страна, цель кредита и так далее. Можно представить, что изначально логика могла быть написана просто, а со временем усложнилась, но всё ещё является одним целым. Это композиция.
    Реализация будет скорее сильно связной, вполне может часто меняться в зависимости от новых бизнес-требований. Здесь имеет смысл тестировать поведение через один фасад. При таких тестах, мы можем менять внутреннюю структуру без ограничений. Наши тесты будут нам помогать.
  2. Процесс покупки товара в интернет-магазине (пишем тест для PaymentAPI). Здесь есть стадии: оплата (разные методы в зависимости от покупателя, города и т.д.), доставка (размер товара, пожелания клиента и т.д.), расчёт скидки для следующей покупки, нотификация об успешном заказе. По-сути это разнородные системы, мы их агрегируем.
    Можно предположить, что интерфейсы каждой системы отдельно меняться будут не часто, поэтому для тестирования PaymentAPI можно использовать моки как раньше. Это вполне нормально.
https://medium.com/devschacht/node-hero-chapter-9-68041507aec

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

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

Литература

  1. https://www.youtube.com/watch?v=ecIWPzGEbFc - будущее программирования от Bob Martin. О важности тестирования, программировании как инженерии.
  2. Агрегация и композиция (с 25 минуты) от Sandro Mancuso - https://www.youtube.com/watch?v=KyFVA4Spcgg в контексте архитектуры. Рекомендую посмотреть запись полностью.
  3. Jakub Nabrdalik раскрывает смысл "фасадов" https://www.youtube.com/watch?v=2vEoL3Irgiw Рекомендую после просмотра предыдущего видео.
  4. https://www.martinfowler.com/bliki/UnitTest.html - Martin Fowler рассуждает про юнит-тестирование и каким оно бывает. Коротко и по делу.

Report Page