Краткий конспект доклада TDD вверх ногами.

Автоматизированные тесты

Егор считает, что юниттесты - неотъемлемая часть работы программиста. Егор приводит в пример метафору про сетку безопасности, которую натягивают гимнасты для отработки своих трюков. Егор очень сомневается, что гимнасты не будут натягивать сеть по причинам, по которым некоторые разработчики отказываются писать тесты:

  • “У нас нет времени”
  • “У нас нет денег”
  • “У нас никогда и не было тестов (сети)”

Сеть безопасности дает гимнастам уверенность, что совершённые ошибки в тренировке не будут стоить здоровья и карьеры трюкачам. Как гимнаст, не имеющий сети под собой, боится рисковать, так и разработчик не будет экспериментировать при реализации новых фич, боясь сломать предыдущий функционал.

“У нас нет времени”

Егор считает, что эти причины довольно нерациональны. Наивно полагать, что написание тестов - это какая-то второстепенная работа, которую делают (если делают) в последнюю очередь “когда остается время”. По мнению Егор, разработчик не должен делить время на разработку и на тесты, потому что тесты - неотъемлемая часть разработки. Тесты - это “сеть безопасности”, которая уберегает разработчиков от появления новых критичных и повторных появлений старых.

Более того, Егор считает, что когда разработчики говорят, что у них нет времени на тесты, они просто не умеют писать тесты.

You just don’t know how!

Егор ссылается на свою статью Fools don’t write unit tests, где объясняет более подробно свою точку зрения.

“У нас нет денег”

Вторую причину также Егор ставит под сомнение. Вы никогда не услышите от гимнаста, что он не натянул сеть, потому что “это слишком дорого”. То же можно уверенно сказать и про строителей, которые используют сети для падающих людей и инструментов. Сравнение разработки софта и гимнастов со строителями имеет смысл, потому что часто баги в продакшене приводят к не меньшим потерям, а иногда даже и к краху всей компании.

Егор считает, что предлагать заказчику варианты “Разработка софта за N денег” и “Разработка софта с тестами за N+ денег” совершенно не имеет смысла, ведь заказчик выберет в большинстве случаев первый более дешевый вариант.

Мы построим вам здание без систем безопасности за один миллион долларов, а без них - за миллион двести.

Строители почти никогда не предложат такую сделку заказчику, так почему же разработчики предлагают. По мнению Егора, заказчикам нужно предлагать вариант разработки софта без тестов как гораздо более дорогой. Объяснить увеличение стоимости Егор предлагает тем, что команда разработки без тестов будут меньше экспериментировать и дольше тестировать. Это явление Егор называет “Fear driven development”.

“У нас никогда и не было тестов (сети)”

Эта причина однозначно нерациональна. Ее корень - неумение писать тесты.

TDD вверх ногами

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

  1. Разработчик пишет код
  2. Программмист передает его некоторому пользователю (в том числе и сам начинает им пользоваться)
  3. Пользователь (сам разработчик) находит баг
  4. Разработчик пишет фикс и юниттест для найденного бага.

И так по кругу. В качестве “пользователя” Егор имеет в виду и самого автора написанного кода, ведь когда разработчик пишет некоторую фичу, после завершения кодирования он приступает к ее дебагу в своей ветке. Иначе говоря, он начинает выступать в качестве первого пользователя собственного кода и сам начинает находить баги и фиксить их. В принципе, так и делают многие все разработчики, из них часть пишет тесты на свой код. Но чаще всего тесты пишут (если пишут) уже после того, как написан код и отловлены баги “первичной” разработки самим автором кода.

Идея Егора заключается в подходе написания тестов: он предлагает разработчикам после того, как он нашел баг в собственном коде в собственной ветке, остановить дальнейший дебаг, пока он не напишет фикс и как минимум один юниттест для него.

Cycle of tdd

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

Вопросы из зала

Есть ли исключение из правила “Пока не найдут дефекты, тестов не будет”, верно? Если так, то в случае разработки финансовых систем не лучше ли сначала написать тесты, чтобы не было багов на продакшене?

Ощущение, что автор вопроса не понял суть доклада и услышать только “пользователь находит баги”. Егор упомянул и самого разработчика как пользователя своего же кода, он не имел в виду, что только конечные пользователи репортят баги.

Егор согласен с задающим вопрос и также напоминает, что если система требует высокого качества, то и пайплайн релиза софта будет содержать этапы тестирования на препрод-окружениях автоматически и/или вручную. Так или иначе, баги будут отловлены еще до этапа деплоя релиза, если процессы построены верно. также не стоит забывать и о кодревью, на котором даже потенциальные проблемы могут быть отловлены.

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

Как вы решаете проблемы, что когда руководство видит, что код написан без тестов, и останавливает разработчика? Оно, допустим, говорит, что “отлично, код написан, бог с ними с тестами, мы тебя перебрасываем на следующий проект”.

В таком случае разработчик должен еще раз напомнить, чем чревата разработка софта без тестов, и если руководство принимает ответственность на себя за это, то разработчику беспокоиться об этом совершенно не нужно. Если руководство устраивает гимнаст, который периодически падает на пол, то пусть так, ведь они несут за это ответственность.

Часто разработка через тестирование принуждает разработчика писать код так, чтобы он был пригоден для тестирования. А если следовать вашему подходу, то может сложиться ситуация, когда код становится просто непригоден для тестирования.

Егор согласен с этим тезисом и считает, что непригодность какого-то кода к написанию тестов - это еще один из видов багов, который необходимо решать. Иначе говоря, разработчик написал спагетти-код и столкнулся с тем6 что тестить его почти невозможно. Егор считает, что это характеризует в первую очередь разработчика как профессионала: чем больше разработчик пишет код и тестов к нему, тем лучше он пишет этот код “по наитию” и “интуитивно”, принимая во внимание предыдущий опыт. Человек постоянно учится и улучшает свои навыки.

У профессионала код после первого этапа кодирования вряд ли будет непригоден для тестирования.

Полезные ссылки