Unit-тестирование — критически важный этап разработки ПО и камень преткновения для джунов. Начинающие разработчики не всегда понимают, почему тестирование должны делать они, ведь для этого есть специальные отделы. И это отличает крутого спеца от рядового — ответственность. В первую очередь за то, что вы делаете, каким передаете продукт для дальнейшей разработки. В этой статье мы расскажем вам про Unit-тестирование, для чего оно нужно и почему важно.
Вот скажи, оно мне надо? Это лишняя работа!
При написании кода неизбежно будут ошибки. И неважно насколько вы крутой разработчик и какую должность занимаете: Junior, Middle или Senior. Опытного программиста отличает не количество ошибок, а умение их быстро находить и исправлять. При создании какого-либо приложения, всегда прописываются методы и функции. Unit-тестирование создано для того, чтобы модулями проверять каждую из таких функций или методов. В итоге, хороший код — тот, который весь покрыт unit-тестами. Это значительно сокращает время на поиск ошибок, а значит и влияет на скорость разработки в положительную сторону.
Кстати, это будет полезно и при написании pet-проектов для собесов, что само по себе очень крутая практика. Допустим, мы пишем функцию, которая считает сумму всех бутылок в холодильнике с колой. Их должно быть 240 в одном холодильнике и 240 в другом. Всего 480 бутылок с чудо-жижей из каналов в Half-Life 2. Unit-тест, который я напишу для этой функции, должен проверить, а правильно ли выполнена функция, и получу ли я ожидаемый ответ — 480. Если результат функции равен тому, что заложен в тесте — ура, всё работает корректно. Можно открыть холодос и бахнуть бутылку эликсира за это.
И теперь представим, что нам нужно посчитать не сумму бутылок колы в двух холодильниках, а целый магазин товаров для гиков, где стоит этот холодос. Есть полки с модельками, с мерчом, и каждый из них ещё разбит по вселенным. И тут можно понять, что проверять каждый из них вручную, просто подряд просматривая каждую из полок — дело вот вообще неблагодарное. Проще сразу написать unit-тесты, которые проверят, а правильно ли посчитано количество фигурок Примархов из Вахи или плащей Бэтмена.
Ну и как я это сделаю?
Собственно, а как создать то эти самые Unit-тесты? Существует множество библиотек для проведения unit-тестов на Java. Вот лишь некоторые из наиболее популярных:
JUnit — наиболее распространенная библиотека для unit-тестирования. Она предоставляет аннотации, методы и классы для тестирования кода.
TestNG — другая популярная библиотека для тестирования Java-кода. Она обладает расширенными возможностями для тестирования, такими как группировка тестов и тестовые параметры.
Mockito — популярная библиотека макетирования объектов для Java. Она позволяет создавать фиктивные и макетные объекты для тестирования кода.
PowerMock — расширенная библиотека макетирования объектов для Java. Она позволяет создавать макеты статических методов, конструкторов и т. д.
AssertJ — библиотека, позволяющая писать более читабельные и удобные тесты, чем стандартные Assert-методы. Это только некоторые из множества библиотек, доступных для проведения unit-тестов на Java.
Рассмотрим три самые популярные из этого списка: JUnit, Mockito и TestNG. Они используются чаще всего, как подсказывает практика, и наиболее удобны для написания тестов, т.к. понятны как новичкам, так и более прошаренным за код дедам индустрии.
JUnit
JUnit является одним из наиболее популярных инструментов для тестирования Java-приложений и широко используется в разработке программного обеспечения в различных областях, включая веб-приложения, мобильные приложения и т.д.
JUnit — это библиотека для тестирования программного обеспечения (unit-тестирования) на языке Java. Она позволяет создавать и выполнять тесты, а также проверять результаты работы программы.
JUnit предоставляет собой набор аннотаций (@Test, @Before, @After и т.д.), которые помогают определить тестовые методы и методы инициализации и завершения тестов. JUnit также обеспечивает удобный способ создания тестовых наборов (test suites), которые дают возможность объединять несколько тестовых классов или методов в единый тест. Ну и используется JUnit во всех языках, что поддерживают объектно-ориентированный подход, от Java до Python'а.
Mockito
С помощью Mockito можно создавать моки различных классов и интерфейсов, устанавливать для них поведение и проверять, вызывались ли на них определённые методы с определёнными параметрами. Mockito позволяет легко и удобно создавать моки объектов, игнорируя их реальную реализацию, что позволяет лучше контролировать процесс тестирования и ускорить разработку.
Mockito также предоставляет большой набор методов и классов для настройки мок-объектов и проведения более гибкого тестирования. Например, она позволяет установить ожидаемые значения для конкретных вызовов методов, вызывать методы мок-объектов с определёнными аргументами и настраивать классы и интерфейсы на выполнение конкретного поведения в процессе тестирования.
Mockito широко используется в интеграционном и модульном тестировании Java-приложений. Его гибкость и удобство давно зарекомендовали данную библиотеку среди Java-разработчиков, и давно используется даже в очень масштабных приложениях.
TestNG
TestNG — это фреймворк для функционального тестирования Java-приложений. Он предоставляет мощный, гибкий и расширяемый набор возможностей для написания и запуска тестовых сценариев. Основные преимущества TestNG включают в себя:
Поддержка аннотаций: TestNG предоставляет набор аннотаций для создания тестовых сценариев, таких как @Test (для обозначения тестового метода), @BeforeSuite (для перед выполнением всех тестов) и @AfterMethod (для очистки ресурсов после каждого выполняемого метода).
Гибкие конфигурационные параметры: TestNG позволяет конфигурировать тестовый запуск с помощью xml-файлов, что очень удобно при работе с большим числом тестов.
Группировка тестов: TestNG позволяет группировать тесты по своим функциональным особенностям и запускать их отдельно от других групп.
Поддержка параллельного выполнения: TestNG позволяет запускать тесты параллельно, что ускоряет время их выполнения.
Генерация отчетов: TestNG предоставляет мощный механизм генерации отчетов, что помогает в легкой и быстрой отладке найденных ошибок в программах.
Бесплатный и открытый исходный код: TestNG разработан на языке Java и распространяется под лицензией Apache, что даёт возможность использовать его бесплатно и изменять исходный код.
TestNG является отличным инструментом для функционального тестирования Java-приложений. Он обладает гибкостью, расширяемостью и простотой использования. Этот фреймворк позволяет создавать тесты, конфигурировать их, группировать и запускать параллельно и генерировать отчеты о результате выполнения. Это все позволяет ускорить и улучшить процесс разработки и сборки ПО.
Ну и что в итоге то?
В конце концов мы приходим к тому, что unit-тестирование и правда мастхэф для разработчика любого абсолютно уровня, потому как от этого зависит и вся разработка в целом, в общем-то.
То есть, проверяя свой код, вы закрываете сразу несколько проблем:
исключаете или минимизируете количество ошибок в том, что написали;
учитесь проверять сделанную работу, что всегда важно;
передаёте более качественный “продукт” своим коллегам;
банально качаете свои скиллы, набирая всё больше строк код и подмечая ошибки, которые чаще всего допускаете при его написании.
Unit-тестирование позволяет разработчику убедиться, что компонент работает правильно и не содержит ошибок, а также облегчает поиск и устранение ошибок в случае их обнаружения. Отдельные модули, прошедшие unit-тестирование, могут быть интегрированы в более крупные модули и тестироваться вместе с ними. В целом, unit-тестирование помогает повысить качество и надежность программного обеспечения и ускорить процесс его разработки.
Если вы нашли этот материал интересным и полезным для себя будем рады вашим реакциям!
scome
Сильное заявление. Проверять я его, конечно, не буду
DasMeister
Это же почти дословная цитата, цитаты из вступления к книге "Чистый код", Мартина. Удивительно, что тимлид не успел проверить это весьма обыденное заявление.
scome
Рад за ваши столь доскональные знания такого значимого труда.
В продолжение могу предложить изучить труд Хорикова «Принципы юнит тестирования» - не менее значимая книга, чем творения дядюшки Боба
Qwertovsky
Я проверял это на себе.
В итоге код тестов заметно превышает объем основного кода. В приложении тесты чаще падали не потому, что в логике ошибку я допустил. А потому что сами тесты переставали соответствовать новой логике.
Новый параметр на входе функции увеличивает количество тестов в два раза или больше. Зависит от вариаций, которые могут поступить на вход. Если параметр передается дальше в другой компонент, то и там тесты надо усложнять.
Со стороны отдельно метода кажется, что вариаций может быть много, и все надо протестировать. Но если посмотреть со стороны интерфейса пользователя, то набор входных данных может быть ограничен факторами, о которых бекенд разработчик не знает. То есть он будет писать лишние тесты.
При рефакторинге я удалил все юнит-тесты и переключился на интеграционные. Теперь все приложение можно рефакторить сколько угодно. И стек интеграционных тестов и самого приложения можно менять независимо. Лишь бы основной интерфейс оставался рабочим.
Если на проекте нет хорошего ТЗ, и работаете по аджайлу, то заниматься юнит-тестами дорого. Уже после первого тестирования нового функционала, могут решить все переделывать. Каждый спринт будете все тесты переписывать.
В таком случае тесты лучше добавлять на устоявшийся функционал, когда думаете, что кто-то может его легко поломать. Так как все нюансы не всегда очевидны.
qeeveex
Вы сейчас описали признак проблем в архитектуре приложения.
Мы работаем по аджайлу и у нас легко и быстро покрывается код unit тестами. Весь код делится на отдельные модули по SOLID и DDD.
Тесты тоже нужно сопровождать и именно из-за этого они должны быть максимально простыми.