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

Эта статья, в формате небольших тезисов, нацелена на открытие дискуссии на тему "Test Driven Development" – методологии разработки через тестирование. На моем текущем месте работы существует несколько мнений: начиная от полного принятия и стремления(к tdd), как к идеальному инструменту написания рабочего и лаконичного кода, вплоть до полного отвержения: TDD не работает, убивает время разработчиков, увеличивая при этом time-to-market.

К каждому тезису, которые я выделил, я буду оставлять свой комментарий, стараясь быть объективным и не транслировать какую-либо позицию.

Жду ваших комментариев, уверен, что во многом я могу быть не прав.

Рассмотрим основные аргументы ЗА:

TDD ведёт к увеличению процента покрытия кода тестами

Это действительно, факт, и с ним сложно спорить. Методология подразумевает написание тестов ДО написания кода, поэтому процент покрытия такого кода скорее всего будет стремиться к 100%.

TDD дает разработчикам большую уверенность в надежности и функциональности кода

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

TDD избавляет разработчиков от страха внесения изменений в код

В целом тезис – продолжение предыдущего. Может все-таки стоит хоть немного бояться?) Страх иногда штука полезная.

Но оговорка: если твои тесты отменного качества, то несомненно. Если вы можете рассчитывать на тесты на все 100%, то тут даже и думать нечего, бегом рефакторить все налево и направо, и функционала нового побольше!

TDD подталкивает разработчиков к более прагматичным решениям

Я знаю N-ое количество разработчиков, которых в целом невозможно подтолкнуть к прагматичным решениям, поэтому этот тезис работает далеко не на всех. (А зачастую, те, кто и так склонен к глубокому анализу и прагматичным решениям, могут записывать это в преимущества TDD)

TDD позволяет разработчику быстро получить обратную связь от изменений в коде

Опять-таки, в идеальном мире – да. Но в реальном мире, у вас просто могут быть плохие тесты, которые не позволяют получить обратную связь в тех местах, где она действительно нужна.

TDD позволяет разработчику сосредоточиться на поставленной задаче

Опять же, факт. Что бы написать, пусть даже и плохой, тест, и впоследствии написать код, который проходит этот тест, необходимо сосредоточится. Хотя я не помню ни дня, когда я решал какую-либо задачу, не сосредоточившись на ней (пусть и ненадолго, но такой этап всегда присутствует)

TDD способствует четкому пониманию требований до начала написания кода

Да, абсолютно, но с оговоркой) Тех требований, которые показались тебе понятными. Система сыпется полностью, если требования неправильно донесли, тз было прочтено не в той формулировке, юзеркейсы оказались неверными – все это полностью уничтожает весь вклад TDD в разработку.

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

TDD = документированный код

Грамотные тесты достаточно четко документируют происходящее в коде, отвечая на вопрос: а что реально должно тут происходить? Огромное количество тестов, с которыми сталкивался я, не были в состоянии ответить ни на подобный, ни на прочего рода вопросы.

Рассмотрим основные аргументы ПРОТИВ:

TDD отнимает время

Действительно, с этим фактом не спорит никто, ни сторонники, ни противники TDD. Разброс прироста к длительности процесса разработки составляет 10-35%, в зависимости от квалификации и опыта команды.

 

источник

TDD не гарантирует качество тестов

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

TDD ставит перед разработчиком нереалистичные цели

Позволю цитату:

«в реальной жизни фичи устроены немного сложнее, чем «функция X должна принять имя и вывести приветствие с этим именем». Часто требования к продукту меняются посреди работы или вы вдруг осознаёте, что фича не может работать согласно требованиям. Или вы изначально всё не так поняли, и вам нужно начинать работу с нуля» - тык

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

Изначальные требования могут быть поняты или сформулированы неверно

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

Тесты необходимо поддерживать при изменении требований

Я думаю, каждому, кто работал на крупных проектах, приходилось видеть unit тесты низкого качества. Мало кто думает над парадигмой гибкости и переиспользуемости кода, при их написании, в результате чего тесты превращаются в полотно копипаста, которые при изменении поведений системы легче переписать с нуля, чем отрефакторить. Поддерживать тестовую базу возможно лишь при грамотном подходе к ее созданию, чего TDD не гарантирует.  

TDD зависит от конкретного разработчика

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

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

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

На этом, наверное, все. Вывода не будет, решайте все сами.

А как вы относитесь к TDD?

Источники:

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


  1. segment
    29.08.2024 18:48

    Есть ли кардинальная разница между "написать тест -> спроектировать модуль -> довести модуль -> изменить тест" и "спроектировать модуль -> проверить прототип -> довести модуль до рабочего состояния с учетом всех новых данных -> написать тест"?


    1. YegorP
      29.08.2024 18:48

      Кардинальной - нет. На выходе в обоих случаях возможен один и тот же код, покрытый одними и теми же (плюс-минус) тестами.


    1. youngmyn Автор
      29.08.2024 18:48

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

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


      1. 9982th
        29.08.2024 18:48
        +3

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


  1. powerman
    29.08.2024 18:48
    +1

    То, что ставится на первое место, чему уделяется основное внимание - то и получается качественнее. Практикуя TDD мы получаем качество тестов выше качества кода. Ещё бывает Documentation-driven development - там та же проблема. Вряд ли это то, к чему стоит стремиться.


  1. AnROm
    29.08.2024 18:48

    По-моему TDD многие попробовали лет семь назад и отказались от этого подхода. Возможно потому, что неправильно его применили, не знаю. Бывает такое, что пишут тесты, потом код, и осознают, что тесты нужно переделывать. Получается, в этом случае тесты пишутся дважды. Концепция BDD(Behavior-driven development) выглядит более привлекательной и на практике даёт лучше результат. Она как-то лучше прижилась.


  1. Sadler
    29.08.2024 18:48

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

    На текущем проекте перебиваюсь valgrind, gcc с максимально выкрученными warning'ами, cppcheck, clang-tidy, фаззингом и автогенерируемыми тестами (chatgpt). Это всё тоже даёт какую-то уверенность, хотя и не непробиваемую.


  1. voidinvader
    29.08.2024 18:48

    Разработка через тестирование это примерно как трусы через голову надевать.


  1. dyadyaSerezha
    29.08.2024 18:48

    Классчиеский спор остро- и тупо- конечников. С какого конца начинать, зависит от ситуации. А иногда надо и с обоих. А иногда и ещё с другого, третьего, четвёртого конца. Наука умеет много гитик.


  1. 0xC0CAC01A
    29.08.2024 18:48

    А вот почему не пытаются ИИ заставить писать код, прогоняя ответы через TDD? Вот где TDD действительно был бы полезен.


    1. Sadler
      29.08.2024 18:48

      Не знаю, как на уровне индустрии, а я таким занимался ещё на заре chatgpt: заставляем писать код с тестами, затем скармливаем результаты тестов и заставляем править код. Проблема лишь в том, что без программиста всё равно не получается: у LLM очень быстро возникает кризис идей, и нужно подсказывать и направлять, куда развивать дальше. Или иногда он упирается рогом, доказывая, что его код истинно верный, а весь остальной мир ошибается. Проще ли эта возня, чем самому написать? А вот фиг его знает, зависит от задачи. Ну, и контекста всегда катастрофически не хватает, каким бы большим он ни был :D


  1. i360u
    29.08.2024 18:48

    Хороший разработчик пишет тест до решения основной задачи, только когда это ему действительно нужно. И не пишет, когда не нужно. Когда эта практика навязывается извне, в рамках "эффективного менеджмента" - получается полная ерунда. Всегда.


    1. Hardcoin
      29.08.2024 18:48

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


  1. heart
    29.08.2024 18:48

    Настроение автора и выводы понятны без их письменного документирования. Статья попытка оправдаться перед собой и возможно перед коллегами. Но действительность такова что TDD надо внедрять. Конечно нужен опыт.

    • «TDD подталкивает разработчиков к более прагматичным решениям»: В рамках ООП- шного языка программирования TDD тесно сотрудничает с SOLID и со всеми соседними прагдигмами. Требует знаний паттернов проектирования. Да и вообще ставит мысли на место.

    • Рефакторинг рано или поздно нужен всем. Как быть уверенным в том, что после рефакторинга можно вообще что то отдавать в прод? Трата времени на тесты после этого - отсутствие седых волос при внедрении. А если приходят новички? Как до них донести крайние тест-кейсы кроме как заранее не занести их все в UT?

    • «TDD способствует четкому пониманию требований до начала написания кода»: не понятно о чем речь. Не знаешь что писать, не начинай пока не разберешься

    • «Само по себе наличие каких-либо тестов, как я выяснил на практике, не гарантирует ровным счетом ничего.» Просто писать тесты ради тестов? Зачем? Если не понимаете сути то, конечно, лучше их не писать до тех пор пока в этом не разберетесь.

    • «Огромное количество тестов, с которыми сталкивался я, не были в состоянии ответить ни на подобный, ни на прочего рода вопросы.» Ну так это не аргумент, а просто факт что те тесты что вы смотрели были ужасными. Мотивировать их не писать он не может. Только наоборот.

    • «TDD отнимает время»: так в любой сфере. Вопрос: чье время и сколько оно стоит? Из опыта: «затраты» потраченное на тесты потенциально меньше разного рода суммы «затрат» на разных следующих этапах включая внедрение.

    • «Тесты необходимо поддерживать при изменении требований»: это преимущество при хороших тестах и минус при плохих. Не более не менее.

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