LINUX.ORG.RU

TDDшники, а расскажите про свою религию?

 , ,


4

2

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

В целом, вопросные тезисы и тезисные вопросы таковы:

  • С чего начинать? Как выбрать фичу, к написанию теста на которую приступить в первую очередь? Как не попасть в ситуацию «написал приёмочный тест вместо красивого чёткого TDD, ну ты лох», о которой многие упоминают, но не рассказывают, как правильно? Практически все мануалы показывают написание теста сразу для фичи верхнего уровня, что, КМК, приёмочным/дымовым тестом и является.
  • Написание теста для функционала, решение которого нетривиально, вынуждает писать тонны заглушек просто чтобы «скомпилируйся наконец уже пожалуйста». Количество заглушек умножается на количество «baby steps» при рефакторинге и добавлении новых тестов, генерируя адский объём механической работы. Определённо, значительная часть таких затыков порождена моей дизайнерской криворукостью, но мя не вижу способа полностью избежать этого рака.
  • Как TDD предлагает «пробивать» инкапсуляцию, когда функционал под тестом оказывается нетривиальным и требует вынесения части функционала в новую сущность? Многие статьи демонстрируют погрузку болта на внутреннюю сложность реализации, тестируя только контракт, что выглядит очевидно неправильным. Имеет ли концептуально реализация право порождать новый тест? Нужно ли, когда в ходе рефакторинга или позеленевания тестов требуется создать что-то новое, откладывать текущую работу над реализацией и идти писать новый тест для свежеобозначившейся проблемы? Что делать, когда поймёшь, что погряз в огромном объёме некомпилируемого кода и незапускающихся тестов?
  • Некоторые авторы предлагают следующий рекурсивненький жизненный цикл: ставим задачу верхнего уровня, решаем её. Если не удаётся за вменяемое время написать тест/реализацию, дропаем текущие наработки, собираем митап и распиливаем её на подзадачи, далее работаем с ними. Это выглядит минимально-рабочим, но вызывает вопросы: как планировать время на реализацию фичи, как рефакторить функционал более верхнего уровня, если он окажется концептуально неправильным, как избежать лавинообразного рефакторинга с проблемой кучи некомпилируемого кода, чем безумно дорогая по времени перековка какашки в конфетку лучше, классического предварительного планирования с UML и быстрого написания прототипов отдельных штуковин.

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

Change my mind, как говорится, если есть желание. Мя ещё не зафиксировал какого-то конечного мнения о сабже, но первые впечатления смешанные.

TDD по большей части для обучения и нужно. Оно естественным образом вырабатывает в тебе SOLID принципы (иначе задолбаешься тесты писать).

fulmar_lor
()

С моего дивана это всё представляется примерно так:

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

  2. Документация нужна. Описать публичные интерфейсы (наборы функций) модулей. Написать к ним документацию, спецификации входных и выходных данных.

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

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

  5. Готово, вы великолепны!

Nervous ★★★★★
()

Если известно что делать, то можно и ТДД. Если нет – начинать с реализации, и корректировать её тестами.

anonymous
()

Вообще, ТДД описан кратко и в примерах в книге Майкла Хартла о Рубине на Рельсах. Там и применимость и подход понять проще. Разработка идёт по сценарию добавления фич. Фича, тест, провал, реализация, тест, успех, готово.

anonymous
()

А что-то изначально огромное таким подходом не взять.

anonymous
()

дымовым тестом.

Божечки-кошечки.

Полностью работающего тдд в продакшене никогда не видел и сомневаюсь что оно возможно в хоть сколько-то сложном проекте.

pinus_nigra
()

Основной принцип TDD. Любая строчка кода пишется только для того, чтобы прошёл какой-то тест. Если есть хоть одна строчка кода, без которой тесты проходят, она не нужна.

Полностью следовать этим правилам сложно, поэтому отладочное логгирование и метрики разумно исключить.

Твои вопросы я не очень понял. Но в целом — да, писать покрытый тестами код трудней и дольше, чем не покрытый. С непривычки — намного дольше.

Legioner ★★★★★
()

Если это религия, то надо знать её пророка, которым является Кент Бек. Изучать TDD надо по его книге, а не по каким-то статьям. И в книге он сам пишет, что его методика подходит не везде.

TDD и вообще юнит-тесты идеально подходит для какой-нибудь библиотеки без побочных эффектов. Потому что всё равно вы будете проверять свою библиотеку через код, имеющий побочные эффекты (вывод), так почему бы не использовать какой-нибудь аналог JUnit. Если начинают появляться mock-объекты, как замена реальных объектов с побочными эффектами, то всё уже не так красиво. Потому что мы тестируем поддельные объекты вместо настоящих. Это тестирование ради тестирования.

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

Может ли TDD испортить код? Да, может. Если код с побочными эффектами выворачивается наизнанку ради юнит-тестов, то что-то идёт не так. Рефакторинг, ради которого юнит-тесты зачастую внедряют, будет произвести сложно, ибо никто не сможет понять, как этот хитроумный код работает. Я уже не говорю о добавлении нового функционала.

Kogrom
()
Ответ на: комментарий от Kogrom

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

…только без вдумчивого ревью %)

Nervous ★★★★★
()
Ответ на: комментарий от anonymous

чёткие пацаны сразу пишут чёткий код

Это про петушков на coq’е?

anonymous
()

TDD круть!

anonymous
()
Ответ на: комментарий от anonymous

Фича, тест, провал, реализация, тест, успех, готово.

В общем, макаронный говнокод, задача которого всего лишь не завалить тесты.

devl547 ★★★★★
()

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

если по пунктам кратко, то ттд не подходит для тестов с состоянием @ интеграционных тестов. Юнит тесты пожалуйста.

abcq ★★
()
Ответ на: комментарий от abcq

общая философия такова

есть (если нет, пусть достанет из-под земли!) бигдата с промаркированными данными и программиста тренируют на этих данных пока не напишет «Искусственный Интеллект».

Вот так надо подавать «философию» инвесторам.

anonymous
()
Ответ на: комментарий от abcq

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

Вы, товарищ, аккуратнее, опасным марксистским говном запахло 🤣

erfea ★★★★★
()

Я как-то собеседовался в одну контору, где были фанаты TDD. После собеседования они меня пригласили сделать техзадание — на их технике. И показали, как они работают. Бежал я оттуда теряя тапки.

Miguel ★★★★★
()
Ответ на: комментарий от Legioner

не очень понял

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

izzholtik ★★★
() автор топика
Ответ на: комментарий от Kogrom

мы тестируем поддельные объекты

Так вроде ж мы тестируем интерфейс, до момента рефакторинга вообще не обращая внимания на внутренности?

Если код с побочными эффектами выворачивается наизнанку ради юнит-тестов, то что-то идёт не так

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

izzholtik ★★★
() автор топика
Ответ на: комментарий от izzholtik

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

abcq ★★
()
Последнее исправление: abcq (всего исправлений: 1)
Ответ на: комментарий от izzholtik

Никак. Это особенность такого стиля. Зато заказчик видит постоянные релизы. А не так, что программист ушёл на полгода в нирвану, а через полгода оказалось, что ничего не готово.

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

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)

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

Но вообще, я не видел нигде доказательств улучшения качества продукта в плане цена/качество с TDD/без TDD в более-менее массовых количествах не подверженных survivor bias.

slapin ★★★★★
()
Ответ на: комментарий от Miguel

Я как-то собеседовался в одну контору, где были фанаты TDD. После собеседования они меня пригласили сделать техзадание — на их технике. И показали, как они работают. Бежал я оттуда теряя тапки.

Любишь падающие программы? Или фанат ручного тестирования?

fsb4000 ★★★★★
()

Мя тут немного почитал

Мя ещё не зафиксировал какого-то конечного мнения о сабже

Таких как ты током через башку лечат.

Oberstserj ★★
()
Ответ на: комментарий от Oberstserj

Ну я не в курсе, зайдёт через полгодика ответит может. =)

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от fsb4000

TDD - это не про тестирование как таковое, это скорее про подоход к разработке и отчасти дизайн. При бездумном использовании можно навалить лютого кринжа, как этот чел с топа выдачи, например: https://m.youtube.com/watch?v=e3wcDos9gAI&t=720

izzholtik ★★★
() автор топика
Ответ на: комментарий от slapin

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

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

Oberstserj ★★
()
Ответ на: комментарий от fsb4000

Монады на хаскеле не надо тестировать на то, что они являются монадами. «Жесть, дует».

anonymous
()
Ответ на: комментарий от devl547

В общем, макаронный говнокод, задача которого всего лишь не завалить тесты.

Там речь про интеграционные тесты (или как их правильно назвать? тестирование api-вызова в общем). Оно юниты не отменяет. Просто тестирование функционала идёт впереди реализации. И при этом нет решения огромного кол-ва задач за раз.

anonymous
()
Ответ на: комментарий от erfea

По мне – отдельный тестировщик – это другое. Программист всё равно должен тестирование делать. Зная код, и как его завалить. При этом тестировщик всё равно нужен.

anonymous
()
Ответ на: комментарий от devl547

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

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

В общем методология для техподдержки.

anonymous
()
Ответ на: комментарий от izzholtik

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

abcq ★★
()
Ответ на: комментарий от izzholtik

нет никакой обратной связи

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

anonymous
()
Ответ на: комментарий от anonymous

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

izzholtik ★★★
() автор топика
Ответ на: комментарий от Oberstserj

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

slapin ★★★★★
()
Ответ на: комментарий от izzholtik

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

abcq ★★
()
Последнее исправление: abcq (всего исправлений: 1)
Ответ на: комментарий от anonymous

Ну почему же маленькими. Нужен процесс. Спека -> тесты -> реализация. Если тесты под спеку не подходят - нужно писать тесты. А любые изменения функциональности - через изменения в спеке. Любые отклонения от этой схемы всю разработку по TDD спускают в унитаз. Любые быстрофиксы типа «ща так сделаем, сдадимся а потом тесты перепишем» тоже все спускают в унитаз. То же самое если начинается не разработка а экспулатация дыр в процессе - если это происходит, процесс на свалку и нужна разработка нового процесса. Эффективным менеджерам не понять.

slapin ★★★★★
()
Ответ на: комментарий от abcq

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

slapin ★★★★★
()
Ответ на: комментарий от slapin

ну так в этом и суть, пишите минимальные юнит тесты, делаете таску, сдаетесь до дедлайна. А когда настанет очередь до рефакторинга этой таски уже можете побольше уделить времени на тесты если код +/- приличный.

abcq ★★
()
Ответ на: комментарий от anonymous

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

izzholtik ★★★
() автор топика
Ответ на: комментарий от fsb4000

Любишь падающие программы? Или фанат ручного тестирования?

Пхпшник, наверное.

Nervous ★★★★★
()
Ответ на: комментарий от izzholtik

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

Если предлагается через инверсию зависимости выбирать, реальную мы базу данных используем или mock-объект, и всё это делается только ради юнит-тестов, то это усложнение системы на ровном месте. Сторонники такого подхода могут сказать, что код будет гибче, что нам так проще будет поменять базу на другую, если это когда-нибудь потребуется. Но нам это не потребуется.

Может ли дать какую-то пользу тестирование mock-объекта? Вероятно, может. Если архитектура не идеальна, то мы кроме него зацепим тестом ещё какой-то кусочек кода. Или если mock-объект используется не только для тестов. Или для того, чтобы галочку поставить в отчёте о проделанной работе.

Kogrom
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.