Модульное тестирование проводят сразу после написания кода. Проверить работу кнопки в готовом приложении не получится, потому что на неё уже влияют другие модули.
Если пропустить этап юнит-тестирования, в следующий раз не получится понять, что именно вызвало ошибку: какой-то из модулей или неправильно настроенная интеграция между ними. Придётся разбираться, тратить время и всё равно тестировать отдельные юниты.
Для примера представим автомобиль. Его «юниты» — это двигатель, подача бензина, зажигание. Можно проверить их по отдельности и ещё до сборки увидеть поломки и починить их. А можно собрать автомобиль, не протестировав юниты, — и он не поедет. Придётся всё разбирать и проверять каждую деталь.
Сквозные (end-to-end) тесты — тестирование работы большого количества юнитов вместе. Это может быть как всё приложение, так и конкретный сценарий, например поиск товара, его помещение в корзину, заказ и оплата.
Если сравнивать с другими тестами, у модульных есть следующие особенности:
● Можно провести сразу после написания кода. Программист пишет конкретный модуль и тут же его тестирует — не нужно ждать готовности других модулей или интеграций.
● Быстрее, чем другие тесты, так как охватывают только небольшую функцию. Часто один такой юнит-тест занимает всего пару миллисекунд.
● Не требуют серьёзной инфраструктуры, так как их выполнение не требовательно к вычислительным ресурсам.
● За счёт лёгкости и скорости юнит-тесты самые дешёвые.
● Разные юниты можно тестировать одновременно.
● Легко автоматизировать, так как при таких тестах нет имитации сценария пользователя — только проверка реакции кода на те или иные действия и данные.
● Просто посчитать, какой процент кода покрыт тестами.
Поэтому в пирамиде тестирования юнит-тесты стоят в самом низу — для экономии времени и сил их стоит проводить больше всего. В идеальном случае мы можем вообще обойтись только модульным тестированием проекта, то есть всего написанного кода — проверять только юниты, так как интеграция между ними предсказуемо работает правильно.
На курсе Практикума «Инженер по тестированию» мы разбираем разные виды тестов и отрабатываем их на реальных практических задачах. Вводный курс доступен бесплатно.
Разработчик пишет код конкретной функции — юнита.
Проверяет, чтобы функция была изолирована, то есть не вшита намертво в другие функции. Если вшита — переписывает её, чтобы вынести.
Если функции нужны реакции от других модулей, разработчик создаёт моки — заглушки, которые имитируют другие модули и взаимодействие с ними. Например, передают данные, на которые тестируемый юнит должен отреагировать.
После этого разработчик пишет тесты и исправляет ошибки.
После запускает юнит-тест в режиме покрытия и смотрит, все ли строки функции покрыты, то есть протестированы.
В итоге через пару итераций получается хороший протестированный код.
Но есть и другой подход — Test driven development. Его суть в том, что разработчики получают задачу и сначала пишут тесты, основываясь на принципах модульного тестирования: на проверке отдельных юнитов сразу после написания кода. И уже под эти тесты пишут код, стараясь избежать предполагаемых ошибок.
Инструменты для проведения юнит-тестов. Например, если пишете на javascript, существует пакет jest. Он позволяет быстро делать заглушки, содержит инструменты для проверки покрытия, позволяет запускать тесты в разных режимах, в том числе в многопоточном.
Для других языков программирования тоже существуют свои инструменты для создания юнит-тестов — JUnit , Mockk, robolectric, пакет unittes для Python.
Читать также: