LINUX.ORG.RU

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

 , ,


4

2

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

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

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

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

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

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

там про единорогов было чет, имеет право на жизнь.

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

Нужен процесс. Спека -> тесты -> реализация.

Так в TDD нет различия между «спекой» и «тестами на багофичи», это одно и тоже.

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

БД и файлы тестируются отлично, слава h2 и временным файлам.

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

Задача без написания тестов не считается выполненной

Вообще-то задачи нет, пока нет нерабочего теста.

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

Ты реально считаешь, что TDD означает всего-навсего автоматические тесты?

Люди постоянно забивают на всё. Там где применяют TDD есть хоть какие-то тесты. Там где не применяют TDD, там просто треш и угар.

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

Ну вообще, в тестировании на mock’ах польза есть, зависит от проекта. Но как правило это отдельные тесты и как правило функциональные или интеграционные… но unit-test’ы такие тоже видел, когда mock’и простенькие а обвес вокруг них достаточно сложный и его имеет смысл тестить unit-тестами чтобы не развалить чего-нить. Но если для unit-тестов надо разворачивать целую здоровую БД или что-то еще имеющее собственное состояние - это уже перебор. А еще беда когда ради тестов приходится писать портянки кода которые по факту не покрываются тестами и что в результате тестируется - непонятно…

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

Ну в реальной жизни разница есть. Просто у тебя соотношение 1 в 1 со спекой и «интерпретации спеки тестами». И ты смотришь не в спеку уже а в тесты при реализации. А в спеку смотрит PM, архитектор и техписатель.

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

где применяют TDD

А его нигде и не применяют. Все сперва пишут реализацию, и после пишут тесты. И называют это TDD. Но это не TDD.

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

Это не проблема ТДД. Если джун пинает член, то он будет это делать и при других подходах. Это проблема ленивожопости или перегруженности вышестоящих.

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

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

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

Более менее похожее на TDD есть в bug-fixing’е.

Когда программист-тестер сперва пишет сценарий, где проявляется баг - «тест, который не проходится». И только после этого пишется исправление, которое проходит этот тест.

«Тест с ошибкой» –> «исправление» –> «тест без ошибки»

anonymous
()

Я считаю, что TDD идеален для таких команд, в которых и дизайн, и реализация, и тестирование лежит на одном человеке. Одном или максимум двух. Причем, второй нужен для обслуживания вопросов первого и связи с заказчиком. А ТЗ у них либо нет вообще (например, всё со слов заказчика и какой-то презенташки, показанной на митинге), либо такое хреновое, что переделывается с каждой итерацией разработки.

Короче, TDD идеален, если заказчик не знает, что хочет, а разработчик не имеет опыта составления ТЗ и не обладает бюджетом для найма архитектора, программиста и тестировщика.

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

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

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

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

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

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

В чём проблема?

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

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

anonymous
()

Как уже писали, твои вопросы от того, что ты внедряешь тесты в уже существующий проект, где development был совсем не test driven. А так TDD про написание юнит тестов до написания кода, что поможет и написанию тестов, и упростит написание кода. Но конечно это все будет дольше обычного подхода, если только требования не меняются постоянно.

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

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

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

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

В последних двух мёрдж вообще невозможен, если тесты не пройдут.

Тесты от царя гороха, или при каждом новом коммите смотрят изменились ли требования, и нужно ли дополнительное покрытие тестами…

Если второе, то чем это отличается от TDD?

fsb4000 ★★★★★
()
Ответ на: комментарий от izzholtik
  • полезно уделить внимание следующим моментам (как минимум)
    • в основном при хуках на пуш
      • CI
        • проверка отработки тестов в результате изменений
          • в том числе автоматические тесты в окружениях:
            • браузер
            • desktop
            • shell
            • network
      • линтинг, в том числе орфография и стиль, отступы и т.п.
    • практически мгновенное развертывание тестового окружения
anonymous
()
Ответ на: комментарий от anonymous

. В то время, когда TDD - именно про тесты и сперва тесты.

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

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

при каждом новом коммите смотрят изменились ли требования

У тебя превратное представление о процессе разработки. Требования не меняются от балды. Требования не определяют тесты.

Miguel ★★★★★
()

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

В таком же духе можно придумать DDD, JDD, и SDD — соответственно Debugger-Driven Development, Jira-Driven Development, и Smoothie-Driven Development. То есть, берете любой банальный инструмент, придумываете идеологию «банальщина-driven development», пишете книги, устариваете тренинги, организуете консалтинг, разрабатываете автоматизированные инструменты для контроля выпитого смузи, и так далее, в лучших традициях эффективной разработки в опенспейсе.

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

Да, нужен правильный SDD! А то без драйва не девелопается

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

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

Но если для unit-тестов надо разворачивать целую здоровую БД или что-то еще имеющее собственное состояние - это уже перебор.

Ну не знаю. Я всегда БД тестирую с живой БД. Иногда даже с фикстурами (типа). Но с ними тяжелее. А остальное моками. Это всё юниты для покрытия. Интеграционного тестирования не отменяет.

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

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

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

ТДД нужен чтобы развеять миф, что тесты пишет тестировщик

Тестировщик? Кто это? Я никогда в жизни не работал в команде с отдельным тестировщиком.

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

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

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

На одном собеседовании, где побеседовал я, кандидат мне заявил, что они писали финтех и очень дорогой, поэтому тестов не делали – дорого для заказчика, понимаете ли.

anonymous
()

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

из личного опыта - тесты начинаю писать когда основная фактура дизайна прорисовываться начинает. держать покрытие 70-80% и выше можно только на законченных проектах, которые не развиваются, а только на сопровождении с частичным файн-тюнингом. но в остальных случаях, конечно же, лучше стараться держать 40-50%

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

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

Ты не можешь перезапустить такой «тест» и отловить регрессию. Точнее можешь, но скорее всего будет поздно (баг обнаружит уже реальный юзер на продакшене).

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

Тестирование с живой БД необходимо, если она используется, но только не в Unit-тестах а в интеграции… юниты они чтобы быстро показать проблему, желательно сразу на этапе сборки, потом CI прогонит интеграционные и уже будет уверенность (ну почти).

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

Тестирование с живой БД необходимо, если она используется, но только не в Unit-тестах а в интеграции…

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

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

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

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

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

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

Возможно путаю, но если БД является одним из модулей то почему нет?

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

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

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

Задача «написать поиск наибольшего общего делителя».

1 коммит: тест gcd(1, 1) = 1
2 коммит: gcd(p, q): return 1

3 коммит: тест gcd(2, 2) = 2
4 коммит:

def gcd(p, q):
  if p % 2 == 0 && q % 2 == 0:
    return 2
  else:
    return 1

5 коммит: тест gcd(3, 3) = 3
6 коммит:

def gcd(p, q):
  if p % 3 == 0 && q % 3 == 0:
    return 3
  elsif p % 2 == 0 && q % 2 == 0:
    return 2
  else:
    return 1

… 100500 коммит:

def gcd(p, q):
  if p % 50250 == 0 && q % 50250 == 0:
  ...
  100500 строк
  ...

Всё по TDD.

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

Да у меня там запросы к БД и больше тестировать нечего. Мне корректность SQL-запроса и сканирования ответа иначе проще проверить никак просто. Это самый простой способ. Причём через переменные окружения. Нету – пропуск теста и всё. Я то у себя локально всегда могу запустить и удостовериться, что всё хорошо.

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

В других бла-бла-DD конечно же по другому!

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

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

начинается с математики

Ага, с аксиом, которые надо соблюдать. Я вот подзабыл, аксиомы пишутся до алгоритмов или после?

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

И они единожды написаны.

И каждый раз проверяются. Как удобно, да?

Надо бы ещё всех посадить на coq. Вот тогда посмотрим, кто умеет в математические алгоритмы, а не в противоречивые неопределенные поведения. Интересно, на каком коммите напишут хоть что-то проходящее «отсутствующие» тесты?

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

я> аксиом, которые надо соблюдать

ты> они единожды написаны

я> И каждый раз проверяются.

ты> Зачем?

Как же быстро ты теряешь контекст.

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

Аксиомы соблюдает компилятор.

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

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