Как, используя TDD, сократить время разработки

Как, используя TDD, сократить время разработки


Автор
Павел
Павел
Ведущий веб-разработчик

TDD или Test Driven Development - это разработка через тесты: сначала пишутся интеграционные тесты, в которых детально описан будущий функционал. А новые функции разрабатываются на основе этих тестов.

Недавно осознал, что работаю по TDD 5 лет. Так сложилось, что на первых моих проектах TDD использовался по умолчанию, поэтому пришлось привыкать и учиться. Тогда о TDD уже говорили много и часто. Однако, в реальности ее мало кто использовал.

Пришло время поделиться опытом, когда надо и не надо использовать TDD, чтобы получить максимум пользы.

Зачем использовать

  1. Ускоряет разработку. Пока разработчики привыкают к написанию тестов, работа будет идти медленнее. Когда привыкнут, разработка ускоряется;
  2. Высокое покрытие функционала тестами. На каждый функционал я пишу 20-25 тестов, чтобы охватить все возможные варианты его использования;
  3. Меньше времени на отладку. Обычно отладка начинается, когда основной функционал уже сделан. Здесь мы отлаживаем заранее концепцию функционала, пока пишем тесты.

Как это работает

Путь любого кода при разработке по TDD проходит 3 стадии:

  • Красная стадия: пишем тесты. Первый прогон тестов будет всегда возвращать ошибку, потому что интерфейс, который они проверяют, не готов. Каждый тест должен переживать в своей жизни хоть одно падение. Как минимум, сразу после написания. Как говорят адепты TDD: «Я не могу доверять тесту, который никогда не видел упавшим». Упавший тест обратит на себя внимание, и вы задумаетесь о правильности реализации функционала или самого теста.
  • Зеленая стадия: разрабатываем функционал и заново проверяем. Наша задача - добиться того, чтобы тест стал зеленым. Так мы понимаем, что функционал разработан верно. Важно, чтобы тест минимум один раз упал и минимум один раз прошёл. Легко ошибиться и написать тест, который всегда падает или всегда проходит. А вот тест, который и падал и проходил, явно проверяет какую-то логику. После этого можно считать, что функционал работает верно.
  • Рефакторинг. Рефакторим конкретную задачу, потому что уже уверены, что у нас рабочий код теста. Просто пишем логичный и чистый код для нашего проекта.
TDD.png

Где это работает

Выбор TDD зависит от:

  1. Команды и человека, который ставит и принимает задачи (назовем его заказчик).
  2. Внутренних процессов на проекте. Например, в команде не используется непрерывная интеграция. Здесь использовать TDD не стоит, потому что разработчик не будет каждый раз запускать тесты перед тем, как залить код в репозиторий. Ему станет лень в итоге.

Есть критерии, по которым вы сможете определить, что TDD сработает:

  • В проекте чётко описана структура интерфейсов, например, используются JSON-API или REST-API. Наша задача - ускорить разработку продукта. Когда есть четкая структура, программист не придумывает структуру сам. Если четкости нет, программист продумывает структуру интерфейсов, а его видение может не совпасть с тем, что в голове у заказчика. Поэтому, если на проекте есть продуманная структура API, пишите тесты до кода;
  • В проекте однотипный подход к реализации интерфейсов, т.е. логика и порядок работы над разными сущностями одинаков или сильно похож. Перед написанием тестов мы организуем в тестовом окружении требуемые данные. Если на проекте есть определённый подход к реализации интерфейсов, вы можете спокойно применять один шаблон и экономить время на написание тестов. Если единого подхода в разработке нет, придётся для каждого теста создавать собственные условия перед запуском. На это уйдет столько же времени, сколько при обычной разработке, поэтому использование TDD не принесет пользы;
  • Задачи ставятся в стиле: одна подзадача - один тест. Обычно такие задачи ставит заказчик-технарь. Заведите систему: внутри задачи каждая подзадача - это один тест. Тогда разработчики спокойно пишут тесты, которые описывают подзадачи, потом реализацию, и тесты постепенно становятся зелёными. Если в каждой подзадаче можно вычленить несколько тестов, процесс не выиграет по времени по сравнению с обычной разработкой;
  • Есть высокоуровневый тестовый фреймворк с поддержкой интеграционных тестов на технологии, которая используется на проекте. Альтернативный вариант: абстрагированный от реализации тестовый фреймворк на другой технологии. Весь мой TDD - это Ruby проекты. Здесь я использую средства тестирования RSpec, Minitest, Capybara. Тесты должны быть абстрагированы от реализации, поэтому не важно, какой инструмент вы выберете. RSpec + Capybara можно применять на любом проекте, который имеет HTTP-интерфейс. Лучше, если такой инструмент есть в вашем языке. Так программисту не придется переключать контекст во время разработки;
  • В команде нет отдельных тестировщиков. Если в команде есть тестировщики, тесты должны писать именно они. В итоге теряется главное преимущество TDD - «ментальная связь программиста с функционалом», ведь тесты пишет другой человек. Чтобы TDD принес пользу, тесты должен писать программист.

TDD нужен обязательно, если программист пишет API, которая возвращает JSON на фронтэнд. Если программист пишет API без TDD, проверять «глазами» JSON очень долго. Чем дольше проверяет, тем больше ошибок и тем дольше их потом исправлять. Когда тесты написаны, они автоматически проверяют JSON на ошибки. Заранее написанные тесты помогут программисту проверять JSON на выходе. В итоге разработка идет быстрее.

Где это не работает

TDD - не панацея и не универсальное решение. Для каких-то случаев он подходит, а где-то может навредить. Если TDD не подходит для проекта, он помешает и замедлит разработку. В итоге разработчики начинают считать, что:

  1. TDD применим только для продуктовых компаний;
  2. У нас нет подходящего стека технологий для TDD;
  3. Методология не работает;
  4. Можно сделать только на backend;
  5. В нашей предметной области не работает.

Чтобы такого не произошло, «приценитесь» к TDD перед внедрением. Не используйте его, если:

  1. Задачи ставятся без должной проработки. Задачи ставит не технарь и отдает продумывание сценариев программисту. В таких случаях писать тесты в начале - риск потратить на разработку больше времени. Например, есть задача «нужна форма регистрации. Сначала много полей, потом аккаунты в соцсетях». Разработчик сделал страницу, на которой сверху располагались поля, а снизу были кнопки соцсетей. Оказалось, что заказчик хотел трехступенчатую регистрацию: 1 - фамилия, имя; 2 - аккаунты соцсетей; 3 - дополнительная информация. Нужно переделывать и функционал, и тесты - в два раза больше бесполезной работы.

    Так увидел заказчик Регистрация. Шаг 1 Регистрация. Шаг 2 Регистрация. Шаг 3


    Так подумал разработчик
    Регистрация
    Здесь лучше писать тесты после утверждения заказчиком функционала;
  2. Непроработанная заранее бизнес-логика. Разработчик до начала разработки точно не знает, как будет работать функционал. В моей практике было 3 BI системы для внутренних нужд клиентов. Во всех проектах требования к ним менялись ежедневно. Заказчики не всегда понимали, какие именно метрики нужны, поэтому требования уточнялись после разработки. Функционал нужно делать максимально быстро, чтобы заказчик видел что не так и предлагал изменения. Если пытаться писать сначала тесты, то заказчик увидит функционал позже, и сроки будут постоянно сдвигаться;
  3. Сложные вычисления или большие нагрузки. Если в проекте сложные вычисления, результат этих вычислений сложно предсказать заранее на этапе написания теста. Например, вы собираете и анализируете тысячи данных о пользователях, чтобы выяснить, какие услуги популярнее. Результат в тестах нужен, потому что с ним будут сравнивать реализацию.

Применять или не применять TDD зависит от ответственного за проект и ценностей команды. Для многих писать тесты до разработки - это разрыв шаблона. Как так? На самом деле, нет ничего страшного.

Напомню:

  • тесты должны покрывать не код, а функционал;
  • тесты должны быть абстрагированы от реализации;
  • тесты должны исполняться в своём собственном окружении.

TDD поможет не только повысить осознанность работы программиста (он же продумывает функционал заранее и ждет, что тесты «упадут»), но и сократить время разработки.

Почувствуйте наш подход и повторите
успех наших клиентов

Напишите нам
МАКСИМ БЕЛЯКОВ
МАКСИМ БЕЛЯКОВ
СЕРГЕЙ ИСАКОВ
СЕРГЕЙ ИСАКОВ