Как писать код, который не ломается: гайд по TDD от эксперта Эйч Навыки
Владислав Гайденко, эксперт Эйч Навыки и бэкенд-разработчик в Авито, рассказывает, как TDD помогает избежать ловушек нестабильного кода, сократить время на исправление багов и контролировать процесс разработки.
998 открытий8К показов
Разработка ПО редко идет без приключений: требования меняются, ошибки всплывают в самый ненужный момент, а исправления одного бага, как смещение таблицы в Word, может сломать вообще всё. К счастью, есть подход TDD (Test-Driven Development), который минимизирует эти риски.
Влад Гайденко, ментор Эйч Навыки и бэкенд разработчик в Авито, где он с командой разрабатывает платформу «Гарантии запчастей» в рамках Авито Авто, расскажет, как применять TDD без стресса и писать код, который не будет ломаться.
Что такое TDD
TDD (Test-Driven Development) часто считается крайне сложным подходом, но на самом деле все довольно просто. Представьте, что вы строите дом: вы же сначала нарисуете план, и только потом начнете строить, верно? В TDD все работает точно так же, только с кодом: сначала мы пишем тесты, описывающие, как должен работать наш код, а потом уже пишем сам код, чтобы эти тесты проходили.
Другими словами, здесь полностью меняется логика разработки: обычно мы пишем код, потом тестируем и финалим баги. В TDD все идет от обратного — схема примерно такая:
- Определяем функциональность, которую нужно реализовать. Условно: вам нужно при запросе «300» возвращать «спартанцев».
- Под эту функциональность пишем тест — в нем вы описываете, как должна работать будущая программа. Спойлер: при запуске тест провалится, потому что тестировать пока нечего.
- Пишете самый простой (даже «глупый») код, после которого тест просто перестанет выдавать ошибку.
- Если тесты больше не падают, поздравляем, вы великолепны. Теперь можно делать рефакторинг кода и пилить «по красоте».
Да, это самый банальный пример — в реальности модулей могут быть тысячи, и под каждый из них, конечно, нужно писать тест.
Почему TDD работает
Давайте разберем на конкретном примере. Представьте, что мы разрабатываем функционал расчета стоимости доставки. Начав с написания тестов, мы сразу видим важные моменты:
- Как считать стоимость для разных типов товаров (легких, тяжелых и хрупких)
- Как учитывать расстояние до адреса доставки
- Как применять скидки и акции
Написав тесты для этих сценариев, мы уже на старте проекта знаем, что наше решение будет учитывать все важные детали. Круто, правда?
Что это реально дает
Когда начинаешь работать с TDD, понимаешь, насколько это мощный инструмент. Ниже о его суперсилах.
Надежды как швейцарские часы
Допустим, через какое-то время нам нужно добавить новый тип доставки — курьером. Без тестов мы бы постоянно переживали: «А вдруг что-то сломалось?» С тестами же мы можем спокойно вносить изменения, зная, что если что-то пойдет не так, тесты нас предупредят.
Актуальная документация
Тесты становятся отличной «живой» документацией. Новый разработчик в команде? Просто покажите ему тесты, и он быстро поймет, как все работает. Это намного удобнее, чем читать многостраничные документы, которые часто устаревают.
Экономят время на поиске багов
Помните ситуации, когда нужно срочно исправить ошибку, а вы не знаете, где искать? С TDD все проще: написал тест, воспроизводящий проблему, исправил код, убедился, что тест проходит — и готово!
Где TDD реально полезен
Отлично подходит для:
- Бизнес-логики: все эти CRUD-операции, валидации, обработка ошибок — самое то!
- Утилитных модулей: математические операции, форматирование данных, работа с коллекциями
Где лучше подумать дважды:
- Интеграция с внешними сервисами
- Работа с файлами и сетью
- Настройка окружения
С чего начинать TDD
Освоить TDD действительно несложно, но начинать нужно не с кода, а с правильной постановки задач в системе управления проектами, например, в Jira.
Ключевой момент — это включение в описание задач четких критериев приемки, которые определяют, когда задача будет считаться выполненной. Эти критерии должны быть сформулированы представителями бизнеса, продакт-менеджерами или другими заинтересованными сторонами, близкими к требованиям пользователей.
Например, для задачи по добавлению нового типа товара в доставку с признаком акциз:
- Моторные масла с типом акциз до 5 л включительно объема доступны для доставки
- Тип доставки «Лошадью»
- Логистическая компания «Рога и копыта»
Такие четкие критерии приемки становятся основой для написания тест-кейсов, которые будут проверять, что реализованное решение действительно соответствует ожиданиям.
Когда задача сформулирована с критериями приемки, разработчик вместе с QA-инженером могут начать создавать тест-кейсы прямо в Jira. Эти тест-кейсы будут отражать различные сценарии использования, которые должны быть протестированы.
Например, для задачи по добавлению нового типа товара, тест-кейсы могут быть такими:
1. Проверить, что типы товара доступны для доставки в «Лошадью» в «Рога и копыта»:
- моторные масла
- с акцизой
- объем (1, 2, 5 л)
2. Проверить, что типы товара недоступны для доставки «Лошадью» в «Рога и копыта»:
- моторные масла
- без акцизы
- объем (1, 2, 5 л)
Эти тест-кейсы становятся основой для написания автоматизированных юнит-тестов в коде. Разработчики могут ориентироваться на них, когда пишут реализацию, и проверять, что их код действительно соответствует ожиданиям.
Очень важно, чтобы тест-кейсы, определенные в Jira, просматривались на встречах по оценки задач (PBR). Это позволяет:
- Убедиться, что тест-кейсы действительно отражают все важные критерии приемки задачи.
- Согласовать с продакт-менеджером и другими заинтересованными сторонами, что эти тест-кейсы полностью покрывают требования.
Такой подход гарантирует, что разработчики пишут код, ориентируясь на ожидания бизнеса, а не просто на свое собственное понимание задачи.
В итоге, начав с правильной постановки задач в Jira и определения тест-кейсов, разработчики получают надежный фундамент для применения TDD. Это помогает создавать качественный код, который точно соответствует требованиям пользователей.
Как писать тесты еще лучше
Используйте принцип «Светофора»:
- Красный: пишете тест, он падает
- Зеленый: пишете код, тест проходит
- Рефакторинг: улучшаете код, тесты все еще зеленые
Делайте тесты читаемыми:
- Давайте понятные названия
- Структурируйте код теста
- Используйте вспомогательные функции для часто повторяющихся действий
Вот пример плохого теста:
Здесь неясно, что конкретно проверяет тест. Название теста ничего не говорит, а использование магических чисел усложняет понимание. Это приводит к путанице, особенно если тесты придется читать или модифицировать спустя время.
А вот хороший пример:
Почему это хороший пример?
- Понятное название теста: TestCalculateDelivery сразу дает понять, что мы тестируем функцию расчета стоимости доставки. Т
- абличный формат: использование таблицы позволяет легко добавлять новые тестовые случаи без дублирования кода.
- Понятные имена переменных: каждая переменная имеет четкое назначение, что упрощает чтение и сопровождение теста.
- Параметризация тестов: за счет табличного подхода мы избегаем избыточного кода, проверяя несколько сценариев в одном тесте.
- Табличные тесты — это отличный способ поддерживать чистоту и масштабируемость тестов, особенно когда сценарии похожи, но параметры различаются.
Типичные сложности и как с ними справиться
«Это же долго!»
Да, поначалу придется потратить больше времени. Но это как инвестиция: сейчас вложишь время, потом получишь в разы меньше багов и более быстрое внесение изменений.
«Не знаю, с чего начать»
Начните с простого! Возьмите небольшую задачу и попробуйте написать для нее тесты. Используйте существующие тесты как примеры. Постепенно вы найдете свой стиль и ритм.
«У нас legacy-код»
Начните с нового кода! Не пытайтесь сразу покрыть тестами весь старый код. Добавляйте тесты постепенно, когда прикасаетесь к старому коду для внесения изменений.
Подготовка проекта
Например, в Go есть отличные инструменты для тестирования. Я рекомендую:
- Стандартный пакет testing для базового функционала
- Testify — набор полезных ассертов и мок-объектов, лично используем на проекте
- Ginkgo — BDD-стиль написания тестов
- Встроенные инструменты для измерения покрытия кода:
TDD — это не какая-то магия, а просто удобный инструмент, который помогает писать более качественный код. Начните с малого, и вы увидите, как постепенно ваш код становится надежнее, а работать над проектом — приятнее.
Удачи в практике TDD! А если у вас остались вопросы — велком в комменты.
А вы используете TDD в своих проектах?
Да, это лучшее, что придумало человечество. Наконец-то избавились от миллиона багов
Ага, конечно, а еще что?
998 открытий8К показов