Artem Zakharchenko, специалист по тестированию и автор библиотеки для тестирования MSW с 15К звезд на GitHub, поделился мыслями о Test Driven Development.

Вот правда о TDD (Test Driven Development).

TDD - это неправильная практика. Она всегда была неправильной. Она неправильна по определению. Ее главная заслуга - поощрение тестирования, но на этом все и заканчивается.

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

В большинстве случаев вы этого не знаете. Все разработчики, которых я знаю, не знают этого заранее. Я не знаю этого заранее. На самом деле, я могу потратить несколько дней на эксперименты, написание MVP, пока не начну немного понимать, какими должны быть части моей системы и чего я от них ожидаю.

Я не считаю TDD жизнеспособным подходом в быстро развивающихся системах, таких как веб. Он может иметь гораздо больше смысла при написании системного программного обеспечения, в котором очень мало что меняется от проекта к проекту. Это полная противоположность тому, что вы пишете в Интернете.

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

Я не придерживаюсь TDD. Это не значит, что я не пишу тесты. Я пишу много тестов. Я занимаюсь разработкой прототипов, итераций и тестов.

Прототип. Я даю своим идеям простор и позволяю им дышать, не слишком заботясь о тестировании на первых порах. Я экспериментирую, меняю вещи, ломаю вещи, ставлю себя на место пользователя и разрабатываю API, поведение и ожидания. Как я уже сказал, это может занять некоторое время.

Итерация. Я трачу это время на то, чтобы убедиться, что моя система имеет смысл и удовлетворяет предъявляемым к ней требованиям (которые сами по себе могут развиваться и менять то, зачем я это делаю).

Тестировать. Наконец, я пишу тесты. Это стало неотъемлемой частью моего рабочего процесса. Я не могу представить себе, что не пишу тесты.

Конечно, бывают исключения. Если я пишу простую функцию ввода-вывода, то не нужно тратить день на то, чтобы понять, что она делает, потому что это все, что она будет делать. Я могу написать для нее несколько модульных тестов с самого начала. Но большинство моих (и, я уверен, ваших тоже) работ - это не простые функции. Это сложная логика, на отладку которой требуется время. Если я буду неукоснительно следовать TDD, я буду тратить время на написание тестов, которые в итоге выброшу. Это бесполезно и не поможет мне обрести уверенность в том, что я создаю.

Не отчаивайтесь. Применяйте те практики, которые работают для вас (даже если это TDD, лишь бы вы не лгали себе!). Главное, что тестирование имеет значение. Оно всегда имело значение. Разработчики тестируют программное обеспечение с 80-х годов, я полагаю. Вы тоже должны! Я сделаю все возможное, чтобы показать вам, что тестирование может быть доступным и увлекательным.

Комментарии (15)



  1. joffer
    21.03.2024 07:42
    +2

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

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


    1. Anarchist
      21.03.2024 07:42

      Даже со спецификацией писать тесты впереди кода имеет смысл только для самого верхнего уровня (и лучше это сделать заказчику). Тесты на подкапотную реализацию писать имеет смысл только с частично готовым кодом.


  1. andrejbestuzhev
    21.03.2024 07:42

    В большинстве случаев вы этого не знаете. Все разработчики, которых я знаю, не знают этого заранее.

    А что вы тогда делаете? Кто вам за это платит? Я тоже так хочу.


  1. onegreyonewhite
    21.03.2024 07:42
    +5

    TDD в значительной степени подразумевает, что вы должны знать, как ведет себя система, еще до ее реализации. Вы должны знать, что вы делаете.

    В большинстве случаев вы этого не знаете. Все разработчики, которых я знаю, не знают этого заранее. Я не знаю этого заранее.

    Ужас. Я не хотел бы переходить на личности, но это прям даже звучит дико. Если вы не знаете что пишите, то как пишите? Методом научно-ненаучного тыка? По вдохновению правой пятки? Возможно с таким подходом TDD и правда мешать будет. Возможно проблема не в методологии.

    Смысл написания тестов до кода, что тесты проверяют функциональность, которая требуется. Если нет требований, то что конечно тесты не написать. Но говорить о вреде TDD просто потому что у вас процессы... ну мягко скажем не очень, как минимум глупо.


  1. GulDmitry
    21.03.2024 07:42
    +3

    В конце концов код и тесты должны быть написаны, последовательность тут не важна, это правда. Главное понимать, что тесты не менее важны чем код:

    • В вебе, энтерпрайзах чаще всего тесты важнее кода. Цельность фичи, интеграция разработчиков, бизнес инварианты это про тесты, а не про реализацию.

    • Если код тяжело тестировать = плохой код. Не всегда наоборот.

    • Тесты это тоже код, его надо уметь писать, изолировать тест кейсы, декомпозировать части логики.

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

    Если резюмировать, то TDD для меня имеет скорее образовательный потенциал:

    • Научить, что разработка быстрее через тесты, чем проверку работоспособность того-же веба через страницу и мануальный ввод.

    • Заставить заработчика продумать систему, а не экспериментировать и переписывать MVP.

    • Когда не уверен в команде\разработчике и хочешь посмотреть правильно ли он понимает задачу.

    • Научить писать тесты, понимать баланс между интеграционными, юнит и функциональными. И что тесты это не про один метод execute вызывает другой execute .

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


  1. barancev
    21.03.2024 07:42

    большинство моих (и, я уверен, ваших тоже) работ - это не простые функции. Это сложная логика, на отладку которой требуется время. Если я буду неукоснительно следовать TDD, я буду тратить время на написание тестов, которые в итоге выброшу

    Разве те "примеры", которые используются для отладки, не выполняют роль тестов? Просто вы их почему-то не хотите так называть. Вы как бы делите тесты на "первый" и "второй" сорт. Ну да, часть из них, действительно, будет выброшена в итоге, но это нормально, любые тесты эволюционируют вместе с программой и с требованиями к ней, новые тесты появляются, существующие изменяются по мере уточнения требований, какие-то тесты становятся ненужными и исчезают.


    1. Suor
      21.03.2024 07:42
      +1

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


      1. Anarchist
        21.03.2024 07:42

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


  1. manyakRus
    21.03.2024 07:42
    +2

    Наконец-то хоть кто-то не побоялся говорить правду :-)

    ито статья похожа больше на чей-то перевод с другого языка


  1. hooy
    21.03.2024 07:42

    Странно, никогда не видел чтобы TDD воспринимался буквально — сначала тест, потом все остальное. Зачем писать тесты для PoC и экспериментов?

    Иногда тест помогает отладке — тогда проще сращу его написать и им уже дергать свой сервис/функцию/вотэвер, но common sense подсказывает что есть куча исключений, как раз о том, о чем пишет автор. Вот только это не проблема TDD, это проблема в том, как кто-то его слишком буквоедственно воспринимает. Судя по тому что написал автор (всегда потом пишет тест) — он как раз таки следует TDD, оно про результат — все покрыто тестами, а не про буквальное — «блииин не могу тест написать сначала, все, у меня лапки, нафиг вообще эти тесты».


    1. Suor
      21.03.2024 07:42
      +1

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


  1. noodles
    21.03.2024 07:42
    +2

    Тесты по TDD обычно пишутся теми же, кто пишет код. Если разработчик неправильно истолковал требования - то и тест, и тестируемый модуль будут содержать ошибку.

    Вот если бы тесты писали постановщики задач перед тем как передавать задачу в разработку!.)


    1. Anarchist
      21.03.2024 07:42

      Они часто не то, что тесты, требования сформулировать не могут. Как террористы, захватившие погреба Массандры.


  1. eertree
    21.03.2024 07:42

    Мне кажется вы неправы уже с начала статьи: "TDD - это неправильная практика. Она всегда была неправильной. Она неправильна по определению. Ее главная заслуга - поощрение тестирования, но на этом все и заканчивается."

    TDD -- это концепция с своей границей применимости. Писать на все TDD не имеет смысла если у вас постоянно меняются функциональные требования.

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

    Также не рационально пихать TDD на среды где затруднено писать тесты: это будет доставлять больше неудобства чем business value в виде качества продукта. Тем более если нет автоматизации тестирования

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

    Лучше всего использовать TDD на проектах с ясными функциональными требованиями (такое редко, но все же случается), с высокой степенью автоматизации и в основном на core domain часть, которая зафиксирована и меняется крайне редко: процессинги, шедулеры etc

    Поэтому утверждать "TDD - это неправильная практика" -- это популизм, оправдывающий плохие практики и некомпетентность техлидов