Почему 95% разработчиков не используют TDD?

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

Вот самые распространенные отмазки, которые я слышал, почему тесты не нужны:
1. Я сразу пишу код без багов. (А еще я экстрасенс, предсказываю будущее, потомственный телепат и лично знаком с Графом Дракула)
2. Это долго. (Зато потом не долго месяцами лазить по коду дебагером и пытаться понять что это за хрень и как оно вообще работает)
3. Заказчик не оплачивает. (Тоже самое что в 2. только еще во всем виноваты жадные пиндосы)
4. Тесты плохо работают. (А еще плохо работают ленивые разработчики)

Может подойдет простое объяснение — изначально не учат программировать через тестирование, а потом самому лень разбираться?

UP: Под словом «тесты» я подразумеваю именно использование методологии TDD, а не просто сферические Unit-тесты в вакууме.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному1
LinkedIn

Найкращі коментарі пропустити

Наболевшее:
дайте мне плз спецификацию по проекту, а потом поговорим о тестах :)

В первых двух случаях можно просто списать на умственные способности населения, но третьи должны быть умнее, по идее.
Как же ж мне нравится, когда вылазит очередной пыонэр, заходит на форум «профессиональных электриков» и начинает задвигать про то как плохо совать пальцы в розетку.
1. Я сразу пишу код без багов
Именно. Распечатай эту фразу двухсотым шрифтом и повесь на стену позади монитора. Может и тебя постигнет дао.
2. Это долго
Да, это долго и ненужно. В дебагере лазить месяцами не нужно, см. пункт 1.
3. Заказчик не оплачивает.
Если ты считаешь, что ты откровенно лажаешь, то дели свой рейт на два и пиши тесты, когда надоест, то см. пункт 1.
4. Тесты плохо работают.
Они вообще не работают. Если ты написал тест, который поймал ошибку в твоём коде, то ты не программер, а тестер. Настоящие программисты пишут без ошибок. См пункт 1.
Может подойдет простое объяснение — изначально не учат программировать через тестирование, а потом самому лень разбираться?
Учить программировать через тестирование — то же самое что тренировать школьную сборную по плаванию в бассейне без воды.

Почитал коменты и вижу что главная причина почему не используют ТДД — это отсутсвие понимания такого процесса разработки в целом + отсутствие практического опыта успешного применения ТДД. Т.е. люди привыкли работать определенным образом и что бы эту привычку поменять мало прочитать про ТДД — нужно попробовать и доказать себе что с ТДД лучше.
Вторая причина — ТДД сложнее. Что бы его применять успешно — нужно очень хорошо понимать как это делать правильно. Поэтому многие пробуют — ошибаются и потом плодят мифы что с ТДД дольше, дороже, нужно иметь спеку — и т.д.
Можно сказать что с ТДД разработка дольше — но дольше она не за счет тестов, а из-за необходимости думать вперед, поддерживать хорошую архитектуру и избегать технического долга.
Как правильно написали: проект, который с ТДД напишут за 3 месяца можно написать вдвое быстрее если применять методику тяп-ляп и в продакшин. С этим сложно поспорить.
В этом, я считаю, главный плюс правильной методики разработки — технический долг просто не получается накапливать. Если пытаются что-то заткнуть костылями по-быстрому — то сразу значительное колличество тестов становятся красными, падает степерь покрытия и т.д. Дальше, обычно, поломанные тесты начинают выкидывать что бы не тратить время — и покрытие падает еще больше.
В хорошей компании должен быть человек, который мониторит метрики проектов. И такая ситуация прекрасно сигнализирует о проблемах на проекте, даже если ПМ и техлид уверяют что «все под контролем», «мы успеваем» и т.д. Но если это не «одноразовый» проект — то задача начальника более высокого уровня думать наперед: сегодня они «успеют» налепив костылей — а через полгода скажут что проект «не интересный» — и уволятся. Новым людям придется долго вникать и еще дольше разгребать технический долг. Или продолжать лепить костыли пока проект окончательно не сдохнет под их весом.
Вообщем хотите правильно делать ТДД на .Net — спросите меня, как.

Вы мешаете в кучу необходимость писать тесты и использование TDD как методологии написания тестов.

Писать тесты можно и без строгого следования ТДД, внезапно.

Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

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

xxx: Если ваш сервис сделан из говна и палок, нужно как минимум три типа тестов: на говно, на палки и интеграционные.

приёмочные, забыли про приёмочные)

Лоооол. Вы обсуждаете некрометодологию безсмысленность которой доказана 25-ю годами безуспешных попыток внедрения.

некрометодологию

Мало того, кто-то откопал дохлую тему и отлично занекропостил %)

Ну 25 вроде нет — книга относится к 2002-2003, активный шум пошёл ещё через пару лет. Но 10 уже точно можно отмечать :)

Та даже если 10. (Хотя имхо ближе к 20-ти) Методология — не математика. Либо успешно зашло, либо вечная память)))

Я помню, что появились массово переводы книг по TDD на Петровке, когда во всём мире оно уже даже перестало издавать трупный запах %)

Як з будь-якою методологією, треба розбиратися хто її розробив та для яких конкретних задач. Так ось, XP не про розробку програмного коду. Вона про ефективність бізнесу розробки програмного коду. Так, вам не почулося та не примарилося. Саме тому вона не зайшла технічним спеціалістам та інженерам, бо вони зазвичай в менеджменті та бізнесі ані в зуб ногою. Тупе виконання практик XP зазвичай не давало жаданого ефекту, тому її швидко закидали як неефективну.

Там вся книжка побудована на двох графіках витрат/прибутковості, класична експоненційна кривуляка та парабола (. Зазвичай витрати на кожну наступну ітерацію/додану функціональність/рефакторінг зростають експоненційно. Через деякий час внесення змін стають збитковими. Компанія, або проект вмирають. Щоб цього не трапилося, треба інвестувати час в архітектуру та гнучкість вже на початкових етапах розробки. Так, це збільшує витрати на початку, але такий продукт легше змінювати з часом, а значить дешевше.

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

умеют же консалтеры красиво рисовать.

как можно юнит тесты написать раньше кода

V-shaped SDLC model is an expansion of classic waterfall model and it’s based on associated test stage for the every development stage. This is a very strict model and the next stage is started only after the previous phase.

existek.com/blog/sdlc-models

Так что скрам-мастера аджайла будут против :)

Похоже на ватерфолл, но в модном, молодежном стиле.

я не совсем понимаю как можно юнит тесты написать раньше кода

Юнит тесты написать раньше кода можно, если решение (алгоритмическое, дизайн, итд) уже готово (в голове либо спеке), но кода еще нет. Ну и плюс, многие забывают, что ТДД это итеративный процесс — никто не пишет все тесты до кода.

Если мы сроки проебем — то проебем 100% без возможности срезать углы за счет технодолга)

Кстати да. Хотя,

Ну и плюс, многие забывают, что ТДД это итеративный процесс

То есть если быть точным, то проебываешь ты конкретную фичу, не прям весь проект

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

Так тесты тоже код :)

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

Пример хороший, но на практике такое невероятно редко приходится писать. Ведь есть библиотеки для работы с цветами, они уже написаны и протестированы

единственное что я не совсем понимаю как можно юнит тесты написать раньше кода

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

Сам же Кент Бэк вполне четко написал.
Вольный пересказ:

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

Но так как 90% украинских помидоров уверенно оседлали гребень кривой Даннинга-Крюгера и считают себя гениями, то на TDD (и юнит тестирование в общем) они высокомерно фыркают, как на ненужное говно.
Фыркание даже считается почётным. Это такой же карго-культ, как и сам TDD для некоторых.

Цитирование одного из «создателей» TDD в топике про TDD более чем уместно и ожидаемо. В чем смысл твоего подкола?

Цитируй на здоровье. Только с какого перепугу ты подписываешься за «90% украинских помидоров»?

Не подписываюсь, а выношу свою субъективную оценку. В этом суть форумов. Feel free оспаривать и не соглашаться. Можем сойтись на 80%.

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

Цитирование одного из «создателей» TDD в топике про TDD более чем уместно и ожидаемо

ууу как все запущено, ты видимо «одаренный»

то на TDD (и юнит тестирование в общем)

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

Ошибка тут именно в приравнивании этих двух понятий.

Кто приравнивает? Где приравнивает?
Это частное и общее. TDD, как инженерная практика, существует исключительно в контексте юнит тестирования, как более общей инженерной практики.
Можно писать юнит тесты и не практиковать TDD, но нельзя практиковать TDD и не писать юнит тесты.

Учение Маркса всесильно, потому что верно ©

Сам же Кент Бэк вполне четко написал.

на всем что он ввел в мейнстрим — лежит отпечаток Smalltalk, не столько языка, сколько уникальной на сейчас среды выполнения.

Поэтому всё что от Кента Бэка на практике не такое блестящее. хотя и пуля.

Вообщем: народ включая помидоров путает что такое: автоматизированные тесты, интеграционные тесты, юнит тесты и разработку через тестирование(TDD).

В итоге получаем ересь в стиле: «Зачем нам QA если есть TDD».

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

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

Игрушки нынче лучше тестят

Давно в современные игрушки играл ?

Сколько лет скайриму и ведьмаку ? Сколько лет боинг максу ?

в Ведьмаке лично нашол пару багов

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

ты понимаешь что по факту наличие тестов (или писание через ТДД) никак не влияет на качество?

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

кто тебе сказал что наличие какогото теста даст хоть 5% вероятность того что оно отловить хоть одну настоящую проблему?

Практика. Но опять таки на одних проектах в этом есть смысл, на других это трата времени, дешевле вручную протестировать.

Где-то важно покрыть критическую часть.
Сейчас на проекте использую интеграционные тесты в некоторой части функциональности.

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

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

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

Я с этом согласен.
У на одном проекте было требование от заказчика покрывать юнитестами все. А разработчики умели только архитектуру на синглтонах, божественные объекты и юнит-тесты со скриншотами.
У меня подгорало от этого проекта где только могло.
А тимлид ходил и ворчал что Test Coverage падает:)

Сейчас у меня такая ситуация: мобильный проект на Андроиде. Интеграционный тест позволяете в облаке покрыть такое количество девайсом которое физически покрыть не можем. В данном случае тесты оправданы.

большинство не умеет писать тесты

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

Опишу двумя словами — тестирование имплементации — если ваш тест попадает в эту категорию то он просто дублирует функциональность системы версионирования кода.

тестирование имплементации

Прогуглил этот buzzword. Нашёл пару статей, в которых говорят «тестируйте то, что должна делать функция,» (или что там вместо функции) «а не то, как она реализована». С ходу нашёл контрпример — тестирование того, что конкретная применённая реализация сортировки имеет время O(n log n), весьма полезно. Но предположим, что так, и есть кто-то, кто «тестирует реализацию», когда это не нужно... а примеры-то будут?

дублирует функциональность системы версионирования кода.

При чём тут именно версионирование кода?

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

Хороший пример:

int[] testArray = new //blah blah 
Utility.sort(testArray);
Assert.assertNotNull(testArray); 

Ахеренно пртестировали сортировку. Зато покрытие збс.

Причём сначала отсортировали, а потом на нул потестили %)

Интересный у вас опыт. Вот честно, не попадались такие... но ответ безусловно засчитываю. Хотя я бы пример чуть переделал для другой цели — для удобства, это будет на Питоне (ибо мне нужно присвоение отсортированного, и облом вспоминать его для Java):

testArray = [3,2,1]

## вот этой строчки при первом прогоне теста нет
testArray = sorted(testArray)

assert testArray

Отсутствие второй строчки удовлетворяет fail-first test критерий для TDD.

только он и так вначале провалится — у тебя то функции еще не будет — потому красный, а потом ты пофиксишь и станет зеленым

только он и так вначале провалится — у тебя то функции еще не будет — потому красный, а потом ты пофиксишь и станет зеленым

Именно!!!

Весь TDD удовлетворён, а что на самом деле sorted оказалась, например,

    sorted = lambda x: x

никого не волнует — разумность теста не требуется.

потому не в тестах суть, а суть как всегда в прокладке между стулом и компьютером

Только это не юниттест, а ассерт.

А всё вместе — юниттест.

Только это не юниттест — это ассерт.

Это код теста. В джва юнит-тест либах класс как правило Ассерт называеться.

Я на питоне писал, ты заметил вообще?

Виктор к обоим кускам кода коммент оставил.

И что это даёт в данном случае, если Assert.* завалит тест, если ему не понравится результат?

Ассерт завалит тест. Билд несбилдиться, итд.

Вместо проверки на налл можно сделать, например, проверку на ожидаемый результат

@Test
public void testUtilitySort(){
 int[] testArray = new int[]{2,1,3}; 
 int[] expectedArray = new int[]{1,2,3};
 Utility.sort(testArray);
 Assert.assertEquals(testArray,expectedArray); 
}

Спасибо, кэп.

Влияет. Правильные тесты создают надёжный базис для верификации кода.

Там вверху было о просто тестах, а не о правильном.

Так это вы обобщили на все тесты, а я дал частное (полезное) исключение.

Та то фигня, когда ПМ из QA собирает совещание под девизом «А почему разраби не могут писать без бажин». Так что все от менеджмента

Тому що в них завжди є послабуха у вигляді тестів та QA. Тому немає взагалі сенсу писати якісний код.

Якісний код може неправильно реалізовувати бізнес-логіку. Юніт-тест це не помітить, тільки якщо там не щось трівіальне. А ,QA як раз спіткнеться.

Якісний код, який неправильно реалізує бізнес-логіку, має всі ознаки неякісного.
А на «правильний» юніт-тест треба ще писати свій тест, який доводить правильність тестування. :D

Якісний код, який неправильно реалізує бізнес-логіку, має всі ознаки неякісного.

это как так?

Л — логіка. Якщо ви написали код, який не реалізує бізнес-логіку, то немає значення, яка архітектура, чи всі назви змінних красиві й зрозумілі, скільки патернів ви по ходу використали та інше. Бо воно тупо не працює. А якщо щось працює не так, як треба, то це нікому не потрібна фігня. Разом з архітектурами, патернами, назвами змінних, тощо.

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

Якість в кожного своя. В мене якісний код має наступні ознаки:

  • На 150 відсотків виконує бізнес-задачу
  • Легко модифікується під нові бізнес-задачі
  • Не вимагає додаткових зусиль на його підтримку

Якість в моєму світогляді диктується виключно економікою. Кодошедевр, який нікому не цікавий окрім його автора, не вартий нічого. Це звучить образливо для багатьох програмістів, бо дуже сильно спаплюжена система координат та обрані неправильні ознаки крутості. Бізнес продає не круті архітектури, не повноту покриття тестами, не патерни та кодстайл, не наявність документації та CI/CD процедур. Бізнес продає рішення проблем кінцевих споживачів. Якщо твій код, який написаний лівою ногою, може швидко задовольняти сьогоденні та майбутні проблеми бізнесу, то це і є шедевр. Хоча більшість скаже, що це шмат соковитого лайна.

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

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

Я не понимаю как ты связываешь то что написал с разговором «что есть качество»

Приведи ознаки якісного коду. За твоєю версією.

Добавлю. Приведи признаки, да так, чтобы можно было пропустить этот «качественный код» через особый тул, который скажет что-то вроде «поздравляю, ваш код качественный на 87% и удовлетворяет 92 признакам качественности из 134». А то сейчас начнется «loose coupling», «Low cohesion» и прочая эзотерика.

я не знаю как сформулировать это так чтобы не пришлось писать несколько экранов текста

Тобто, всі ваші оцінки якості є чимось примарними на рівні почуттів? Без жартів, раджу подумати над більш точним формулюванням власних оцінок якості коду. Це ж те саме, що й знайти правильні абстракції та гарно зробити декомпозицію.

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

Навіщо кілометровий? Можна витяжку лише. Основні постулати.

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

На 150 відсотків виконує бізнес-задачу

Ні, більше 146 не буває.

Блін... ото лоханувся... Ганьба мені

На 150 відсотків виконує бізнес-задачу

А где тут связь с качеством?

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

Разве изменение бизнес-требований может влиять на качеству уже существующего кода?

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

А где тут связь с качеством?

Добре що ти почав задавати такі запитання. Можна вважати, що половина шляху пройдено.

Для того, щоб зрозуміти, що є якісна робота програміста, треба спочатку дати відповідь на запитання, а що саме робить програміст? Виконує задачі? Пише код? Звичайний, пересічний галермен так й робить. Це не погано, це просто факт. Але профі робить інше. Він спочатку розбирається в задачі, в умовах її виникнення, в матчастині, в тому, що саме автоматизується, а вже потім робить реалізацію.

Вот например интеграция с платежным сервисом на 150 процентов выполняет бизнес-задачу проведения оплаты картой.

Ось тут підміна сутностей. Інтеграція з одним платіжним сервісом не факт, що дає 150% від задачі. Тому що задача бізнесу звучить не «написати інтеграцію з платіжним сервісом А», а «дати можливість клієнтам з усього світу платити за товари та послуги». Спрощений для реалізації варіант вже звучить звично для вух пересічного виконавця: «написати інтеграцію ...».

Так ось, з точки зору програміста він може на 150% проходити програмістські критерії якості. З точки зору бізнесу цей код може не виконувати й 10% реальної бізнес-задачі. То й чхати, що там 100500 тестів, CI/CD, документація, та ще купа «крутих» фішек, бо вони ні на йоту не наближують до виконання решти 90%.

Разве изменение бизнес-требований может влиять на качеству уже существующего кода?

Так, якщо критерії якості не в покритті тестами, а в виконанні реальних бізнес-задач. Наприклад, замовник просив вас зробити формування замовлення в цілих одиницях товарів. В нього на той час дійсно не було можливості працювати з більш дрібними частками. Ви реалізуєте систему, яка починаючи від створення замовлення, закінчуючи звітами, оперує лише цілими одиницями. Потім приходить вимога додати дрібні частки.

Все, написаний код в більшості випадків стрімко стане неякісним, бо його прийдеться суттєво переписувати. А це є першою ознакою якості коду. Недостатня архітектурна продуманість.

якісна робота програміста

!=

якісний код

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

Качественная работа программиста очень привязана к контексту того что в данном конкретном случае является критерием «качественно».

Результат роботи програміста — його код. Навіть повна відсутність коду може бути ознакою якісної роботи програміста. Але, саме код робить роботу якісною. Не робота — код.

Виходячи з цього, формулювання «робота виконана якісно, тому що код якісний» — вірне, а висловлювання «код якісний, тому що робота якісна» — ні.

повноту покриття тестами, не патерни та кодстайл, не наявність документації та CI/CD процедур.

Не путай твердое и квадратное. У бизнеса свой головняк — у тебя свой.
Вот єто из цитаті можно сократить до одного понятия «чтоб после полгода ті сам догадался чего єто чудо делает и на что его проверяли. И чтоб я или еще какая обизяна смогла чего то там поправить или поменять»
А вот следить за этим, чтоб азь не сделаль

код, який написаний лівою ногою, може швидко задовольняти сьогоденні

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

И если этих процессов нет, например в стартапе,

Хм, а каким средством вы пользуетсь, чтоб мозг запустить утром в понедельник?

А шо таки уже не?

Ты чего, может и на кресты положил? Я то думал, что это у вас там обычай, тип помесь наркомовских и саке

чтоб после полгода ті сам догадался чего єто чудо делает и на что его проверяли.

Це лайнокод.

И чтоб я или еще какая обизяна смогла чего то там поправить или поменять"

Так, уяви собі!

Ну вот это все тип ревью и т.д.

Код-ревью кардинально не поліпшує якість коду. Тільки ситуативно виправляє деякі симптоми.

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

Це пряма ознака лайнокоду. Не треба так робити.

Люто плюсую. Такая жиза.
«Ау, тестировщики, почему так много багов? Когда все будет пофикшено?!»

А почему разраби не могут писать без бажин

Потому что разрабы — Йожины.

Без картинки камент не проходит ревью. Требую показать образ. Старый уже, фантазии не хватает. (Вернее сдерживаю)

Философствование на тему нужно или не нужно TDD возникает когда качество результата работы вторично и не важно. Если качество на первом месте только TDD может привести к результату за разумное вермя. Все остальные методологии разработки либо никогда не приведут к желаемому результату (желаемое качество не достижимо) либо потребуют намного больше ресурсов (типа анализ и математические доказательства, батальон QA инженеров и т.д). Да и вообще если нужно качество то все это будут применять одновременно.

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

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

Не используют, потому что цели другие. Быстро, качественно и дешево — выберите две.

Он тестирует продукт с точки зрения конечного пользователя и каждый раз заново (результаты не сохраняются)

Уже давно есть QA automation как раз для того чтобы результаты были всегда сохранены пока не будут признаны устаревшими.

Хотя как по мне дело не в этом, а в том что QA не заменяет юнит тесты.

Если качество на первом месте только TDD может привести к результату за разумное вермя.
только TDD может

Всё, началась религия. Дальше можно не читать.

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

причем я не отрицал достижение качества другими путями.

Ваши слова?

>>

Если качество на первом месте только TDD может привести к результату за разумное вермя.

От добавки «за разумное время» факт религиозности тезисов не уходит.

Спасибо за совет, но поздно — уже прочитал.

ТДД никак не влияет на качество решения, только на наличие тестов — собственно это единственное что он дает

только на наличие тестов

Я бы не сказал. При условиях большого процента покрытия (на CI) код вполне успешно покрываеться недо-тестами и без TDD.

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

Это не про TDD, а про интеграционные тесты

а кому вообще нужны юнит тесты?

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

ну то есть кто за TDD aka

бесполезный ананизм

готов платить в мире аутсорса?

интеграционные тесты.

Шта токое в вашем понимании интеграционные тесты ?

заказчику вообще похер

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

ну то есть кто за TDD aka

бесполезный ананизм
готов платить в мире аутсорса?

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

а кому вообще нужны юнит тесты?

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

гребцу помогают компилятор, IDE и интеграционные тесты.
завтра энтерпрайз-залипуху выкинут

Не все пишут бесполезные энтерпрайз-залипухи.

готов платить в мире аутсорса?

Аутсорс бывает разный. Сейчас, например, очень много automotive.

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

Так на галерах переважно друге. Тоді нафіга робитити покритя тестами під 100%?

Так на галерах переважно друге.

«Переважно» — це не «суцільно», і крім галер ще багато чого є.

Тоді нафіга робитити покритя тестами під 100%?

Я і не пропонував. Я пояснюю, чому юніт-тести можуть бути необхідними.

Сейчас, например, очень много automotive.

и где вы видели для алгоритмов ml юнит-тесты?

Препроцессинг и постпроцессинг данных вполне можно покрыть тестами.

Или в модели для машинного обучения можно уже слать всякую фигню и получать магический результат?

это называется integration test, потому что тестируется часть пайплайна. так что нет, unit тесты не нужны.

Если покрывают отдельные методы для обработки данных это юнит тесты.

а зачем тестировать отдельный метод, если он часть ETL? времени много свободного? пишите сразу rich integration.

или у вы на big data с монолитом ходите?

А если не часть ETL?

это как? типа, какой-то метод самопиской библиотеки? тогда уместно, но это 5 процентов кода в лучшем случае.

Я говорил о методах и юнитестах. ETL и BigData вы добавили.

Препроцессинг и постпроцессинг данных

мы об этом говорили.

Эээ... а что вам дало основание переводить разговор на тему ML, видя только слова «алгоритмы» и «automotive»?

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

Понятно. Я про кровавый энтерпрайз и не говорил.

А юнит-тесты в ML, кстати, вполне могут быть. Представим себе функцию, которая просто прогоняет изображение через поисковую свёртку с вписанным в неё массивом коэффициентов. Мы не можем выловить граничные случаи, но проверка типа assertFalse(find(белое_поле, котик)) вполне полезна :)

Я согласен:) но ты явно не к тому комментарию ответ поставил.

Я показал пример, где без TDD будет очень сложно.
без TDD

Не в возражения основному смыслу комментария, но у тебя в слове «юнит-тест» 8 ошибок.

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

Полностью согласен. Добавлю, что тесты нужны также, чтобы проверить понимание логики библиотек. Вспомнили картинки — сам недавно с libtiff возился — если напрямую читать документацию, получается одно, а по факту — другое. Вот и рисуешь тест, чтобы, когда он сломался, заметить смену логики библиотеки раньше юзеров ;)

вот то что ты и говоришь и есть тестированием поведения системы а не имплементации.

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

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

вот то что ты и говоришь и есть тестированием поведения системы а не имплементации.

Для данного вопроса мне разницы нет.

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

Если для функции известно, что она в принципе иначе по ТЗ не может делать свою работу, как через эту либу — это будет как называться?

Если для функции известно, что она в принципе иначе по ТЗ не может делать свою работу, как через эту либу — это будет как называться?

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

Представим себе, что «предсказуемый результат» это открытие порта и запись байта в него, и единственный метод это вызвать системный open() с конкретным путём и конкретными опциями.

Значит надо проверит открылся ли порт, не вижу никаких проблем

Процитируй. И покажи, где я, по-твоему, неправ.

Понятно, ответа нет. Тогда иди сам читай, до просветления.
Hint1: для юниттеста неважно, как именно он организован, главное, что если тестируемая функция не выполняет что надо — будет ошибка.
Hint2: pytest, например, переделывает питоновские assert в свои вызовы проверки.

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

TDD — это методология, при которой вначале пишеться юнит-тест, а потом уже собственно сам код.

вообщето тдд это не только о юнитах

А о чем еще? В контексте кодинга слышал токо о юнитах.

TDD это вообще какой-то бесполезный ананизм. Хотя нет. Даже хуже. От ананизма хоть как-никак удовольствие есть.

TDD это вообще какой-то бесполезный ананизм. Згідний із цим твердженням.

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

Я пишу код только по TDD уже много лет, и постоянно ловлю баги. Это меня мотивирует продолжать использовать TDD. Когда я говорю TDD — я имею ввиду «red-green-refactor»

Например если мне надо сделать новый микросервис с новым эндпоинтом, например GET /customers/{id}/profile — перед тем как писать какой-либо код, я напишу тесты в которых я буду ожидать определенное поведение.
Я заранее найду ответы на вопросы (спрошу коллег):
— Что я ожидаю получить от сервера?
— Что я ожидаю получить если нет такого id?
— Что я ожидаю получить если customer с таким id заблокирован?
и так далее.
Когда я напишу тесты — они будут red, так как кода еще нет.

Следующий шаг — пишем код. Что мне нравится в TDD, что он помогает уменьшить количество кода. Если в процессе написания кода появляется вопрос «а что если я передам пустую строку в этот метод» — то есть два варианта. 1) Пишем тест который тестирует этот самый случай и думаем (спрашиваем) что мы ожидаем 2) Принимаем решение что это не важно (или никогда не произойдет) и оставляем поведение системы неопределенным. Нет теста — нет кода!

Когда все тесты зеленые — переходим к последнему шагу Refactor. Чистим код, переименовываем методы, удаляем дублирование и т.д.

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

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

И так каждый билд руками?

Если я ничего не путаю, то ТДД это вообще не о —

Например чтобы писать тесты для апи или для базы

Потому как ТДД == unit test.
unit test == тестирование изолированных блоков кода.
unit test !=

тесты для апи или для базы

Если интеграционные тесты можно запустить полностью локально а время их выполнения не влияет существенно на скорость разработки, то какие причины не считать описанное выше TDD, кроме религиозных, конечно?

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

Без таких крайнощів.

Добавил кроме code coverage sonarcloud и scrutinizer-ci. Теперь кроме обычного 100% покрытия тестами слежу за ошибками в кодоанализаторах и оценками для создаваемых методов.

TDD хорошо помогает только для всяких Pure методов или Pure библиотек по типу вход-выход.
Вообще unit тестирование — это неплохой механизм для библиотек в опен соурсе. И отлично в комплекте с live coverage.
В большинстве остальных случаев, больше гемора чем пользы.

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

Юнит-тесты полезны для всего,

Токо юнит тесты написанные после реализации куска, и ТДД это разные вещи.

Спасибо, кэп :) я TDD и не подразумевал.

TDD хорошо помогает только для всяких Pure методов или Pure библиотек по типу вход-выход.

Никто не мешает свою бизнес логику выражать чистыми функциями. Нужно хранить состояние?
Состояние может входить и выходить из функций. (State) -> State. Получаем иммутабельность, поэтому нужно будет сбросить ООП оковы.
Но если даже оставить мутабельность: (*State) -> Void — это то же самое, что и первая функция.
Обе функции легко тестируемые, если нет сайд-эффектов.

А как управлять сайд-эффектами и зависимостями, рассказано уже 100500 раз.
Вот хрестоматийный доклад от Gary Bernhardt:
www.destroyallsoftware.com/talks/boundaries

Да многие любят рассуждать об этом, в основном абстрактно.
Вот я бы с радостью увидел реализованный на github реальный enterprise проект построенный на TDD. Пока в реальной жизни не встречал таких проектов. Желательно с видео выполнения каких-то тасок.

Никто не мешает свою бизнес логику выражать чистыми функциями.

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

Вот я бы с радостью увидел реализованный на github реальный enterprise проект построенный на TDD.

TDD или не TDD — это личное дело каждого разработчика, а не проектная конвенция.

У нас в команде есть люди, которые всю разработку ведут по TDD. Я пишу тесты после — результат одинаковый. Продуктивность тоже. Но чтобы так было надо изначально писать тестируемый код.

Так и есть, для бизнес логики оно только и подходит.

А что ещё ты будешь тестировать? Как база данных запрос обрабатывает? Кому это нужно?

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

TDD или не TDD — это личное дело каждого разработчика, а не проектная конвенция.

До тех пор, пока не начинают требовать вначале коммита с тестами.

До тех пор, пока не начинают требовать вначале коммита с тестами.

Коммита куда? В рабочую ветку? Кому какое дело, что я делаю в своей рабочей ветке?
А Pull Request в master уже будет содержать сразу и код и тесты. Причем, я обычно сквошу все промежуточные коммиты в один и выставляю свой change на PR одним коммитом.

А как ещё менеджменту убедиться, что разработчики выполняют TDD, а не только рассказывают на словах?

А это надо спросить у того менеджмента.

Обе функции легко тестируемые, если нет сайд-эффектов.

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

когда в бизнес логике таки надо в средине сайд эфект сделать — записать\прочитать в базу

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

// Нетестируемое говно из-за скрытого сайд эффекта
func updateName(user: User, newName: String) {
    user.name = newName
    db.save()
}
Вот простейший рефакторинг:
// Тестируемая бизнес логика
func updateName(user: User, newName: String) -> SideEffect {
    user.name = newName
    return .saveToDataBase
}

// Простой и надежный юнит тест
func test_updateName() {
    var user = User(name: "Foo")
    let sideEffect = updateName(user: user, newName: "Grez")
    
    assert(user.name == "Grez")
    assert(sideEffect == .saveToDataBase)
}
Сайд эффекты, само собой, обрабатываются отдельно:
// По-сути, эта функция не нуждается в тестировании,
// так как она не содержит никакой бизнес логики кроме мапинга
// сайд-эффектов на сервисы. 
func perform(sideEffect: SideEffect) {
    switch sideEffect {
    case .saveToDataBase:
        db.save()
    case .httpRequest:
        ....
    case .writeFile:
        ....
    }
}

Можно протестировать один раз моками/шпионами.
func test_perform_ saveToDataBase() {
   perform(.saveToDataBase)
   assert(dbSpy.received(.save))
}

Этот код можно написать как по TDD, так и без него.

Пример уровня хелловорлд. Но этото уровень хелловорлд — глазаб мои развидеть. Что за мутируемый юзер ? Что за сферический

db.save()

в вакууме ?

Удти учить https://www.sitepoint.com/what-is-referential-transparency/ как отче наш. Без этого даже не хочу продолжать разговор.

Лол, у меня ощущение, что меня троллят.

Это максимально упрощенный псевдокод: db.save() в вакууме и мутируемый юзер — чтобы ты не ломал глаза об сигнатуры функций и вызовов, а сходу увидел суть предложенного рефакторинга.

Замени User на сложное состояние на 500 полей и db.save() на функцию с 30 параметрами, мутирование на иммутабельность — не изменится абсолютно ничего. Хоть выполнение HTTP запроса, хоть сохранение файла. Не имеет никакого значения.

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

Лол, у меня ощущение, что меня троллят.

Welcome to dou.

Это максимально упрощенный псевдокод: db.save() в вакууме и мутируемый юзер — чтобы ты не ломал глаза об сигнатуры функций и вызовов, а сходу увидел суть предложенного рефакторинга.

Подобный рефакторинг плох, за него бить по рукам. Смысла отделять сайд эффект от мутируемого состояния 0, оно только конфузить будет потом.

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

Ну ок, тупой пример: Бизнес логика — хотим по какомуто айди сделать хттп реквест; по результату найти запись в бд, чето там проапдейтить, записать, но одно из полей в этой записи это айди по которому повторно (рекурсивно) сделать следующий хттп реквест. и так по кругу 10 раз. Ну и плюс хотим посчитать время выполнения всего метода и схоронить в метрики.

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

Подобный рефакторинг плох, за него бить по рукам. Смысла отделять сайд эффект от мутируемого состояния 0, оно только конфузить будет потом.

Отвечу твоей же цитатой:

Это все хорошее бла бла

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

Ну ок, тупой пример:

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

Код писать не буду, потому что ты сам поленился это сделать. Но тесты напишу (псевдокод):

// Получили объект из ДБ - создается хттп запрос
func test_fetchedDBObject_message_returns_httpEffect()  {
  let object = DBObject(..)
  let actualEffect = handleMessage(.fetchedDBObject(object))
  let expectedRequest = HTTPRequest(...)
  let expectedMessage = .receivedHTTPResponse

  assert(actualEffect == .http(expectedRequest, expectedMessage))
}
// Получили определенный хттп ответ - создается команда для ДБ
func test_receivedHTTPResponse_message_returns_dbEffect()  {
  let response =  HTTPResponse(...)
  let actualEffect = handleMessage(.receivedHTTPResponse(response))
  let expectedQuery = DBCommand(...)
  let expectedMessage = .fetchedDBObject

  assert(actualEffect == .db(expectedQuery, expectedMessage))
}
// Получили другой хттп ответ - ничего больше не происходит
func test_receivedHTTPResponse_message_returns_ no_effects()  {
  let expectedRes =  HTTPResponse(...)
  let actualEffect = handleMessage(.receivedHTTPResponse(expectedRes))
  
  assert(actualEffect == nil)
}
Но твой пример, как ты сам заметил, тупой, потому что он эксплуатирует крайний случай со спамом сайд эффектов без логики вообще.

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

Что по сути скажешь? Суть этого рефакторинга в достижении тестируемости.

Скажу что такой рефактор не нужен, ибо он усложняет код без какой либо нужды или бенефита. Протестировать можно и моками.

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

Пример сферический, но легко разширить где там вовнутри логика тож будет.

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

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

Скажу что такой рефактор не нужен, ибо он усложняет код без какой либо нужды или бенефита. Протестировать можно и моками.

Моки не нужны ибо они усложняют тесты без какой либо нужды и бенефита. Протестировать можно надежными юнит тестами. Только нужно рефакторить.

Пример сферический, но легко разширить где там вовнутри логика тож будет.

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

Ну если бизнес логика уровня хелло-ворлд (хотя чего ожидать от джава скрипта), то тогда да

О, давай ещё шутки про PHP. Хотя хз, где вообще ты Js увидел — очевидно, что для подобного подхода предпочтителен строго типизированный язык.

Но опять же таки, если логика уровня хелло-ворлд смысл ее отягощать всем этим, если можно протестировать моками ?

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

giphy.com/gifs/l0MYSpvx4pnsoMNz2
Unit test vs. integration test

UP: Под словом «тесты» я подразумеваю именно использование методологии TDD, а не просто сферические Unit-тесты в вакууме.

Мой ответ: Потому что то, что я видел, это ужасс в квадрате....

Происходило это так —
есть спецификация программного модуля.
И понеслось !!!

loop for 1..n:
тесты — моки — рефакторинг — новые эл-ты интерфейса — меняем тесты..

n = <пока заказчику это все не надоест>

В итоге все это запускается и работает и потом в один момент виснет, потому что TDD ничего не знал о лимитируемой очереди CLOSE_WAIT сокетов...
--------------------------------------------------------------------------------------------------------

Другой модуль (аналогичный по объему ф-ционала) делается следующим образом:

— есть спецификация программного модуля.
— разрабатывается архитектура (ага, та самая с диаграммками).
— пишется код
— пишется набор функциональных тестов под АПИ модуля. Тесты эти ни к какому рефакторингу не приводят (в большинстве случаев)!!!

В результате второй вариант прекрасно работает, пишется в разы быстрее и прекрасно эстимэйтится.

Первый вариант с ТДД писал не какой то студент , а сеньор, который начитался умных книжек ГУРУ-КОАЧЕЙ-мега_крутых_чуваков_ТДД ...

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

Кстати, как то последние 3 года эта тема с ТДД как то приутихла ...?

— есть спецификация программного модуля.
— разрабатывается архитектура (ага, та самая с диаграммками).
— пишется код
— пишется набор функциональных тестов под АПИ модуля. Тесты эти ни к какому рефакторингу не приводят (в большинстве случаев)!!!
А теперь как работает ТДД:
— есть спецификация программного модуля.
— разрабатывается архитектура (ага, та самая с тестами).
— пишется код
Итого −2 шага:
1 тот который про диаграмки;
второй тот который вы не указали, с ручным тестированием после окончанию определенного куска работы.
В итоге все это запускается и работает и потом в один момент виснет, потому что TDD ничего не знал о лимитируемой очереди CLOSE_WAIT сокетов...
Если программист не знал про что-то там, то он не реализует это ни по ТДД, ни по другому подходу (этой вашей очереди банально не будет на «диаграмках»).
тесты — моки — рефакторинг — новые эл-ты интерфейса — меняем тесты..
Очень похоже на антипаттерн именуемый «туториал тдд».

Потому что можно включить режим фольцвагена и толк от такого TDD будет стремиться к 0

Тому що покривати тестами слід те, що має для цього раціональний сенс. Бачила випадки коли девелоперів примушують покривати тестами геть усе. Виглядає дивно і марнує час (і гроші).

void show_error(char *err_msg) { fprintf(stderr, "Error occured: %s\n", err_msg); }
напишіть тест, ага

UPD: тут взагалі є функція перегляду коментарів перед надсиланням? Де почитати про те, як працюють тут теги?

void show_error(char *err_msg) { fprintf(stderr, “Error occured: %s\n”, err_msg); }
напишіть тест, ага
От такая вот история:

1) вызов show_error не является критическим требованием.
Вы обязаны проверить что ваша программа делает в “негативном сценарии”. А в негативном сценарии она так же будет вызывать и show_error. Шазам и вы получили покрытие на шару.

2) вызов show_error является критическим требованием.
Тогда вы должны определить необходимую степень абстракции и или замокать fprintf, или переопределить/перенаправить вывод stderr.

Тогда вы должны определить необходимую степень абстракции и или замокать fprintf, или переопределить/перенаправить вывод stderr.

Осталось выяснить зачем.
Осталось выяснить зачем.
Потому что
2) вызов show_error является критическим требованием.
То есть на выводе этой строки в лог завязана важная логика.

Критичні вимоги до ПЗ зазвичай абстрактні. Девелопер створює процедури та функції для виконання цих вимог або некритичного функціоналу. З такої точки зору, некритичний функціонал не треба покривати тестами.

Функції і процедури, що виконують логіку ПЗ є сенс покривати тестами. Причин перевіряти ті, що цю логіку використовуюсть не бачу, окрім випадків, коли тестування результатів є в скоупі роботи ПЗ, що буває дуже рідко.

З такої точки зору, некритичний функціонал не треба покривати тестами.
Ага, надо научится читать:
А в негативном сценарии она так же будет вызывать и show_error. Шазам и вы получили покрытие на шару.

Я не мала на увазі конкретно мій випадок, а «в цілому».

Я не мала на увазі конкретно мій випадок, а “в цілому”.
Вы не поверите, но я тоже имел ввиду в целом.
Будете придумывать новые ситуации на которые “напишіть тест, ага”? К слову, их мало, но они таки есть, поэтому обычно требуют 95-97% покрытия.

Ми, мабуть, неправильно одне одного зрозуміли.

Проте, мені було б цікаво розібрати кілька прикладів. :)

Ответ на этот вопрос

Почему 95% разработчиков не используют TDD?
такой же как и на большинство других и уже давно дан Старджоном «90 процентов чего угодно — ерунда». К разработчикам тоже относится. Плюс/минус 5% — не в счет :D

Потому что в реальных проектах разработка идет не как «вот тут есть полная спцификация, давайте закодим», а «у нас есть идея, давайте сделаем MVP и посмотрим, что получится». И факт того, что никто не знает всех деталей реализации и что где упадет по пути никого не пугает. Удачи с тестами и рефакторингом раз в неделю.

Потому что в реальных проектах разработка идет не как «вот тут есть полная спцификация, давайте закодим», а «у нас есть идея, давайте сделаем MVP и посмотрим, что получится»

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

Ну OK, пишемо MVP. Додаємо метод, всередині 3-5 гілок логіки.

Написати тест, котрий зажене метод у потрібні стани — справа кількох хвилин. На фініші отримуємо:
1. 100% впевненість, що все працює так, як ми очікували (лишається проблема що ми могли щось провтикнути і з очікуваннями, але це до першого виявлення багу — потім додається ще один кейс і у нас все добре).
2. Коли наступного разу в код вноситимуться зміни — якщо щось поламається — тести впадуть, гарні шанси виявити нюанси що можуть привести до реальних багів.

Але це тільки «тактичні» переваги.

Мені більше подобаються «стратегічні». Коли пишеш тести — щоби писати менше, доводиться писати кращий код. :) Менше зв’язності, менше жорстких залежностей на зовнішні системи і т.п.

Звісно, як і всюди, тут багато всяких крайностей котрі можуть легко згівнякати всю ідею. Але якщо робити це правильно — тести рулять. На всіх проектах, без вийнятків — стартап, не стартап — пофігу.

Але якщо робити це правильно — тести рулять. На всіх проектах, без вийнятків — стартап, не стартап — пофігу.

Какие громкие высказывания=) Представим проект — обычное веб приложение, но 100% бизнес логики в процедурах в бд. Бекенд просто дергает эти процедуры и передает параметры с UI. Что вы будете тут тестировать?)

Ага, еще SSDT есть, но мы говорим про тестирование нашего бекенда а не его зависимости.

6 июля 2016

Здравствуйте.

1. 100% впевненість, що все працює так, як ми очікували (лишається проблема що ми могли щось провтикнути і з очікуваннями, але це до першого виявлення багу — потім додається ще один кейс і у нас все добре).

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

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

потому что 99% задач надо было выкатить на прод еще позавчера, а клиент сказал о них сегодня вечером

потому что 99% задач надо было выкатить на прод еще позавчера, а клиент сказал о них сегодня вечером
И этот факт нам оставляет кучу времени на то чтобы все необходимое тестирование, проводили КуА :)

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

Почему дешевле? Юнит тесты проверят весь покрытый код за секунды/минуты, а QA будет тестировать часы и проверит малую долю функционала.

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

лол юнит тесты проверяют????
шо они проверяют????
люди покрывают баганный код тестами прикинь. Такое бывает

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

содержать отдел QA инженеров банально дешевле, чем содержать отдел синьоров-с-зеркалками которые будут тратить своей девелоперское время на тестирование.
О уже дешевле :)
1) Это не правда. Хотя бы если учитывать что тесты надо прогонять больше чем 1-2 раза. А если посчитать что через некоторое время (где-то через год в проде) у вас количество КуА будет превышать количество разработчиков и бардак будет такой что прибыль у вас будет расти только недополученная, то все еще веселее.
2) Мы же говорили о том что фичу надо выкатить на вчера. «Дешевый отдел КуА» справится с задачей проверки быстрее чем средненький сервачек?

То есть вы серьезно считаете замену КуА юнит тестами адекватной??? О_о

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

А вы серьёзно считаете, что, говоря о преимуществах автоматизированных тестов, оппонент сразу говорит о замене QA???
«O_o» ©

Там не говорили о реальном автоматизирование это раз, и там юнит тесты позиционируют как замене куа, потому и в корне не согласен, точнее в шоке

Там не говорили о реальном автоматизирование это раз

А? Я не могу понять реплику Богдана Ш. иначе, как рекомендацию автоматизировать.

и там юнит тесты позиционируют как замене куа,

И снова очень странно. Он говорит, что при отказе от тестов QA раздуется до невменяемых размеров. Но это не значит, что при наличии тестов QA не будет. Банальная логика: из A=>B не следует B=>A.

хмм... может я попутал его комент с коментами автора топика...

То есть вы серьезно считаете замену КуА юнит тестами адекватной??? О_о
В такой формулировке, ответ нет.
Вот пара наводящих тезисов:
1) Не полную замену
2) Не только юнит-тестами (есть еще куча других)
3) ТДД привносит дисциплину, что уменьшает риски
4) ТДД привносит практику автоматизации, что уменьшает затраты на ручную работу
2) Не только юнит-тестами (есть еще куча других)
3) ТДД привносит дисциплину, что уменьшает риски
4) ТДД привносит практику автоматизации, что уменьшает затраты на ручную работу
согласен, только не согласен с тезисом о замене

А мне не нравится писать тесты до.Это ограничивает мои творческие порывы... я серьезно... и не хочу себе мозг ломать даже ради заказчика) ... пишу тесты после кода и покрытие не хуже чем при ТДД

А у автора вопрос про «настоящий», «рафинированный» TDD в виде «красный, зеленый, рефакторинг» или про использование тестов вообще?
В заголовке есть слово «TDD», но при этом «третьи не пишут тесты», поэтому не ясно.

Если на проекте, как минимум, основной функционал покрыт тестами и есть работающий CI, но тесты не всегда были написаны кода, который они, собственно, покрывают, этот случай входит в 95% или в 5%?

да, тут и большинство комментаторов в кучу всё смешали.
и ничего, большинство на одной волне

Ага по моему автор сам намешал все в одну кучу люди-кони...
Покрытие кода юнит тестами это как бы совсем одно.
А вот ТДД это совсем как бы другое.

Вариантов масса, выбирайте

1) Потому что 95% разработчикам не нужно TDD для решения их задач?
2) Потому что на 95% проектов не нужно TDD для решения задач?
3) Потому что 95% разработчиков, вооружившись TDD, устроят месс на проекте еще быстрее, чем без TDD?
4) Потому что на 95% проектов попытка внедрения TDD загонит все в медленнодевелопящийся месс еще быстрее, чем отсутствие TDD?
5) Потому что 95% разработчиков дизайнят архитектуру инплейс и необходимый для нормального тестового покрытия уровень декомпозиции недостижим?
6) Потому что на 95% проектов... ну вы поняли.

Декларуйте інтерфейси на початку і узгоджуйте їх зі всіма і не буде в вас геморою,якщо не хочете TDD використовувати.

Почитал коменты и вижу что главная причина почему не используют ТДД — это отсутсвие понимания такого процесса разработки в целом + отсутствие практического опыта успешного применения ТДД. Т.е. люди привыкли работать определенным образом и что бы эту привычку поменять мало прочитать про ТДД — нужно попробовать и доказать себе что с ТДД лучше.
Вторая причина — ТДД сложнее. Что бы его применять успешно — нужно очень хорошо понимать как это делать правильно. Поэтому многие пробуют — ошибаются и потом плодят мифы что с ТДД дольше, дороже, нужно иметь спеку — и т.д.
Можно сказать что с ТДД разработка дольше — но дольше она не за счет тестов, а из-за необходимости думать вперед, поддерживать хорошую архитектуру и избегать технического долга.
Как правильно написали: проект, который с ТДД напишут за 3 месяца можно написать вдвое быстрее если применять методику тяп-ляп и в продакшин. С этим сложно поспорить.
В этом, я считаю, главный плюс правильной методики разработки — технический долг просто не получается накапливать. Если пытаются что-то заткнуть костылями по-быстрому — то сразу значительное колличество тестов становятся красными, падает степерь покрытия и т.д. Дальше, обычно, поломанные тесты начинают выкидывать что бы не тратить время — и покрытие падает еще больше.
В хорошей компании должен быть человек, который мониторит метрики проектов. И такая ситуация прекрасно сигнализирует о проблемах на проекте, даже если ПМ и техлид уверяют что «все под контролем», «мы успеваем» и т.д. Но если это не «одноразовый» проект — то задача начальника более высокого уровня думать наперед: сегодня они «успеют» налепив костылей — а через полгода скажут что проект «не интересный» — и уволятся. Новым людям придется долго вникать и еще дольше разгребать технический долг. Или продолжать лепить костыли пока проект окончательно не сдохнет под их весом.
Вообщем хотите правильно делать ТДД на .Net — спросите меня, как.

но дольше она не за счет тестов, а из-за необходимости думать вперед, поддерживать хорошую архитектуру и избегать технического долга.
Це задача-мінімум програміста. При будь-якому підході розробки. На будь-якому проекті.
е задача-мінімум програміста. При будь-якому підході розробки. На будь-якому проекті.
Угу, где-то far far away in another galaxy :)). На самом деле я всеми конечностями за, но оказывается в реальности совсем наоборот — кастомер требует чтоб было, и в 90% случаях надо побыстрее а то \метеорит\атака ситхов\очередной апдейт Пингвина, а что там у тебя под капотом — твои проблемы ты ж специлаист. И никто в сроки лишнего не закладывает...А еще чаще нужно на вчера... И сидит такой, юный Эникен, пишет тесты, потом выстраивает SOLID архитектуру, затем все это дебажит, а потом приходит ПМ и говорит что ж ты козел, написал то только мизер проекта, в то время, как Вася Фигачкин уже сдал 3 таски ??? И пофиг что Вася исповедует садистки перевернутый принцип KISS ака я вручную обфусцирую код аля я напишу а потом пох. И еще получит +500 спустя полгода к ЗП. И ничего не остается Эникену делать, как переходить на темную сторону Силы ;)

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

Гарний стимул розвиватися як професіонал: шукати кращі ніж є зараз підходи, архітектури, патерни, поліпшувати існуючий процес. Все життя ж не будете лайнокодити, правда?

Расскажите это заказчикам, которые трясуться за каждый час.

Навіщо таких замовників шукати?

А как их отличать? На детекторе лжи?
По всем разговорам, там всегда инновационный проект из компании лидера рынка.

задача-мінімум програміста

Понять КПИ по которым тебе засылают бабло. Потом понять как можно его повысить. А так вообще то суть в окружении/фирме и ее требованиях

Нормальним програмістам КПІ не виставляють. Це безглуздо.

В целом согласен. Но вот это никогда не работает и работать не может:

В хорошей компании должен быть человек, который мониторит метрики проектов
.

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

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

Конечно работает. Вот только опыт и чутьё техлида Васи не есть метрика. Метрики — это другое.

Метрики — это в дженкинсе (или где), горит билд красным «ололо мало тестов». Приходит вышестоящий менеджер, который вооще не в курсе что происходит и выписывает люлей. И ничего что продакшн горит, и вообще проблемы другие.

Точно! Как то раз требовали покрытия кода 80%, вот это было ололо. В итоге 80-90% времени тратилось туда — на покрытие get/set и конструкторов.

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

И ничего что продакшн горит, и вообще проблемы другие.
Но если это не «одноразовый» проект — то задача начальника более высокого уровня думать наперед: сегодня они «успеют» налепив костылей — а через полгода скажут что проект «не интересный» — и уволятся. Новым людям придется долго вникать и еще дольше разгребать технический долг. Или продолжать лепить костыли пока проект окончательно не сдохнет под их весом.
Проект развивался и развивается порядка уже 15 лет.. Я пришел на него, когда думал также, как и большинство в треде — нах те тесты, и вообще, у миня работает!!Адинадинадин!! Но в один прекрасный момент у нас кол -во мануал QA оказался критично низок для проекта.. А тикеты все заходили, все серьезнее и серьезнее — перефигачить знатную часть тех же урлов для гугла, для примеру..Рассказывать ли что случилось дальше?

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

Можно сказать что с ТДД разработка дольше — но дольше она не за счет тестов, а из-за необходимости думать вперед, поддерживать хорошую архитектуру и избегать технического долга
Очень верно заметили! Спасибо за комментарий.
Почему 95% разработчиков не используют TDD?
— потому что говнокодеры, сэр!!!
потому что говнокодеры, сэр!!!

мизантропия она такая. А примерно то же девы говорят про дизайнеров громко, и про ПМ —тихо. И про КУа тож, когда читают репорты.

А чё ты понимаешь в дизайне. Оне так видят, а ты стоял на пути потока позитива.

Ждем темы «почему 95% программистов не верят в господа нашего Иисуса Христа».
Потому что ммм... это вопрос веры?

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

А другой, не менее важный нюанс — это цель. Когда мы пишем код, наша цель, чтобы он работал, чтобы он вписывался в существующую систему, чтобы он был отказоустойчивым. Типа если через 2 года бекенд в этом месте станет возвращать вообще другое, а юзер до сих пор не проапдейтил аппу, как мы тут обработаем. Наша цель — написать код, описывающий поведение системы в 100% возможных ситуаций.

А с ТДД у нас какая цель? Удовлетворить тесты (я молчу, что написанные нами же). То есть написать код, который в некоторых условиях работает правильно.

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

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

Тут кстати несогласен, как показала практика далеко не каждый студент может написать код чтобы он сразу работал. Даже очень синьйористые синьйоры давольно частенько мелкие копи-пейст ошибки допускают. Помогут ли копи-пейст юнит тесты эти ошибки исправить — большой вопрос.
Помогут ли копи-пейст юнит тесты эти ошибки исправить — большой вопрос.
 100% гарантии ничто не даст, но как раз вот эти мелкие ошибки юнит-тестирование часто вылавливает за счет перепроверки скопированного.

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

И получится BDD, а не TDD.

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

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

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

И вот в этом «прямым текстом» чаще всего и получается «смотрю в книгу — вижу фигу». Там, где не ожидаешь подвоха.

Слишком долго. Чаще всего не заложено время даже на 30% покрытие.

У Scrum час на програмування закладають самі програмісти; їхнє завдання при цьому, зокрема — врахувати модульне тестування.

У Scrum час на програмування закладають самі програмісти

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

То, что Scrum ее популяризировал — это да.

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

Пишу через TDD хранимки для MS SQL Server’a на tSqlt, вполне облегчает разработку

это дорого по времени и все хотят получить результат уже вчера. Но мы все должны призновать ся что нам нужны тесты для того чтобы понимать где у нас аукнется после изменений одного условия в регистрации пользователя или установки дополнительной проверки на заказе. поэтому нужны тесты. Но всегда был вопрос на каком уровне.
Мы решили что 10% TDD достаточно, а вот 90% тестов на уровне UI нам подскажут что происходит! ведь кроме методов мы должны поддерживать старые данные.

Мы решили что 10% TDD достаточно, а вот 90% тестов на уровне UI нам подскажут что происходит!
Мне одному эта фраза звучит как шизофренический бред?

Половина сообщения — поток сознания.

Напевне автор хотів сказати, що 10% функціоналу покривається тестами, а все інше вручну перевіряється :) Але то вже явно не TDD :)

Ручное тестирование есть. Но uiмона проверять автоматами типо селениюм вот мы его и используем чтобы проверить сразу и все браузеры

10% это важные глубокие места проекта со сложной локикой которые надо проверять на том уровне. Остальное в реальности является чистым чтение и отображением одной и той же инфы — так что достаточно проверять на уровне отображение что да и как проверяется и что при какие данный как реагирует. У нас небольшой сайтик с пару букентов и аналитикой. Думаю сайты со сложной локикой пишут больше глубокого тестинга а обычным незачем в реалии делать так как код простой и тупой считал и показал при этом все только для чтения.
И да в основном только задроты которым важен не результат а сам процесс разработки сидят и жуют тему постоянного абсолютного покрытия тестами. Люди проснетесь вы должны понимать и осознавать еще и нужность тупых покрытий. У вас в 30% это api оно покрывается на все 90% а остальное в реальности не надо так реально покрывать!! Икономте жизнь она у вас одна — надо тратить разумно.

Мне показалось, что это толстая шутка.

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

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

Test-driven development — это воплощение идеи «ленивых вычислений» в самом программисте.

Тебе облом. Тебе ОБЛОМ. Тебе облом в кубе. Но надо делать. Ты смотришь на обломки старых недоделок. Ты понимаешь, что нет никаких сил разбираться во всём этом, тебе абсолютно по барабану, что внутри делается каким кодом и почему. Но тебе НАДО это сделать.

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

Наконец заработало, ты его спихиваешь и с чистой душой идёшь в отпуск.

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

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

А вот эффективность тут не рассматривается. :)

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

Почему 95% разработчиков не используют TDD?
Потомучто овер 99%. Ибо глупость. Фактически разработка детальных спецификаций эквивалентна написанию кода. Ну так зачем выделываться? Лучше сразу написать код, потом можно и тесты присобачить. В крайнем случае переписать по быстрому. По факту тесты нужны для двух вещей — фиксация логики и дебаг/отладка куска кода в отрыве от остального проекта (если проект большой собирать-запускать-отлаживать его трудно и долго)
Фактически разработка детальных спецификаций эквивалентна написанию кода.
Лучше сразу написать код
А что ваш код будет делать?

Ключевое слово детальных. Какойто спек есть всегда. Пусть даже устный. Иногда и так хватает.

«Х%як-х%як и в продакшн» — опасно.
«Семь раз отмерь, один раз отрежь» — долго.
«Семь раз х%як, один в продакшн» — наш выбор.

Потому что гонятся за скоростью, а не качествам. Что ни говори, а ТДД медленный.

В том то и дело, что с тестами НЕ медленней. Это миф, что тесты писать долго. На само по себе написание кода тратится максимум 10% времени в общем цикле разработки более-менее сложного проекта.


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

И тогда вы поймете почему с тестами можно двигаться намного быстрее.


Обычно говорят «что с тестами медленней» те, кто в жизни ни одного проекта по TTD не сделал или даже не пытался.

TDD аж никак не исключает, и не помогает в:

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

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

лично моё наблюдение, с TDD я выкачу проект за 3 месяца который без TDD выкачу ну максимум за 5-6 недель, с одинаковым качеством кода, и возможно скрытыми мелкими багами.

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

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

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

То тобі не потрібні вони. Ти досяг просвітлення

Как знать наверняка, что какое-то небольшое изменение ничего не поломало, без тестов?

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

один ФАТ вместо тысячи юнитов,,,

две причины:
1. не хочется
2. ссыкотно

развернуто: не видит профита для себя лично или для проекта/команды. или видит дополнительные(реальные или мнимые) риски для себя лично или для проекта/команды.

а чего вы от ответа на свой вопрос ожидали-то?

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

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

Не могу назвать себя экспертом в этой области, но думаю, что надежность в Боинге достигается именно благодаря банальным тестам. То что «тесты гарантируют, что программа не сломается» никто не говорил, но они являются одним из самых распространённых способов уменьшить вероятность сбоя программы или свести сбой к чему-то менее катастрофичному. Я понимаю что в NASA ученые на доске математическим путем доказывают невозможность сбоя того или иного расчета, но не думаю что это сильно распространённый способ в рядах программистов всего мира, а вот тесты как бы это ни отрицали некоторые программисты все же являются таковым. К тому же мое сообщение было вовсе не о полезности или бесполезности тестов, а о том что мы делаем то — что заказывает заказчик и не более. Вот если бы Вы написали в оппозицию моему утверждению что есть множество программистов которые готовы в свое личное время пописать тесты для рабочего проекта, вот тогда бы Ваше сообщение не было бы так похоже на троллинг способствующий разжиганию очередной Holy War.

Якщо я б хотів розпалити черговий HolyWar, я б почав з образ.
А так я просто акцентував увагу на результатах бажання тестувати. Є два світи: в одному програмісти не можуть жити без чергової дози тестування, а в іншому — роблять все, щоб не тестувати (ігнорування проблеми сюди не входить). Якість кода зазвичай вище у других. Бо тест дає примарне відчуття того, що все правильно, що код працює, що помилок немає. :) На цей гачок попала купа людей. І кожного разу результат однаковий — баги все одно є. Хочете навчитися писати нормальний код? Перестаньте тестувати. ;)

Программисты из Боенг с Вами не согласны и это все так же офтопик. Но конечно каждый имеет право на свое личное мнение.

Якщо я б хотів розпалити черговий HolyWar, я б почав з образ.

Ви вже робите образи:

в одному програмісти не можуть жити без чергової дози тестування,

такий прозорий натяк на некеровану залежність не можна зрозуміти інакше.

Якість кода зазвичай вище у других.

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

Хочете навчитися писати нормальний код? Перестаньте тестувати. ;)

«Миши, станьте їжаками». Ні, це не працює за межами окремих унікумів, і не працюватиме в скіль-небудь великому проекті. І от як раз в доказ цього є сотні історій великих проектів.

такий прозорий натяк на некеровану залежність не можна зрозуміти інакше
Тестування — це найпростіший спосіб боротися з проблемою. Мозок лінивий, він не хоче вигадувати щось нове, коли є варіант, який приносить заспокоєння та знімає тривогу. Тому це проста фізиологія. Набагато складніше заставити себе по триста разів перевіряти свій код, уважно його модифікувати, правильно зробити декомпозицію тощо.
Такі ствердження зазвичай потребують доказів.
Логічний підійде? Практичний теж можу, але його доказувати складніше.
Простий приклад. Будуємо систему трансформації різноманітних HTML в певний формат (стандартний для клієнта). Найпростіший спосіб вирішення задачі — взяти темплейт систему та вручну створити правила. Більш складний спосіб — використати XSLT. Чи може гарантувати такий підхід 100% нормальну робочу функціональність? Ні. Чи можна створити тест, який би гарантував хоча б щось? Ні. Проблема в тому, що вхідна структура HTML не фіксована, завжди може з’явитися код, який нам все або зламає, або тупо неправильно буде відпрацьовуватися. Що можна зробити, щоб гарантувати хоча б якусь надійність нашого трансформатора? Ставити ще один крок попереду — валідацію XSD на очікуваний формат. Якщо документ не буде задовольняти структурі, яку ми вміємо трансформувати, то ми можемо направити його в іншу систему, наприклад сповістити оператора, що сталося виключення з правил. Тепер наша система вміє «виправляти» баги та не падати, коли прийшла неочікувана структура. Вона, так би мовити, сама буде тестувати себе.
Як розробник буде розробляти цю систему? Використовуючі живі дані. Писати правила, запускати систему, отримувати помилки, виправляти, запускати знову, поки не буде нормального результату. Такий собі TDD без чистого T :)
Ні, це не працює за межами окремих унікумів, і не працюватиме в скіль-небудь великому проекті
Правила написання коду в великих компаніях працюють? Працюють. Різні методології розробки? Так. А якщо прийняти, що нетестування — це одна з методологій розробки кода? Чому от саме такий підхід мусить зафейлитися?
А якщо прийняти, що нетестування — це одна з методологій розробки кода?

Не можна такого прийняти, бо заперечення чогось у принципі не може бути методикою. Методика буде тоді, коли ви покажете інший метод, який дозволяє отримати порівняні результати.

В цілому по галузі був тільки один метод, який претендував на заміну тестам — це математична верифікація. І то, після перших спроб дійшли до консенсусу, що вона не може повністю замінити тестування хоча б тому, що сама система верифікації не ідеальна (люди помиляються, програми мають помилки) і засновки можуть бути хибними (наприклад, поведінка заліза чи використаного API — про це я вже казав).

Ваш метод

Писати правила, запускати систему, отримувати помилки, виправляти, запускати знову, поки не буде нормального результату. Такий собі TDD без чистого T :)

працює тільки в ідеальних умовах системи, що знаходиться біля розробника під повним його наглядом. А тепер порівняйте це, наприклад, з типовими умовами для embedded. Як ви отримаєте помилку з пристрою в іншій країні?

А, якщо згадати, що «запускати систему, отримувати помилки» це теж тестування — то ви до нього і воротились. :) Тільки на найвищому рівні інтеграції, а не на елементах будови програми.

Чому от саме такий підхід мусить зафейлитися?

Саме тому, що практика показує, що він занадто дорогий у скільки-небудь складних програмах. Тестування по частинах, аж до окремих функцій, дешевше, у складних програмах — на порядки.

Проблема в тому, що вхідна структура HTML не фіксована, завжди може з’явитися код, який нам все або зламає, або тупо неправильно буде відпрацьовуватися.

Це ніяк не буде прикладом проти — тому, що ви описуєте фактично необмежену, не формалізовану, задачу, завдання якої уточнюється в циклі після перших втілень. І до вопроса, що і як тестувати, цей приклад є суто ортогональним.

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

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

Так, тестування може бути використане замість свідомого написання правильної реалізації. І, до речі, з TDD це простіше, ніж з тестами після написання коду. Але описана економія зусиль — це не негативний, а позитивний фактор. Краще один раз написати тест, ніж десятки разів його повторювати вручну. І склад апостеріорних тестів має бути розрахований в першу чергу на цю економію.

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

Давайте повернемося до основ. Які саме проблеми вирішує тестування? Превентивне недопущення неправильного (неочікуваного) функціонування системи чи частки системи. Чому виникає неправильне функціонування? Через вихід за межі очікуваного або порушення логіки. Коли виникають ці ситуації? Під час функціонування систем, первинного написання або модифікації коду. Чи можна поліпшити код таким чином, щоб вихід за межі або логічні помилки не шкодили загальній функціональності? В багатьох випадках так. Отже, ми можемо досягати основних цілей тестування без тестування.

Краще один раз написати тест, ніж десятки разів його повторювати вручну
Не краще, простіше. Краще написати код, який не містить помилок, а не той, на якому проходить тест. :)
Це ніяк не буде прикладом проти — тому, що ви описуєте фактично необмежену, не формалізовану, задачу, завдання якої уточнюється в циклі після перших втілень.
Це норма розробки. Таких задач — дохуліард. Але якщо подивитися на методологію, а не на саму задачу, то можна побачити приклад досягнення мети (мінімізація помилок системи) без процесу тестування. Система вже має вбудований процес самополіпшення. Така собі кібергенетика.
Отже, ми можемо досягати основних цілей тестування без тестування.

Отже, ми можемо вирастити крила і літати — фізика це не забороняє. Але чомусь на шляху до цього занадто багато дрібних мілких перешкод — то генів нема, то сили мʼязів не вистачає.

Не краще, простіше. Краще написати код, який не містить помилок, а не той, на якому проходить тест.

І знову маю сказати, що мене не цікавлять роздуми про ідеальні умови з програмістами-єдинорогами, які ніколи не помиляються.

Це норма розробки. Таких задач — дохуліард.

А задач, в яких немає такої «норми», пʼятьдесят дохуліардів.

Система вже має вбудований процес самополіпшення. Така собі кібергенетика.

Не має і не кібергенетика, поки потребує активної участі людини.

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

Да, и это я говорил изначально. Можно писать код, который состоит только из if (входные параметры теста) { return результат теста; }, и он удовлетворит тест. Пока нет требования проверки кода на соответствие задаче, а не тестам — это будет полностью корректно — а такого требования нет в TDD.

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

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

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

Я помітив давно, що тестування призводить до загальної деградації коду. Розробники закінчують свою роботу над кодом саме на моменті успішного проходження тестів, а не на момент обробки всіх виключень, логічних умов тощо. Тобто вирішується не кінцева задача, а задача проходження тестів.

Це лише значить, що програміст не запарювався із написанням як коду, так і тестів.


void multiply_test() {
  CHECK_EQUAL(multiply(0, 0), 0);
  CHECK_EQUAL(multiply(0, 1), 0);
  CHECK_EQUAL(multiply(2, 2), 4);
}
int multiply(int x, int y) {
  if (x == 0 && y == 0) return 0;
  if (x == 0 && y == 1) return 0;
  if (x == 2 && y == 2) return 4;
  return -1;
}

Ой, граничні умови забули!


$ git diff multiply.c
diff --git a/multiply.c b/multiply.c
index 7ba923f7..6bf40133 100644
--- a/multiply.c
+++ b/multiply.c
@@ -2,10 +2,12 @@ void multiply_test() {
   CHECK_EQUAL(multiply(0, 0), 0);
   CHECK_EQUAL(multiply(0, 1), 0);
   CHECK_EQUAL(multiply(2, 2), 4);
+  CHECK_EQUAL(multiply(262144, 65536), 0); // спек сказав про урізання 32 битами
 }
 int multiply(int x, int y) {
   if (x == 0 && y == 0) return 0;
   if (x == 0 && y == 1) return 0;
   if (x == 2 && y == 2) return 4;
+  if (x == 262144 && y == 65536) return 0;
   return -1;
 }

Ну як, стало легше?

А як треба? Покажіть приклад.

1. Ваш тест є так само дискретним. Тільки точок більше.
2. Абстрагуючись від картинки, це перевірка на масиві готових значень. Оскільки ви не зможете зробити перевірку по 2**64 значень пари аргументів, все, що ви тут зробили — перевірку на більший набір значень, який все одно мізерна частка повного набору.


int multiply(int x, int y) {
  if (x > 2 && y > 2) return -1;
   if (x == 0 && y == 0) return 0;
   if (x == 0 && y == 1) return 0;
   if (x == 2 && y == 2) return 4;
   return -1;
Так — легше.

Граничні умови порушені.

Ви не задовільняєте один з тестів.

Я не здивований.

Ми ж програми пишемо не для того, щоб проходити тести. Ми програми пишемо, щоб потім люди користувалися їми.

Я не мазохіст, вашою програмою не користуватимусь.

Корпоративний сектор користується.... Задоволений. Навіть нас приводили в приклад нам же ж, як правильно робити системи аналогічного рівня. :)

І знову маю сказати, що мене не цікавлять роздуми про ідеальні умови з програмістами-єдинорогами, які ніколи не помиляються.
Ви трохи не розумієте посил, тому вам здається, що це саме сферична фігня в вакуумі. Я ж пропонував провести думковий експеримент, та уявити світ без тестування. От просто його не можна робити й все. Ніяк. Ніяких тестів. Зовсім. Як зміниться ваші підходи до розробки при таких умовах? Можна не робити нічого, а можна змінити підходи та методології. Ось, наприклад, як поміняється код вашого програмного продукту в таких умовах?
А задач, в яких немає такої «норми», пʼятьдесят дохуліардів
Ці п’ядесят — це все підзадачи отого головного дохуліарда.
Не має і не кібергенетика, поки потребує активної участі людини.
Машини поки що не навчилися писати код самостійно. Тому будь яке програмування вимагає активної участі людини. ;)
От просто його не можна робити й все. Ніяк. Ніяких тестів. Зовсім. Як зміниться ваші підходи до розробки при таких умовах?

Дуже просто: розробки не буде. Взагалі. Або початкові етапи експлуатації стануть тим же тестуванням.

Далі я не ігратиму в такі дурні ігри типу «уявіть собі, що ви амеба».

Ці п’ядесят — це все підзадачи отого головного дохуліарда.

Моя практика і майже все, що бачив навкруги, протирічать цьому.

Машини поки що не навчилися писати код самостійно. Тому будь яке програмування вимагає активної участі людини. ;)

Тому і не слід згадувати якусь «кібергенетику» там, де її нема.

То что «тесты гарантируют, что программа не сломается»
Тесты ничего не гарантируют. Написание mission-critical софта это отдельная головная боль и к тестам не имеет никакого отношения. Там другие подходы — см Coq, Idris etc.

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

Имеет. Потому что основания для работы Coq/аналога и корректность его работы — надо тоже проверить.
Но они, да, не гарантии, а подкрепления и обеспечение права делать выводы из верификации.

Вообще то проверкой корректности coq компилятор занимается. В этом же вся идея зависимых типов

С каких это пор у нас компиляторы непогрешимы?

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

Так вот с тестами такого бы не произошло и это было бы устранено до пуша на ремоут.
Цю мантру я чую постійно. І все одно є баги на продакшині. :D
Унеможливлення впливу на старий код досягається не тільки шляхом тестування, але й архітектурно. В слабопов’язаних архітектурах зламати існуючий код ще треба спромогтися. Там взагалі можна побудувати декілька версій програми в рамках одного коду, перемикання робиться через конфіг або роутером.

Угу. был у вас парсер протокола версии1.0. Вышла версия 1.1 кое-что добавили, кое-что изменили, кое-что уточнили. И сильно вам поможет архитектура?

Ну такое как раз часто даже поверхностными smoke тестами отлавливается. И интеграционными. Если очень много на парсинг этот завязано, то можно его конкретно достаточно глубоко покрыть несложно. Так что не вижу чем этот пример хорош в данном контексте.

Не зрозумів приклад. Де проблема?

Цю мантру я чую постійно. І все одно є баги на продакшині.
Это не мантра, а реалии жизни. Не всегда есть возможность перестравивать архитектуру при добавлении новых требований.
А то что на продакшене есть какие-то баги, так какое это отношение имеет к тестам? Тесты просто могут предотвратить появление новых.
Тесты просто могут предотвратить появление новых.
А можуть і ні...

так само — наявність коду це лише наявність коду. воно не гарантує вирішення поставлених задач.
але...

Катастрофи 2019 року показали що TDD не допомогли надійності Боінга.

Кацапы , когда ЗРК «Тор» разрабатывали, про TDD еще ничего не знали.
P.S Это уже в контексте 2020 года.

Коментар порушує правила спільноти і видалений модераторами.

Половина жалуется на отсутствие спецификаций, вторая на то, что «тесты ради тестов» бред и двойная работа.
На мой взгляд BDD (Behavior-driven development) в определенной мере решает обе проблемы одновременно.
1. Тестирование поведения для сценария пользователя это и есть исполняемая спецификация.
2. Эта спецификация в большой мере гарантирует одинаковое понимание сценария командой и заказчиком.
3. Поскольку спецификация исполняемая она тестирует сценарий на предмет багов
4. В итоге по этим спецификациям готовится документация проекта.

От самого автора методологии: RIP TDD.

Нет. Фраза “I’m sure I’ll find other ways to solve all these problems.” исключает такой вариант.

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

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

Сыграем в «сперва добейся»? Хотя лучше я вас таки попрошу выложить примеры того, о чём тут говорили. А то для меня Rails совсем не аргумент ни за, ни против, а вот посмотреть на интересные кодокартинки могу. Особенно если они связаны с темой тестирования.

ну github.com/rails/rails/issues/18847 из относительно недавнего например, из прошлого: turbolinks, activesupport mess, alias_method_chain и прочие прелести антипаттернов. еще интересная статья по теме: solnic.eu/...ime-with-rails-is-up.html

Эпичная дискуссия — в этом весь ДХХ последние годы: «Ты не согласен со мной, потому что я хочу добавить Basecamp specific feature I like в ядро ? F..k you, сначала добейся потом возражай» :D Хотя меня уже не трогает (я не на рельсах, да и не руби стек ... не считая шефовских рецептов) ... но вот Yehuda (core contributor), например, очень даже практикует ТДД и в руби, и в EmberJS и даже в Rust ... у него получается , ему помогает .... много их таких ТДДшников (мы же помним что это не про юнит тесты вообще ;) )

Тому що Україна це здебільшого аутсорс. А тут працює ху*к-ху*к в і продакшин, і бігом за новий проект. Щоб побільше проектів видати за одиницю часу. В короткостроковій перспективі тести займають лишній час. Для чого тести якщо програмісти будуть проект бачити декілька місяців, а потім новий проект?
От в продуктовій компанії інша справа... хоча і там тести не дуже приживаються...

це здебільшого аутсорс. А тут працює ху*к-ху*к в і продакшин
то вы в стартапе не работали. когда “надо было выходить на рынок еще вчера” и “ща конкуренты нашу идею стырят и быстрее нас запустят”

Немає емпіричних наукових досліджень, які б доводили ефективність TDD. Якби вони були, усіх би змусили це робити для заощадження коштів. Тест відбиває свою ціну виключно коли падає через реальну помилку. В моїй практиці таке трапляється украй рідко, тобто тести у моїх проектах це самі лише витрати. Так, я припускаю, що не тямлю їх писати :-). У нашій галузі взагалі нічого не піддається незалежним експерементам, тому кожен кому не лінь ліпить свої методології/технології, а потім люди сперечаються довго і нудно без реальних аргументів підкріплених hard data. Саме тому це називають релігійними війнами.

Ну, а если дело в том, что используя тесты код пишется изначально более качественный, из-за чего они отлавливают меньше ошибок? Мне кажется, это — более валидное объяснение

Справді, гарне пояснення, але нажаль це лише правдоподібне припущення. Ми не можемо заявити що це так і спонукати людей робити TDD. А якщо це не так? А якщо design-by-contract, наприклад, теж змушує краще продумувати код але при цьому контракти не так напряжно підтримувати. Ех, ми мало насправді знаємо. Якщо цікаво, на цю тему є дуже класний епізод подкасту www.functionalgeekery.com/...pisode-55-andreas-stefik

Ех, ми мало насправді знаємо.
справа лише в тому: мало що можна виміряти гіпотетично «а якби ми робили згідно TDD/BDD/насрать-і-тікать/etc то скільки б це зайняло часу/коштувало в результаті/скільки багів було б/etc?»
А якщо це не так?
чому б замість пошуку срібної кулі не зайнятися вирішенням саме актуальних проблем?
багато проблем саме на рівні інтеграції виникає? design-by-contract
люди регулярно забувають якійсь нюансі логікі? TDD як метода нагадування
у команді велика різниця у рівні розробників? парне програмування, обов’язкове code review, усілякі linter’и на комміт-хук

і так далі.
і все буде справді доречно та корисно.

згода?

Ну трохи висловився не точно, вони то є, але достовірність їх результатів — сумнівна. Достовірність — це повторюваність експериментів. А там як завжди, взяли купку приятелів і попросили оцінити, як вам здається, TDD зменшило кількість багів? Я сам цим в універі займався і тони цих статей перерив. В дисертації було треба експерементальну частину (дісєр був про ООП дизайн), ну дик я туди case study закинув, бо формально це empirical research method, але чи можна цьому довіряти і узагальнувати? Сумніваюся :-)

Перше правило клюбу свідків ефективності TDD — піддавати сумніву всі спроби доказати відсутності ефекту від ТДД ;)

У нашій галузі взагалі нічого не піддається незалежним експерементам, тому кожен кому не лінь ліпить свої методології/технології, а потім люди сперечаються довго і нудно без реальних аргументів підкріплених hard data

Ну вообще-то есть такой чувак, как Capers Jones. Он этой hard data насобирал довольно много, и в открытом доступе можно найти его отчёты по эффективности различных практик по устранению дефектов. Да, ни одна практика сама по себе не даёт 100%, но их комбинации дают до 95%.

О, цікаво, я не знав про чувака. Дякую!

Если найдете книгу Economics of Software Quality, крайне рекомендую. Цифирь там, возможно, не самая свежая (в открытом доступе можно найти и более свежие отчеты) — но зато есть много букв по поводу научного обоснования эффективности тех или иных практик

Дякую, судячи з назви цікава книжка, сподіваюся вона зможе пролити світло на те, що справді економічно вигідно робити на проектах, а що ні :-)

Each time you neglect writing a test, somewhere dies a puppy.

От фанатично-неумелого следования TDD вреда тоже немало, что мне как-то даже чаще лично попадается.

на 95% проще чем с тестами, говнокодю где хочу и законом не запрещено

rbcs-us.com/...Unit-Testing-is-Waste.pdf
Потому что мир состоит не только из популярных аббривеатур, секси-архитектур, хитрых паттернов и баек от Кент Бека и Папа Джона

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

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

Поговорим, когда у вас будет практический опыт.

чем так отвечать так лучше просто промолчать

Є багато методологій покращення якості коду окрім тестування. Наприклад, слабопов’язана архітектура дозволяє непогано боротися із регресією. Прототипне програмування виконує ту саму роль, що й тести, тільки під час розробки та ще й на декількох рівнях. Самотестуємий код дозволяє робити аналогічне, тільки постійно під час роботи програми. ФРП дозволяє поєднати все це в одну платформу та зменшити кількість багів, бо там кардинально інша декомпозиція. Код рев’ю, парне програмування, *nix way — все зменшує кількість помилок. А ще можна упоротися та впровадити методику програмування, яку я називаю «прозорі помилки», в якій вся логіка коду побудована таким чином, що помилка є частиною нормальної функціональності і ніколи не мусить приводити до жодного ексепшину.
Уявіть собі, що вам на проекті сказали, що вам заборонено тестувати код. Подумайте над тим, як зміняться ваші підходи до процесу розробки, технологічний стек тощо.

слабопов’язана архітектура
А это как?
Прототипне програмування
+
Самотестуємий код
Это асерты чтоль?
ФРП
шоэта? )
А это как?
Це коли частки проекта є повністю автономними та (в ідеалі) не залежать один від одного. Зв’язок робиться через надбудову, через певний API. Такий підхід має наступні переваги
1. Додавання чи видалення елементів, модулів, підсистем з програми не впливає на загальну функціональність.
2. Фіксований API взаємодії модулів між собою зменшує або зовсім унеможливлює проблеми інтеграції
3. Можна мати декілька версій/реалізацій одного модуля в рамках програми і вони не будуть заважати один одному.

Про прототипне програмування
Це не про прототипи JS. Це про прототипи майбутніх модулів, інтерфейсів (UI), API тощо. Спочатку розробляється прототип, який має виконувати певні функції, але не мати повну функціональність, а потім вже, після затвердження замовником чи іншими розробниками, робиться повнофункціональна версія.

Это асерты чтоль?
Схоже. Я приводив приклад із трансформацією HTML, коли додавання XSD і буде прикладом самотестування. Іншими словами, можна вбудувати в код процес валідації даних, струкрур тощо, при наявності помилок намагатися виправити їх або запустити інший процес.
шоэта? )
Функціонально-реактивне програмування.

>>

UP: Под словом «тесты» я подразумеваю именно использование методологии TDD, а не просто сферические Unit-тесты в вакууме.

Если так, то почему т.н. «отмазки» написаны о тестах вообще? Что, если я пишу тесты, но не использую TDD?
Я вообще за тесты (unit, в данном случае), но много раз замечал, что многие их пишут только по TDD, доказывая что никак нельзя по другому. У TDD есть свои минусы, это совсем не панацея от проблем архитектуры, дизайна, багов и т.д.

А ніхто й не стверджував, що, запровадивши TDD, ви позбудетеся проблем архітектури, дизайну, баґів тощо. І це ніяк не заперечує плюсів TDD.

У тдд по факту есть один единственный плюс — работаю по нему тесты будут всегда причём с около 100 процентами покрытия

У тдд по факту есть один единственный плюс — работаю по нему тесты будут всегда причём с около 100 процентами покрытия

А вы работаете по ТДД?
По моему опыту, для джавы
— если не много фремворков в проекте, то покритие где-то 90-96%
— если много фремворков и интеграций, то где-то 85-90%

Так это и есть около 100 процентов :)

По моему опыту, для джавы
— если не много фремворков в проекте, то покритие где-то 90-96%
— если много фремворков и интеграций, то где-то 85-90%

к.м.к. цифры нереальны реальна цифра 70% и то требует упорного труда и специальных подходов конечно при условии достаточно большого нетривиального кода чисто теоретически думаю можно достичь цифры 80% но это будет реально дорого и для многих legacy проектов нереально

манагеры и насяльника декларирующие «70% покрытия уже в этой пятилетке!» (к) (тм) по старому говнокоду со старой командой говнокодившей этот говнокод просто не знают об чём говорят от слова вообще ))

к.м.к. цифры нереальны реальна цифра 70%
по старому говнокоду со старой командой говнокодившей

Цифры приведены для проектов, которые с 0 пишутся по ТДД (именно по ТДД, а не «покрываются тестами»).
Если проект хоть 2-3 итерации писался без ТДД, то таки да 70 уже сложно получить.

Если проект хоть 2-3 итерации писался без ТДД, то таки да 70 уже сложно получить.

Откуда такие мистические данные?

Откуда такие мистические данные?
По моему опыту, для джавы

«Для джавы» это ни о чём. О чём — это тип задачи (мобильное, энтерпрайз типа-CRM/ERP, сервер приложения и т.п.)

О чём — это тип задачи (мобильное, энтерпрайз типа-CRM/ERP, сервер приложения и т.п.)

То что вы описали — это ни о чем :)
Джава == серверсайд. А БЕ для ЦРМ и для Мобилочки не сильно отличаетсо.
Домены (финансы, соц. сеть, магазин, документооборот, и тд) так же не являются определяющим фактором.

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

Если вы пытаетесь парировать сложность достижения 70%, то тут так же домен или «тип задачи», значения не имеет:
2-3 итерации, на каждой 2-3 ключевых бизнес фичи + 1-2 технических/архитектурных.
На выходе 6-15 задач которые являются ядром.
— Если они не покрыты тестами, то скорее всего они уже и не пригодны/не удобны для тестирования (например много шареного скрытого состояния). И надо или тормозить разработку (чего никто делать не будет), или строить новые фичи в изоляции от этих (а тут не получится, потому что первые фичи — это ядро)
— Если представить что «мы просто будем новое покрывать тестами», то это где-то минимум 6.6-7 итераций чтобы добится 70% покрытия (осмысленого, а не просто зеленых строчек)

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

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

Если они не покрыты тестами, то скорее всего они уже и не пригодны/не удобны для тестирования (например много шареного скрытого состояния).

И как это связано с TDD, а не просто фактом сдачи в состоянии, покрытом тестами?

И что, в случае изначального TDD их тоже покрывают, а если потом — то нет?
— если не много фремворков в проекте, то покритие где-то 90-96%
— если много фремворков и интеграций, то где-то 85-90%

Напишите эссе на тему «почему в начале разговора были приведены разные числа».

И как это связано с TDD, а не просто фактом сдачи в состоянии, покрытом тестами?

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

При покрытии «после кода», часто реальные бизнес сценарии могут забываться (особенно если их 10+) и по этому покрывают на основе не зеленых строк в коде.

Суммарно, тесты написанные после кода имею хуже качество, потому что их ... никто не тестировал.

При покрытии «после кода», часто реальные бизнес сценарии могут забываться (особенно если их 10+)

У вас неявное ложное допущение, что если не TDD, то тесты настолько после кода, что причины забыты. Может, у вас это и так (сочетание длительного «сейчас пилим фичи!» с отсутствием качественной истории разработки, даже тикетов нет, или в них не умеют писать), но так далеко не везде.

тесты написанные после кода имею хуже качество, потому что их ... никто не тестировал.

В TDD тесты точно так же не тестированы («fail first» это ложный костыль с вредным самообманом). Нормальное тестирование тестов осуществляется другими средствами — плановые инверсии, мутационное тестирование и т.п.

— «очевидные куски, которые не нужно покрывать» (давай лучше фичу запилим);

То есть подтверждается, что TDD — средство менеджмента, в стиле «гильотина от головной боли». Спасибо.

Напишите эссе на тему «почему в начале разговора были приведены разные числа».

Я не знаю, что у вас за фреймворки, но вообще-то нормальный набор тестов должен и их проверять на корректность — хотя бы в ключевых местах.

Суммарно, тесты написанные после кода имею хуже качество, потому что их ... никто не тестировал.

Это если тесты в рамках «технического долга». Если тесты пишуться в рамках тикета/пул реквеста, то проблема не столь очевидна (с некоторой поправкой на скоуп\размер тикета).

Почему 100% бизнес-аналитиков пишут не спецификацию, а фуфло?
Почему 99% проектов вообще не имеют хоть каких-то бизнес-аналитиков?

Почему 99% проектов вообще не имеют хоть каких-то бизнес-аналитиков?
Потому что
Почему 100% бизнес-аналитиков пишут не спецификацию, а фуфло

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

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

Кроме всего выше названного, есть ПО которое, реально работает более 10 лет. Тогда вообще не существовало тестеров.

Тут подробнее, пожалуйста. А то история почему-то говорит, что независимое тестирование в IT восходит ещё к 60-м годам, если не раньше :)

Да и класика Кенета Бекка про ТТД она какого года разлива? 2000? Раньше?

Оригинал — 2002, издание перевода на русский — 2003. Но я тут и 20 согласен воспринять как 10, из-за стандартной аберрации, но ведь не уложится ;)

Первого живого «тестера», QA тобишь, занимавшегося full time тестированием, лично первый раз увидел в 2006 году. Предполагаю существовали они и до этого)

Без багів, потім не буде роботи

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

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

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

Ну как бы есть проекты, где мануальное тестирование выпилено совсем

А можно узнать что это за проекты?

Если это чисто бэкенд с веб-сервисом, то понятно.
А вот если это web-фронтенд или приложение то очень интересно как этого добились на практике.

А вот если это web-фронтенд или приложение то очень интересно как этого добились на практике

В проде тестировщиков больше

Наболевшее:
дайте мне плз спецификацию по проекту, а потом поговорим о тестах :)

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

Иногда можно living specification делать, но это включает сильную обратную связь на эту самую спецификацию, которая меняется и уточняется на ходу

А вот с этого момента можно поподробнее?

Ну всякий BDD, cucumber-ы там со RSpecами и т.п., в особо запущенных случаях — Fitnesse. Составляется specification by example в соответствующем диалекте, по выполнению задания текст связывается с тестовым кодом и получается living documentation, она же спецификация. Обычно в процессе имплементации удобно спецификацию эту подправить, что вызывает обратную связь.

Чет на практике этот

living documentation
больше похож на те же юниттесты, только в обертке кукумбера

Если писать им юнит-тесты в обертке кукумбера, то так и будет. Что тоже иногда бывает удобно. Но идея несколько иная.

Разница в том, что unit test тестирует отдельный unit, как правило класс. Все остальное mocks. А выше уровнем задействуют несколько классов и проверяют код с точки зрения бизнес логики end to end

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

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

То есть можно писать тесты, не зная их цели? :)

unit тесты тестируют код. Если есть код, то можно написать unit тесты для него. Если смогли написать код, то какое-то понимание цели кода есть.

unit тесты тестируют код.

Любые тесты тестируют код, и что?

Если есть код, то можно написать unit тесты для него.

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

Если смогли написать код, то какое-то понимание цели кода есть.

Вот это и есть спецификация. Никто ж не говорил, что она обязана быть спущена сверху и подтверждена печатью? :)

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

Тогда целью является познание кода.

Нет. Потому что цель «разобраться, что у нас есть (за свалка мусора)» и «написать новое согласно ТЗ» заведомо разные.

Какая спецификация, какое ТЗ, какая архитектура ???
Во о чем, TDD и только TDD !!!

Вы мешаете в кучу необходимость писать тесты и использование TDD как методологии написания тестов.

«Test-first fundamentalism is like abstinence-only sex ed: An unrealistic, ineffective morality campaign for self-loathing and shaming.» david.heinemeierhansson.com/...ad-long-live-testing.html

TDD — это целостный подход. А «написание тестов» может быть постфактум, для галочки, для покрытия строк кода. TDD подходит для простой бизнес-логики, где минимум зависимостей. В реальных случаях надо мокать 90%, а вызывать код аж 10%.

TDD плохо подходит для инфраструктурных вещей и слоев, которые поддерживают бизнес логику — те же контроллеры, слой БД (здесь интеграционные тесты). Если слои «протекают» как в 90% проектов — то сушите вёсла. по TDD вы работать не сможете.

Унаследованный код, где не писали тесты или плохо писали. А заказчик запрещает и команда не хочет. Пойти против всех врядли у вас получится. А 95% всех проектов легаси так или иначе.

Тесты нужны, но нужного типа и в нужном месте.

А как интеграционные тесты помогают на слое БД? Можете пример привести?

Почему это плохо подходят тесты для контроллеров?

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

А что мешает?

Законы физики.

По-моему, автор первой реплики говорил про те контроллеры, что в MVC, а не те, что в железе.

Да, поэтому тему не развивал.

Тесты != TDD. Для тестов контроллера надо замокать сервисы, что-то придумать со срабатывающими аспектами, JSON-конвертерами и прочим, например поднимать отдельный спринговый контекст или уже юзать готовые тулы Spring-а: Spring MockMVC. И это все вместе невозможно написать по стилю TDD. У вас сначала контроллер с обвязкой (которую вы мокаете), а потом уже тест, что не есть ТDD.

Для тестов контроллера надо замокать сервисы
Зачем?
У вас сначала контроллер с обвязкой (которую вы мокаете), а потом уже тест
У вас может и так.
Лично у нас:
Тест -> класс контроллера (спринг не валится с 404) -> код котроллера -> рефакторинг -> котроллер выделяется в сервис.

Очень даже можно писать контроллеры по TDD. Использование моков дело несложное. Дело привычки.

TDD плохо подходит для инфраструктурных вещей и слоев, которые поддерживают бизнес логику — те же контроллеры, слой БД
Слой БД — да, а контроллеры тестировать можно и нужно. Если говорить о разработке для фронтенда, то контролеры это самое первое на что обычно пишут модульные тесты.
Унаследованный код, где не писали тесты или плохо писали.
Да, на унаследованный код писать тесты очень тяжело, а часто вовсе невозможно. Но никто не запрещает писать тесты на новый код. Сначала будет 1% покрытия, потом 10%, а через пару лет все 50%.

Есть еще ньюанс. Зачем воопще программу тестирует QA, а не тот же программер, который ее «написал без багов» ? Да потому, что он дейсно уверен что наваял код без багов (максимум — с фичами :) ), и даже если его заставить искать оные — не найдет :( То, что он был в состоянии предвиветь — он дейсно уже сделал. Т.е. нужен совсем другой человек, с иным взглядом на прогу, в т.ч. со взглядом и с т.з. пользователя, и с т.з. заказчика.
То же справедливо с TDD: нет большого смыслу писать автотесты для своего кода. Нужен автоматический тестер, профессия на сегодня достаточно новая. И тут аргумент «долго и дорого» имеет свой смысл: найти и обучить такого человека — это переход на новое качество, разумная инвестиция в дальнейшее совершенствование кода. Главный вопрос ИМХО — готовы заказчики к ней или нет... у меня в практике был заказчик, который и за обыкновенного тестера наотрез отказывался платить :(( и с теми же аргументами, что выше :) с устной ссылкой на Кембридж :)

По принципу TDD нет необходимости предвидеть баги. Необходимо уметь предвидеть только фичи. Т.е. запланированный «black box» должен получить что-то на входе, и в результате, что-то где-то случится или будет конкретноее что-то на выходе. Вот это и пишется в тест.
Например «если скормим этот полностью правильный файл, то вот это конкретное свойство нового объекта с id „фывап“ будет строка „йцукен“».
Или «если скормим этот битый файл, то вот тут и во-о-о-н там появятся сообщения об ошибке, которые выглядят „вот так“».
В скрамном случае вводные и ожидаемые данные берёте из user story, из acceptance criteria. Если их нет, то задолбать ПО, но добыть. Иначе задолбает уже он вас на приёме стори.

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

Я за общие принципы, лежащие в основе TDD, но категорически против именно той их комбинации, которая собственно и является классическим TDD, потому что она некорректна методически и неприменима для длительной разработки и поддержки ПО. Именно такая длительная разработка и поддержка специфична для моих работ (я ни разу не работал и не планирую в аутсорсных «инкубаторах» на 4K+ человек, только в продуктовых фирмах, да, это даёт существенную специфику).

В классическом TDD объявляется, что
1) пишутся тесты до кода
2) тесты должны быть проверены на то, что они не проходят
3) пишется код для их удовлетворения.

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

Чтобы допустить в принципе ситуацию, когда код меняется, надо допустить, если использовать правило «test first», что новые тесты соответствуют TDD, но старые — нет, часть тестов может работать и до новой разработки, и после. А это значит, что они уже нарушают этот принцип — их нельзя проверить на корректность той проверкой, что «тест до написания упал => он, вроде, правильный». Ситуация, когда новое требование уже удовлетворено тестом, не ложится в концепции апологетики TDD, но на практике является 100% нормальным в большинстве случаев и должна отрабатываться методикой без лишних загибов.

Поэтому, или вы доверяете корректности уже существующих тестов согласно их коду, но тогда правило «сначала тест должен упасть» вообще теряет смысл, или вы вводите другие методы контроля корректности тестов (в моём случае это инверсии тестов, когда проверяется нарушение выходных данных при заведомых отклонениях входных данных). А в этом случае уже пофиг, были написаны тесты до или после: это вопрос административного контроля качества покрытия тестами, но не собственно их выполнения.

Более того, TDD в принципе не позволяет создать сложный алгоритм. Вы наверняка тоже учили «джентльменский набор» разных сортировок. А вот теперь представьте себе написание метода сортировки по принципу TDD тем, кто не знает этих алгоритмов. Вы вначале решите, что должен пройти тест для (1,2) и (2,1). OK, сравнили два элемента, прошли. Теперь добавляем третий... четвёртый... двадцатый... во что превратилась функция? В лучшем случае вы получите сортировку вставками (если кодер очень умён), а скорее всего это будет «пузырёк». При совсем тупом кодере это вообще не будет читаемо даже после ста грамм. И Вы никак не получите ни метод Хоара, ни тем более метод Бэтчера. Потому что для них надо сначала реализовать алгоритм, хотя бы в уме, со всеми циклами, ветвлениями и тому подобным, а уже затем тестировать.

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

В вычислительной математике таких случаев ещё больше. Тестирование решения СЛАУ через построение треугольной матрицы — очень хреново ложится на TDD, а тонкие эффекты на долях эпсилона в принципе не могут быть заранее просчитаны.

Наконец, о смысле тестов в принципе. Тот, кто считает, что тесты проверяют корректность кода, должны немедленно идти в школу учиться заново думать с самых основ. Вероятно, лучшая формулировка (компактная и ёмкая) на эту тему, которую я слышал, высказана landerhigh@rsdn:

«„„Тесты не для поиска багов. А для написания верифицируемого в контролируемых условиях кода. Почувствуйте разницу ©.““»

Под верификацией тут подразумеваются все методы, начиная с простой ручной верификации глазами (code review), извините за каламбур. В TDD нет требования верификации кода. Код, который удовлетворяет только тесты и ничего больше, формально корректен.

Суммируя, правильно использовать отдельные положительные моменты из TDD. Они таки есть:
1. Главный — форсирование этого принципа не позволяет менеджерам и разработчикам низшего уровня жертвовать тестами для скорости разработки в ущерб качеству.
2. Требование покрытия кода ценно само по себе для тестирования.
Всё остальное — скорее в минус.

Даже Фаулер в своей книге(Рефакторинг) говорит что Кент Бек(Автор TDD) перегибает палку и классический TDD, не взлетит никогда на практике и рекомендует покрывать самые важные части приложения, а не 100%.

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

тому що, щоб їх писати і отримувати профіт треба вміти їх писати.

в умовах гонки за фічами , бо «конкуренти не сплять» , сроки і тп, а також багів, які виникли ,можливо , в тому числі і через відсутність тестів, девелопери не здатні освоїти методики написання тестів. Як ми знаємо погані тести , гірше їх відсутності, бо мало того. що код фіксиш ще й тести прийдеться фіксить..

ИМХО, писать тесты наверное стоит только на каких-то высоконагруженных проектах (типа фейсбука или вконтакта), когда от какого-то мелкого бага может зависеть работоспособность всей системы.
А в подавляющем большинстве случаев думаю отсутствие тестов не критично) Посему и не пишут, ибо «зачем платить писать больше?», если оно в данном случае не нужно (хотя конечно никто не запрещает каждому конкретному программеру писать тесты).

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

1. это дорого, ТДД нужно применять с умом и там где нужно (например медицина, авиация и тд), но якщо пан має час та натхнення...
2. результат в конце может меняться в течение проекта, так что все писанные ранее тесты просто окажутся бесполезной тратой времени

Писать тесты можно и без строгого следования ТДД, внезапно.

но третьи должны быть умнее, по идее.
звідки ці стереотипи, що всі програмісти — розумні люди?

Потому что ПРИМИТИВНЫЕ тесты:
1) Готовы тестировать только самые надёжные места;
2) Занимают туеву хучу времени;
3) Предполагают что тот кто пишет тест — гений, способный по памяти написать логику теста, но при этом кретин не способный написать сам код (который раз в 15 короче хорошего теста).
0) Повышают стоимость изменений, и делают из мелких багов — бюрократическую катастрофу. Про пожелания клиента я уж промолчу — кто ж полезет что-то править, когда версия уже прошла все круги ада?

По моим наблюдениям, код написанный под TDD — идеальная среда для сохранения багов годами. При этом именно TDD создаёт риски быть выставленным в недопиленной версии в продакшен. Мало того, именно эта недопиленная версия ОСТАНЕТСЯ в продакшене, потому что бюрократизированный процесс потребует ещё доказать что не верблюд. А доказывать придётся саппорту, который поставит статус «ПРОБЛЕМА РЕШЕНА», найдя workaround типа «поставьте руками предыдущую версию нескольких файлов» или «вот скрипт который решит проблему (забыли сказать что даст всем права админа)».

PS. Если бы эволюция проводила TDD, вы бы её не прошли. Потому что сразу после рождения не способны выжить.

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

Во-вторых, классическое TDD всё-таки подразумевает ООП архитектуру в стиле Java. Их задача не проверка правильности работы (это функциональные тесты), а найти список поломок в случае рефакторинга системы. Далеко не все используют экстремальное программирование с его частым рефакторингом, а тогда преимущество unit-тестов не настолько очевидно.

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

??? почему TDD приравнивается к юнит тестам ??? это вообще не про то ... Это (грубо) сначала тестом описывается логика поведения, а потом кодом доводится до рабочего состояния ... и после усложняется поведение по необходимости и рефакторинг .... И начинать можно не с юнит а с интеграционного или фообще функционального теста (Outside-In) ... прекрасно работает

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

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

почему TDD приравнивается к юнит тестам ?
от глубокого знания проблемы ессно :((

Чуть уточню:

Во-первых, можно пойти дальше и требовать верификации программу.

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

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

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

Во-вторых, классическое TDD всё-таки подразумевает ООП архитектуру в стиле Java. Их задача не проверка правильности работы (это функциональные тесты), а найти список поломок в случае рефакторинга системы.

О! Это очень ценное замечание.

Потому что юнит тесты не спасают от:
1) Падения на проде
2) Длинного time to market.
3) Configuration issues.

Т.е. сами по себе юнит тесты мало что тестируют, они могут покрыть логику, но код все равно раниться в неких лабораторных условиях, а не даже в prod-like. Ниже Макс Ищенко отписывал про системы мониторинга, и он на 100%, я бы еще добавил бы вирутализацию енвайромента (docker), CI pipeline и интеграционные тесты на мажорные фичи.

вопрос это из той же оперы что и «Почему 95% не практикуют BDSM?»
польза от тдд не очевидна, особено если код и требования меняются в процессе работы
Мне проще написать почти рабочий код и довести его до ума. А саппортом и дописыванием через год(в этом случае тесты очень полезны) не мне уже заниматься

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

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

И ещё такой момент.
Если 95% разработчиков не используют TDD,то и 95% проектов прекрасно работают без него.
Следовательно TDD — это не панацея и без неё проекты могу тпрекрасно существовать десятилетиями.

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

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

Тесты по TDD в основном бесполезны.

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

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

Ключевой момент в том, что тесты «остались» после написания фичи. Потому что если они пережили её написание, и соответствуют устаканившемуся коду, то они что-то таки обеспечивают. Они могут проверять не самые важные случаи, не ловить граничные варианты, но они есть. А дальше вопрос, откуда они взялись. Если из ТЗ — то они безусловно нужны, хотя сейчас больше принято такое применение называть BDD, а не TDD (слово behavior). Если из предвидения свойств реализации до самой реализации — то да, это обычно самая бесполезная категория тестов. Основная польза идёт из поведенческих тестов по ТЗ плюс граничных, которые могут быть осознано сделаны уже имея основное представление о реализации.

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

Опять, что значит «TDD тесты»? Неужели они все были написаны в точнейших деталях до реализации и больше не менялись?

Понятие «уровень функциональных тестов» криво по-своему. Юнит-тесты — это тоже функциональные, но уровня функции или метода. Значительно осмысленнее делить на функциональные и прочие тесты (производительности, защищённости и т.п.) и по уровням, чем вводить жёсткие границы деления на на «юнит», «функциональные» и «интеграционные».

Ну и зависит от контекста, конечно.

Вот это главное бесспорное тут :) Слишком уж контексты различаются.

Полезные тесты я встречал. А вот однозначные спецификации — нет.

Тесты не обязательно являются прямым следствием спецификации. Они могут быть расширением оной, или просто декларированием «здесь работает так, сойдет?»

Ни одного теста на Джинне, на ДОУ подозреваю ситуация не сильно отличается. Был у меня проект лет десять назад, писал по TDD. Не взлетел. ;-)

Поддержу Майка Горчака — удобнее и проще писать сразу без ошибок.

TDD и юнит тесты это прикольно, когда ресурсы (почти) не ограничены. Но почему-то в реальных проектах им всегда находится другое применение. В моем опыте, эффективнее вкладываться в системы мониторинга, от банальных Sentry до NewRelic и custom кода, который замечает изменение ключевых метрик.

Юниты «после» как раз очень хороши. Но они как комментарии — должны покрывать принципиально важные и неочевидные места, а не каждую строчку кода.

А если потом что-то апгрейдить надо будет?

Мы ж не качалку точим на станке — софт же еволюционирует.

Подозреваю что апгрейдить будет легче так как не будет головной боли с поломанными 100500 тестами.

ASAP-ое программирование, людям некогда :)

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

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

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

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

1) Прошедшие тесты не гарантируют, что в программе не возникнет race condition проблемы. Или любой другой прблемы взаимодействия ее частей. Т.е. по отдельности все работает, а вместе — [иногда] нет.

2) Тесты пишут программисты, а как мы все знаем, программисты — посредственные тестировщики. Хорошему программисту, просто в голову не придет, что можно «так» использовать его метод/класс/программу.

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

4) Программирование — это движение в две стороны. Это не путь «задумал -> сделал», а скорее «задумал -> попробовал реализовать -> все что не получилось задумал по другому». Поэтому нет смысла писать тесты, т.к. в самом начале еще не известно как ты это «задумал в самом конце».

5) Подход «сначала тесты, затем код» — это уменьшенный вариант Waterfall’а — «сначала архитектура, затем код». И хоть оба лозунга звучат просто, понятно и логично, жизнь доказала, что на практике все далеко не так идеально.

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

Мне кажется вы путаете ТДД и вообще тестирование ©

ТДД гарантирует что программа работает в соответствии со всеми требованиями.

Не получится, ибо

Это вообще не возможно гарантировать.
(© Bogdan Shyiak)

TDD гарантирует то, что выбранные для проверки тесты выглядят проходящими в тестовом окружении. В случае корректности тестовой оболочки (ну да, 99.999% случаев) — что они не только выглядят проходящими, но реально проходят. В том же тестовом окружении.

«„„На прошлой неделе один из пользователей написал мне об ошибке в CityDesk, которая проявляется только на польских Windows из-за того, как операционная система использует правый Alt для ввода специальных символов. Мы тестировали Windows 95, 95OSR2, 98, 98SE, Me, NT 4.0, 2000 и XP. Мы проводили тестирования с установленным IE 5.01, 5.5 или 6.0. Мы тестировали американские, испанские, французские, израильские и китайские версии Windows. Но мы не совсем ещё добрались до польских. ““» ([Джоэл Спольски, «Пять миров»])

«„„Тесты не для поиска багов. А для написания верифицируемого в контролируемых условиях кода.““» ([источник]) Второй раз в этой теме привожу эту мысль, но она того стоит. Гарантию соответствия требованиям обеспечивает верификация (включая неавтоматизированную визуальную верификацию), что код есть и он построен так, что может делать то, что надо; тесты выполняют при этом четыре функции:
1. Проверку соответствия подложки ожидаемому (компилятор, среда исполнения, API используемых библиотек).
2. Отсутствие тупых ошибок, не замечаемых на визуальной верификации.
3. Обеспечение исполнения кода для проверки его покрытия в условиях тестовой среды (ценно настолько, насколько ценна проверка покрытия кода).
4. Обеспечение видимых гарантий реализованности задачи для начальников, контролёров и заказчиков.

Будучи несомненно важными, ни одна из этих функций не совпадает с проверкой соответствия требованиям.

Наконец, ни одна из этих функций не обеспечивается нормой «test first».

Что существенно уменьшает риски и увеличивает вероятность того что программа работает правильно.

Верно для условия, что мы говорим о комплекте грамотно построенных тестов. Не имеет никакого отношения к методологии TDD, кроме собственно факта тестирования.

ТДД гарантирует что программа работает в соответствии со всеми требованиями.
Не получится, ибо
Получается ибо:
1) У вас есть требования
2) У вас есть тест на каждое требование
3) Все тесты проходят
---
Результат: ваш код соответствует всем __известным__ требованиям.

Нет. По крайней мере в своей сфере я очень редко получаю вариант, когда действительно требование можно уложить на тест. Это разве что требования вида if (кобыла.щёлкнутьВНос()) { assert_event_count(кобыла.щёлкнулаХвостом, 1); }, но они и так глазами обычно проверяются без проблем, если внутри надо всего лишь написать реакцию, и такие тесты тут лишние.

А вот типичной ситуацией является, когда есть некоторое общее требование, которое можно проверить только для выбранных конкретных значений входных аргументов и соответствующего им результата. А что при этих условиях всё остальное соответствует ожидаемому — проверяется чтением кода. Хорошая математическая аналогия: имея 3 точки, можно построить проходящую через них параболу и быть уверенным в её значениях для любого аргумента, но только если обеспечено условие, что аппроксимация идёт многочленом 2-го ранга. Если последнее не выполняется, может быть что угодно вне проверенных мест.
Несмотря на математичность аналогии, она работает, например, для таких случаев, как работа с объектом сообщения некоторого сетевого протокола, включая парсинг и обратное формирование в поток.

Насчет (2) я бы уточнил. Хороший программист знает, что «Never-happen happens», поэтому в месте, которое никогда не исполнится ставится throw «Never happen!» ..

чомусь нагадало джунів, які після прочитання «GoF» сунуть всюди всі зазубрені паттерни і люто бризкають слиною на всіх, хто теж цього не робить.

часто буває, що початкова архітектура, вимоги і тд змінюються настільки швидко, що переписувати і код і тести по 100 разів — доволі тупо, тому тести пишуться вже коли все ± устаканиться. і це тільки один кейс.

більшість тестів, які я бачив — тестують ніхера в кращому випадку, або тестують dependency injection в гіршому. решта тестів пишуться для чсв, щоб багато «зеленого» було. звичайно, вони ніхера не тестують теж (валідацію аргументів, лол).

і тільки ті 5-10% тестів, які були грамотно продумані і акуратно написані, реально перевіряють корисні речі. от написані вони були по тдд чи після девелопменту — немає ніякого значення, імхо.

п.с нічого не маю проти тдд, інколи виходить тдд, інколи ні, інколи без тестів, як у всіх. просто це не ідеальна концепція на всі випадки життя, такої просто не існує, інакше всі б вже її юзали

context is king

Не соглашусь с вашим утверждением.
Context is Kong!
Content is King.
Ну а вместе они King-Kong!

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

Надо делать оценку того что делаешь, гдето тесты оправданы, а гдето нет.

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

Скорее наоборот, энтерпрайз спокойно относится к простоям по причине «ой, что-то сломалось» и «ой, а как оно должно работать», которые вяло текут в переписке по несколько недель кряду. Стартапы же ожидают более активной разработки (и изменений) — как раз конёк тестов — не обязательно TDD, но хоть каких-то.

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

Это какие-то неправильные стартапы. А вот красные тесты это хорошо — это значит что писали их не зря. Да, они при переписывании упадут, и это как раз то, зачем их пишут — чтобы увидеть что сломалось.

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

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

да и когда работает +200 человек на проекте без юнит тестов сложно, ибо похерить чужой код раз плюнуть
Залежить від архітектури.

одно слово — монолит, и все очень сильно связано — жизнь боль

Это какие-то неправильные стартапы.

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

Поэтому тесты времени компиляции идут вначале в сад, а потом вслед за кодом.

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

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

Если меняется концепция, то и так заранее можно предсказать заметную часть упавших тестов. Падение тестов важно, когда она не меняется, но что-то порушено :)

В первых двух случаях можно просто списать на умственные способности населения, но третьи должны быть умнее, по идее.
Как же ж мне нравится, когда вылазит очередной пыонэр, заходит на форум «профессиональных электриков» и начинает задвигать про то как плохо совать пальцы в розетку.
1. Я сразу пишу код без багов
Именно. Распечатай эту фразу двухсотым шрифтом и повесь на стену позади монитора. Может и тебя постигнет дао.
2. Это долго
Да, это долго и ненужно. В дебагере лазить месяцами не нужно, см. пункт 1.
3. Заказчик не оплачивает.
Если ты считаешь, что ты откровенно лажаешь, то дели свой рейт на два и пиши тесты, когда надоест, то см. пункт 1.
4. Тесты плохо работают.
Они вообще не работают. Если ты написал тест, который поймал ошибку в твоём коде, то ты не программер, а тестер. Настоящие программисты пишут без ошибок. См пункт 1.
Может подойдет простое объяснение — изначально не учат программировать через тестирование, а потом самому лень разбираться?
Учить программировать через тестирование — то же самое что тренировать школьную сборную по плаванию в бассейне без воды.

"

Настоящие программисты пишут без ошибок. См пункт 1.
" слова истинного пыонера программиста )" - поржал )

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

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

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

Пример нетривиальных ошибок. Проект — эмулятор ядра линукса в юзер-спейс, в линуксе все ядерные объекты синхронизации не являются системными объектами, например, мьютексы можно не удалять и т.п. В другой ОС — это системные объекты и при долгом исполнении кода, при постоянном выделении и освобождении памяти может случится так, что в удалённой памяти находился мьютекс и мы его попытались повторно проинициализировать в памяти. Люди непривыкли проверять коды возврата тривиальных функций, а надо было бы. И тут оказывается, что мьютекс при создании может вернуть EAGAIN, но его никто не слышит. Дальше мы пытаемся его лочить и опять не особо проверяем коды возврата, а стоило бы.

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

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

Или вот такой код:
If (one_time) {
free(workqueue);
}
....
workqueue->done=true;
QLIST_REMOVE(head, workqueue);
....
return one_time ? NULL : workqueue;

Как ты предлагаешь отлавливать такого рода ошибки в юнит-тестировании? Они и при функциональном тестировании могут жить годами, а приложение падать раз в год в совершенно разных местах.

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

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

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

Если ты считаешь, что ты откровенно лажаешь, то дели свой рейт на два и пиши тесты,
так вот, я не буду стыдиться признаваться, что да, я временами откровенно лажаю, смотря прямо в код не вижу очевидного ляпа; но такое у 95% программистов, а то и 99%. И да, для того, чтобы самому заметить ляп, нужно проверить результат. А как лучше его проверить, если не протестировать? :)
Если ты руками написал тест, который поймал ошибку в твоём коде, то ты просто не думал, когда писал код, только и всего.

Почти верно. Думал. Но при этом не учёл все параметры ситуации, потому что все учесть оказалось выше сил.
И снова, это не то, за что надо стыдиться. Это то, что надо понимать и учитывать. Знаменитое правило «семь плюс-минус 2» даже у гениев превращается в то, что вместо 7 будет, ну скажем, 10. Ладно, 20 (не верю). А параметров, влияющих на ситуацию, может быть 100 или 321.

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

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

Вывод — юнит тесты не нужны.

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

Как ты предлагаешь отлавливать такого рода ошибки в юнит-тестировании?

Несмотря на заведомо некорректную постановку вопроса (ты почему-то предположил, что я предлагаю решать юнит-тестированием любые ошибки?), именно эта как раз может быть им найдена! Для этого нужно обеспечение полного покрытия тестами и, поскольку речь идёт об низкоуровневой работе с памятью, запуск всех тестов хотя бы под valgrind. Если сработает ветка на free(), то на последующую работу с освобождённой памятью будет дано предупреждение valgrind (аналога), которое должно превратиться в падение теста.
Возможно, более сложная ситуация так не отловится, но конкретно эта — таки получится :)

Вы пишете код совсем без багов и компилируете его только, чтобы проверить сам компилятор на наличие багов? Я думал только Jeff Dean так может :) www.quora.com/...e-all-the-Jeff-Dean-facts

В коді було 79 багів, було 79 багів.
Пофіксили 1 багу — стало 128 багів
а потім пишіть одразу функціонал без багів і чекайте дао за спиною

Кокая трогедия. ©

Та ні, трагедія то бути самовпевненим егоїстом і роздавати свої ’совєтіки’. У вашому коді теж є баги. Просто ви їх фічами називаєте

А где тут эгоизм? Или это просто, чтобы язык об забор почесать?

тобто все інше ви навіть не намагаєтесь спростувати)
а де паркан?

Хоспади, да перед кем тут опровергать? Эгоизм где?

дійсно, перед ким?! ви ж тут цар

Цар и бох

Пофіксили 1 багу — стало 128 багів

Як це взагалі можливо?

Мабуть, після фіксу баги, довелося ще 50 тестів фіксити :)

Видать вы не деплоили хотфикс на прод без вообще каких либо тестов.

Самая стремная техника, но позволяет понять как фиксить баги правильно.

Ну так это и есть «по бразильской системе» :)

Разработчик который никогда не далет баги это один из трех вариантов:
1) Никогда не пишет код
2) Никогда не тестирует код
3) Просто пиздабол или неадекват
Можете самостоятельно выбрать свою категорию : )

4) мёртв (по сути, включает в себя пп 1 и 2)

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

Я бы на вашем месте избегал бы подобных аргументов.

Почитайте Кента Бека «Разработка через тестирование: на примере»
Там описывается, что сами тесты должны быть максимально примитивными, как минимум намного проще тестируемого кода. Конкретно в тех примерах тестов, что описаны в книге будет сложно ошибиться.

У меня был случай, что тестовая инфраструктура (не код самих тестов, а то, что лежит за всеми этими CHECK_EQUAL) поломалась и прятала нарушения предикатов.
При этом «Test first» позорно спасовал, потому что наличие кода функции было достаточным для прохождения теста при любом ответе.
Как-то я и раньше тому test first не доверял, но в итоге получил дополнительный аргумент, что без аккуратно расставленных инверсий тестировать нельзя. Даже если они проверяются раз в неделю вручную.

При этом «Test first» позорно спасовал, потому что наличие кода функции было достаточным для прохождения теста при любом ответе.
К слову, mutation testing тут бы помог.

Mutation у нас был обычно неприменим из-за отсутствия подходящей инфраструктуры (ну-ка помутатьте Erlang или злобный C++), и из-за не-100% покрытия (не хватало времени, в разы). Вместо него были как раз инверсии, в двух вариантах
1) опция сломать в конкретном месте (точки воздействия планировались заранее)
2) опция исказить входные данные (выход должен был измениться)
и не менее важное, что тестовый фреймворк должен был явно сказать «оно упало», а стоящий над ним make детектил это и сам генерировал fail, если вложенное не упало.
Вместе с умным распределением, где именно нужно ставить тесты в первую очередь, а где можно было отложить, этого хватило на запуск реально сложной системы малым коллективом.

Так похоже что у вас и был свой вариант mutation testing’a — просто без использования существующего mutation framework’a и с заведомо заданными мутантами.

и не менее важное, что тестовый фреймворк должен был явно сказать «оно упало», а стоящий над ним make детектил это и сам генерировал fail, если вложенное не упало.
Мне кажется это как раз и должен делать mutation framework — который может (или нет) быть частью тест фреймворка.

Кстати, для плюсов/ерланга вроде есть готовые mutation framework’и — но насколько они живые/не поделки, конечно, вопрос.

Так похоже что у вас и был свой вариант mutation testing’a — просто без использования существующего mutation framework’a и с заведомо заданными мутантами.

Да, можно и так сказать.

Кстати, для плюсов/ерланга вроде есть готовые mutation framework’и — но насколько они живые/не поделки, конечно, вопрос.

На тот момент (основная активность была 2008-2012) ничего видимого для доступа не было.

Очень легко заметить, что больше всего негодуютъ т.н. пэхэпэ дэвэлэпэры, которые даже не имеют языка программирования, но баги делать умеют %)

Сказав представник вмираючого виду мамонтів письменників на C.... :/

Очень легко заметить, что вы из третей категории:

3) Просто пиздабол или неадекват

Мы же взрослые люди, давай просто достанем и померяемся.

А що ви будете робити, коли програєте?

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

А хто лайно на вентилятор кинув перший?

Как ни странно, но ТС.

т.н. пэхэпэ дэвэлэпэры, которые даже не имеют языка программирования
это уже перебор.
ну, я про наезд на язык.
наследие интерпретируемости(вызов метода/функции по имени, например) и изкоробочный classkit/runkit позволял мокать практически всё, что порядком упрощало написание тестов даже в случае tight-coupled кода.
это уже перебор. ну, я про наезд на язык.
Это ради того, чтобы позлить. %)

Дуже легко помітити, що ти бидло

Прямо таки сказывается интеллегенция в надцатом поколении.

Дуже добре , що почали з самокритики, це вже початок лікування

Ну чем бы не тешилось,... пусть пациенты в докторов поиграют %) Лечим то как раз вас, у людей кругозор намного шире, чем PHP+TDD, это вы там в своём мирке живёте и считаете себя пупами, которым неожиданно разрешили указывать всем как надо жить. Окститесь, забейтесь в угол и не мешайте жить другим.

Причому тут взагалі тема про TDD, якщо коментарій був стосовно вашого вкиду . Ви ж навіть уявлення не маєте який в людей кругозор,як вони живуть і чим займаються, тому як ви можете судити?
Тільки бидло може судити інших людей по мові, якою вони говорять, так і в програмуванні аналог є мовою,якою вони пишуть. Ваші «фразочки» показують ваш рівень як людини, і тому раджу саме ВАМ «забитись в угол» і не мішати іншим жити.

О, ти тут новенький.
P.S. Тут всі звикли до його манери спілкування і просто не звертають увагу. І ти не звертай — все буде добре:-)

На самом деле все проще — я подрабатываю зеркалом %) Увы, моя тяжелая ноша по жизни.

Да им просто дебаггер не завезли, вот и пришлось костылями обкладываться. )

Zen Debug, xDebug — ні не чув ніразу. Просто вброс

"Холмс курить не бросил, но Ватсон без трубки уже не мог"© ))

Учить программировать через тестирование — то же самое что тренировать школьную сборную по плаванию в бассейне без воды.

на века сказал.

потому что у меня 2+ гига кода написанного без всякого tdd и это требует адских инвестиций для создания адекватной тестовой инфраструктуры
правда у нас довольно развесистые интеграционные тесты что сильно помагает

Я не понимаю почему многие люди делают очевидно глупые вещи: одни пьют водку, другие поддерживают Путина, третьи не пишут тесты.
Годно вбросил)

Мое мнение: потому что 95%+ не понимают, что TDD не столько о тестировании, сколько о дизайне кода. И да, в 90-х — ранних 2000-х, когда нужно было обосновать необходимость тестировщиков, учили, что программист не способен протестровать свой код.

Я не пишу тесты по двум причинам:

1 тесты это тупое дублирование кода
2 большая часть ошибок — ненаписанный код, который тестами покрыть невозможно ввиду его отсутствия

Мне вот другое непонятно — а нафига вы пишите тесты? Нет, я понимаю необходимость тестирования другими — они находят те пути, на которые у вас ума (или глупости) не хватило. А смысл писать тесты на свой же код? Вы ведь там просто тупо повторяете свои же ошибки.

А потом надо поменять вот этот маленький класс, и ВНЕЗАПНО через два месяца заказчик узнает что у него критичная система отпала. Приятной отладки :)

Но да, в идеальном мире тесты должны писать QA: не только потому что чужой взгляд найдет другие edge cases, но и потому что это более глубокая область знаний, чем это принято признавать среди сырных магнатов.

А потом надо поменять вот этот маленький класс, и ВНЕЗАПНО через два месяца заказчик узнает что у него критичная система отпала. Приятной отладки :)

Приятной отладки, говоришь? :) Алексей, я полгода искал один баг. QA все оттестили и разрешили выставить в продакшен. А через месяц началось... Я покрыл код тестами на 200%. Я написал эмулятор, который в реалтайме повторял по логам продакшен. Я сутками фигачил бекенд стресс-тестами, попутно прогоняя логи эмулятором. Я несколько раз просил код-ревью. Код в итоге был вылизан до состояния круче, чем «по учебнику», все тесты (включая нагрузочные) отрабатывались на ура, эмуляция жрала логи гигабайтами не показывая проблем. И один черт раз или два в неделю продакшен тупо отваливался от бекенда и не мог приконнектится обратно.

Так вот, на основании своего горького опыта я имею сказать две вещи:
1. никакой TDD, никакой на 100% правильный код, никакой самый мощный отдел QA, ничто в этом мире в принципе не способно защитить от ошибок.
2. заказчик переживет. Может быть есть вещи пострашнее банка у которого регулярно падает мобильный банкинг, но что-то слабо верится.

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

Очень грустная история. :(

На самом деле, от чего я больше всего в ужасе тут, так это от полугодовых затрат на относительно простую сетевую проблему. Потому что я бы лично в этом случае в первую очередь увешал всех участников tcpdump (а если слишком толстые потоки — хотя бы netflow), а бэкенд — писать подробно жизнь сессий и все возможные случаи (отказ по переполнению количества разрешённых соединений обязан идти в лог с серьёзным уровнем важности!) Даже просто лог попыток коннекта с указанием IP, откуда это пришло, дал бы понимание ситуации (три разных IP вместо двух — есть о чём подумать).

Так что тут надо списывать эти полгода впустую на совершенно некомпетентных devops’ов, или тех, кто им мешал реализовать простую диагностику. Это не программная проблема.

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

Не прошу название банка, но надеюсь, что до приведения IT отдела в порядок мне не придётся иметь с ним дело.

1. никакой TDD, никакой на 100% правильный код, никакой самый мощный отдел QA, ничто в этом мире в принципе не способно защитить от ошибок.

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

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

Начинаю хотеть пьесу/фильм с такой сценой. Если бы не ожидаемый поток 20-этажного мата после выхода из ступора, это было бы покруче финальной сцены «Ревизора». :)

Даже просто лог попыток коннекта с указанием IP, откуда это пришло, дал бы понимание ситуации (три разных IP вместо двух — есть о чём подумать).
Все было проще — было только два разрешенных для коннекта IP. Вендор это подтвердил. Но наша доблестная VPN Team втихаря решила и эту проблему!! :) Ну и доступ у меня был только к своим логам, даже рестарт сервиса делался через имптехов. Про логи заказчика (бекенд их) можно было даже не заикаться.
Начинаю хотеть пьесу/фильм с такой сценой. Если бы не ожидаемый поток 20-этажного мата после выхода из ступора, это было бы покруче финальной сцены «Ревизора». :)
Я сказал, что у меня отгул и пошел к другу. После ночных покатушек по горным серпантинам с автогонщиком за рулем любые проблемы резко теряют свою актуальность и значимость. Рекомендую, кстати. :)
Алексей, я полгода искал один баг.

Этот аргумент примерно такой — вот Вася бросил бухать, начал кататься на велосипеде и его машина сбила. Значит нужно бухать.

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

Я покрыл код тестами на 200%

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

Этот аргумент примерно такой

Это и есть такой аргумент — это было не про ТДД, а про «приятную отладку».

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

Это вопрос мотивации. Разъяренный банк — отличная мотивация. ;)

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

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

А потом надо поменять вот этот маленький класс, и ВНЕЗАПНО через два месяца заказчик узнает что у него критичная система отпала. Приятной отладки :)
Долго думал — что меня в этом кейсе смущает. И внезапно таки понял.
Если это маленький, но базовый класс или часть библиотеки, которая потом используется другими и других местах, то как вы при ее написании можете предугадать — кто и где ее будет использовать? А если это часть уже полностью описанной архитектуры, которую всю заботливо продумали, то как вы можете тогда менять данный класс, не проанализировав предварительно последствия для существующей реализации?
Мне совершенно ясен смысл регрессионных, нагрузочных и интеграционных тестов, которые практически всегда внешние относительно разработки. Как и использование автоматики для эмуляции вариантов ожидаемого поведения пользователей.
Но вангование всего возможного «шит хэппенс» кажется просто пустой тратой времени в промышленных масштабах, т.к. от того что знаешь можно и нужно защищаться в самом коде при его написании, а то, что не знаешь — и тестами, соответственно, не покроешь.

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

(Зато потом не долго месяцами лазить по коду дебагером и пытаться понять что это за хрень и как оно вообще работает)
Понять что делает мудреный юнит тест с 500 строчками моков моков не всегда легче.

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

Справедливости ради, если для одного теста приходится делать 100500 моков, то это вполне себе повод задуматься все ли хорошо с дизайном. Неудобство при написании теста очень часто признак плохой композиции и сильного связывания. ИМХО выявление таких проблем, это даже более важный аспект чем сам по себе «зеленый» тест. Впрочем, это не о TDD а о тестах в целом.

Писать/не писать тесты и использовать или не использовать TDD — абсолютно разные вещи же, не?

А еще плохо работают ленивые разработчики
Хуже ленивого разработчика только ленивый тестировщик.

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

а на очень больших уже просто не получаеться и опять забивают

ну если ты для боинга пишешь или для аирбаса то забить не получится

та про аерспейс давай не будем — там совсем другая жизнь. Котики же или финансы таким не страдают

Котики же
Котики. Котики — это life critical systems %)
1. Я сразу пишу код без багов.
Люблю эту отмазку, такая забавная :).

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

Может подойдет простое объяснение — изначально не учат программировать через тестирование, а потом самому лень разбираться?
На мой взгляд причина немного в другом.
Дисциплина против очевидного решения.
Люди как правило низкодисциплинированы.
Интеллектуальных способностей большинства программистов вполне хватает на то чтобы удержать в голове цепочку более чем из одного пункта.
Поэтому во многих случаях проще сначала набросать код, чем написать 2-5 тестов на 1-3 строки кода.
Простой пример — ТДД каты: самое сложное это проходить их по порядку, не забегая вперед.
.
P.S. Немного от Дяди Боба blog.cleancoder.com/...6/10/MutationTesting.html

Спасибо за комментарий, Богдан. Интересное мнение.

Підписатись на коментарі