Простое написание тестов — это не TDD!

http://spin.atomicobject.com/2012/12/06/writing-tests-is-not-tdd/
  • Перевод
Эта статья представляет собой хороший теоретический материал о TDD для тех, кто об этом ещё ничего не знает.




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

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

Что такое TDD?


В TDD есть 3 основных правила от дядюшки Боба:
  • Пиши только тот код, который протестирован.
  • Начинай писать тесты с малого, а затем наращивай их.
  • Пиши ровно столько кода, сколько необходимо для прохождения теста.


Основы TDD


Базовый процесс следования TDD содержит 3 этапа: красный, зелёный и рефакторинг.

Красный

Красный этап состоит из написания теста, который не проходится. Только одного теста. Если ты не можешь остановиться и продолжаешь писать много тестов, займи идею из Getting Things Done и выкинь лишние мысли из головы, чтобы они не отвлекали тебя. Существует несколько разных способов, которые ты можешь использовать: создать список предстоящих дел на бумаге, нарисовать индексную карту, добавить серию TODO комментариев в свои файлы и многие другие. Для себя я определил, что физическое действие вычёркивания пунктика на бумаге или рисование галочки и сворачивание индексной карты пополам даёт мне большее ощущение завершённости дела.

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

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

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

Зелёный

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

Рефакторинг

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

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

Преимущества TDD


Рабочий код

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

Изменения без страха

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

Живая документация

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

Архитектура через код

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

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

Когда не TDD


Что если тебе нужно использовать новую библиотеку или фреймворк, а ты не знаешь как это сделать? Как ты можешь написать тест в первую очередь, если ты не знаешь с чего начать? Ответ прост — а ты не можешь. Создай новый проект и используй новую библиотеку отдельно от своего рабочего кода. Такие новые проекты называются костылями. Так как они не в твоём рабочем коде, ты не нарушаешь Правило №1 из трёх правил дядюшки Боба. Работай с ним пока ты не почувствуешь комфорт в использовании этой библиотеки. Когда узнаешь, как твоя библиотека работает, забудь костыли и возвращайся назад к своему рабочему коду и начинай с написания тестов.

Как бы то ни было, если ты не можешь использовать TDD, не забывай о важности написания тестов. Твои тесты послужат справкой для тебя и (если твой костыль в системе контроля версий) для тех, кто придёт после тебя. С помощью этих тестов ты можешь быстро вспомнить всё что ты изучил, и, оглядываясь назад, ты увидишь большой прогресс в своём мастерстве.
Метки:
Поделиться публикацией
Комментарии 121
  • +22
    всегда вдохновляли такие статьи, но как только садишься за работу, то не думаешь о тестах, а начинаешь продумывать архитектуру. Никак не получается «перевернуть вверх ногами» рабочий процесс. В итоге получается так, что сначала пишешь код, а уже потом, с угрызениями совести, пишешь тест.
    • +14
      Честно говоря, я вообще не понимаю, как можно садится писать что-либо, будь то код или тесты, не продумав хотя бы поверхностно архитектуру приложения. Что вообще писать? С какой стороны начать? Мой подход обычно такой:

      0. Продумываю базовую архитектуру, выбираю некоторую часть системы, которую собираюсь реализовать.
      1. Набрасываю небольшой кусок кода, более-менее похожий на то, что мне хотелось бы иметь — прототип.
      2. Пишу тесты для этой части системы, даже если заранее понятно, что прототип их не пройдет.
      3. Привожу протип в состояние, когда он проходит все тесты.
      4. Если необходим рефакторинг — рефакторю.
      • 0
        У меня тоже не получается не думать об общей архитектуре, но, наверное, не стоит впадать в крайности. Если, например, писать интеграционные тесты, то нужно сперва продумать и поднять какой-то базовый каркас приложения, и уже начинать с тестов не получится.
        • 0
          На мой взгляд, когда пишется код, большинство архитектурных уже принято. Хотя бы тот простой факт, что код вы на каком-то языке пишете? Почему?
          • +6
            Я думаю огромный процент разработчиков пишет на определённом языке просто потому, что знает его лучше всех, и я в их числе. По подобному принципу в компаниях выбираются языки и технологии.
            • –4
              лучше все остальных языков? это не оправдание
              дучше всех остальных разработчиков? это хорошо
              • +3
                Лучше остальных языков. Вполне себе оправдание.
                Самый распространённый случай — Вы программист на полную ставку. Вам ставят цель в одиночку(читать как команда равных) написать систему. Вы оценили задачу: на знакомом Вам языке это займёт Х времени + 0.3*Х времени как риск, на слабознакомом это займёт Х времени + 0.7*Х времени как риск + проблемы с дедлайнами в промежуточные этапы разработки (очень даже вероятные проблемы).
                Вы любите свою работу, и не хотите завалить проект, выберете первый вариант?
                • –2
                  а зачем вы меня в придуманные вами рамки поставили?
                  Вообще исходный мой комментарий был не об этом. Язык — это лишь один из ярких примеров уже выбранных архитектурных решений. Давайте писать предварительные тесты на структуры данных, например. Это не сарказм. Давайте писать, ведь как сами структуры данных, так и выбранное их представление и размещение в той или иной памяти, синхронизация в случае дублирования, много чего определеяют априори.
                  Я не против предварительного написания тестов. И даже «за». В любом виде, не только в этом. Но не надо тешить себя иллюзиями:
                  Так как мы проводим большое количество времени непосредственно взаимодействуя с объектами и функциями которые мы пишем, архитектура проявляется из кода сама.
                  • 0
                    Понятно о чем Вы пытаетесь сказать. Выбор языка программирования это действительно вопрос архитектурный. Однако Вы не учитываете в каком положении находятся современные программисты. А ведь это важно понимать! На данный момент программист, как правило, приходит в уже сформированный проект над которым уже подумали до него. Ему не надо думать над тем, что подходит его язык или нет. Боле того, даже если современный программист и задумывается над этим вопросом, то достаточно часто он не может повлиять не выбор сделанный до него.
            • 0
              *архитектурных решений
          • +1
            Я тоже так делаю, но с угрызениями совести и с осознаванием недостаточного джедайства.

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

            С опытом привычка планировать почти прошла.

            Но с другой стороны на прототип ТДД не распространяется. Если вам надо очень быстро соорудить макет, чтобы что-то пощупать (ГУИ) или нащупать возможный алгоритм или вариант решения — то такой подход вполне себе оправдан без угрызений совести.
            Еще. Для прототипирования желательно выбирать или язык такой или такое средство, чтобы время на разработку стремилось к нулю. А потом, если надо, переписывать с ТДД на чистовик. Или не переписывать, если не надо. Но плохо писать нечто среднее между прототипом и проектом, покрывая его потом тестами. Ни туда ни сюда. С одной стороны, если создание прототипа заняло больше времени, чем нужно, а он не показал, что так делать проект не стоит — потеря времени. А если удался, а вы пишете не на кратком языке или средстве — есть соблазн не переписывать (уже время потрачено)
          • +1
            > В итоге получается так, что сначала пишешь код, а уже потом, с угрызениями совести, пишешь тест.

            Задумайтесь о том, что вы написали «костыль», который «не в твоём рабочем коде. Работай с ним пока ты не почувствуешь комфорт в использовании этой библиотеки. Когда узнаешь, как твоя библиотека работает, забудь костыли и возвращайся назад к своему рабочему коду и начинай с написания тестов». Вот и всё. ;)
            • 0
              А почему нельзя просто написать тесты, взять уже готовый «костыль» и привести его к «рабочему коду» с помощью рефакторинга?
              • 0
                Наверно, можно. Но прототипы редко кто использует, так как миссия прототипа: «понять, как с этим работать», а миссия готового кода: «просто работать, не задавая вопросов».
                • 0
                  А смысл? С нуля написать зная при этом нюансы, которые были получены с помощью прототипа, иногда куда быстрее, чем рефакторить. Более-того Программера при разработке прототипа не связывают каким-либо конкретным языком программирования, он волен выбрать любой, лишь бы быстрее получить Proof-Of-Concept. У нас в команде так и делается, одна часть ребят пишет сначала Proof-Of-Concept на Python, убеждается что да, это возможно запилить и только потом «великие проекта сего» определяют что реализовывать другой части ребят на C++.
                  • 0
                    Я полностью согласен с вами, но вы лишь описали возможные ситуации, когда переписывание действительно необходимо. Да, бывают ситуации, когда нужно полностью изменить платформу, подход или алгоритм, в таком случае конечно проще начать с чистого листа, но так бывает далеко не всегда. Если я пишу код python, прототип разрабатываю тоже на python, подход менять не собираюсь (прототип оказался удачным), то какой смысл переписывать, если на выходе получится «почти тоже самое, только лучше»?
              • 0
                Вы просто упускаете один интересный момент: тест это своего рода спецификация, как ваш код будет выглядеть и как работать.
                Перед его написанием тоже нужно продумать архитектуру (в рамках тестируемого функционала) и просто свои мысли выразить в тесте, а не в голове. Хотите, чтобы был класс А — не сразу создаёте класс А, а сначала пишете тест: var a = new A(); Тест упал (даже не скомпилировался) -> создали класс. Затем думаете, а зачем этот класс? Да, чтобы складывать два числа. А как? Методом add(int a, int b) -> написали тест: var a = new A(); a.add(1, 2); Опять не скомпилилось -> реализовали метод. И понеслась.

                Т.е. моя мысль сводится к тому, что тесты, которые так тяжело по-началу начать писать, это в действительности ваши мысли об архитектуре создаваемого ПО, ваши предположения и рассуждения, но зафиксированные в коде. После осознания этого становится проще жить :)
              • +1
                ты можешь переписывать код с лёгкостью и комфортом, зная, что твои тесты провалятся, если ты ошибёшься и потеряешь работащую функциональность.
                это пять!
                Вообще, подход «сначала подумай, как будешь использовать, а потом реализуй» — это и есть то самое рациональное зерно, на мой взгляд. Но оно и было изначально, еще до этой методологии. Но потом потерялось куда-то оказывается.
                • +1
                  Дополнительно можно почитать Типы тестов
                  • +3
                    Так как мы проводим большое количество времени непосредственно взаимодействуя с объектами и функциями которые мы пишем, архитектура проявляется из кода сама.
                    Архитектура проявится сама только если до этого был опыт работы с похожей системой, похожими объектами и функциями. Тогда да, все легко и быстро «само пишется». Если предметная область незнакома и опыта мало, то придется потратить какое-то время на обдумывание архитектуры и не надеяться, что она сама нарисуется.
                    • 0
                      Архитектура глобально обычно продумывается в то же время, когда идёт оценка самой идеи — так, по-крайней мере в моём случае, я думаю многие согласятся.
                      Локальная архитектура, например архитектура кода для корзины в интернет-магазине, тоже продумывается немного загодя, перед написанием кода, но если действительно думать на уровне переиспользования и функционала объектов, то она может и поменяться — могут всплыть(специально или случайно) совсем другие паттерны. Я не проверял, но теоретически такое возможно.
                      • +2
                        Ирония в том, что у прогрессивного разработчика практически всегда «область незнакома и опыта мало». :) Иначе зачем вообще писать то, что уже однажды было написано?
                        • 0
                          Если прогрессивный разработчик прогрессивно разрабатывает больше двух-трех лет и у него все еще мало опыта, то тут стоит задуматься.
                      • +12
                        Как мне кажется TDD подходит, когда:
                        1. все заранее известно о проекте, есть подробная спецификация
                        2. куча времени
                        3. проект не планируется сильно или вообще ни как менятся в ближаешем будущем.

                        а не когда:
                        1. заказчик сам не знает, что хочет
                        2. спеки меняются 5 раз на день
                        3. и сделать все нужно в сжатые сроки

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

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

                        А про TDD UI тесты вообще страшно говорить :)
                        • –6
                          1. заказчик сам не знает, что хочет
                          2. спеки меняются 5 раз на день
                          3. и сделать все нужно в сжатые сроки

                          я бы предпочел застрелиться
                          • +5
                            Вы лучше просто в сторонку отойдите, половина проектов ведется так (по многим причинам) и есть люди, готовые ими заниматься.
                            • –5
                              Может лучше вы тогда отойдете в сторонку и не будете говорить что это ок в посте про методологию для улучшения качества? Я так понимаю у вас приоритет деньги-скорость на треугольнике деньги-скорость-качество.
                              • +4
                                В большом мире среди океана проектов доля софта я ля Curiosity исчезающе мала. И это не потому что все такие ленивые и не хотят писать тесты.
                                • 0
                                  Я не говорю что нужно уходить в качество. Я имею в виду то что все должно быть взвешенно.
                                  Да и эти три пункта это сильный стресс — я не люблю такие проекты и поэтому не берусь за них.
                                • +4
                                  У треугольника есть и четвертое измерение, иначе разные команды вели бы проекты исходя из этих трех данностей абсолютно одинаково.

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

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

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

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

                                  Если хочется поиграть в идеологов, и настаивать на том, что тестируемость гарантирует хорошую архитектуру и менее явные плюсы, чтож, можно не экономить на написании избыточных тестов. У всего есть своя цена.
                                  • 0
                                    Я отлично это понимаю — почитайте остальные мои комментарии )
                                    Я далеко не идеолог — я практик. Причем с разных сторон баррикад — и как владелец продукта, и как программист.
                              • НЛО прилетело и опубликовало эту надпись здесь
                                • 0
                                  Мое, пардон?
                                  • НЛО прилетело и опубликовало эту надпись здесь
                                    • 0
                                      Ну так у нас в стране забивать и молчать в тряпочку является нормой как правило — это же не значит что я должен поступать так-же. Данные вещи становятся нормой, когда люди переступают через себя ради чужих ценностей.

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

                                      Когда это действительно экстренная ситуация — я согласен что 3 причины имеют место быть, и я готов принять их. Но не когда они становятся нормой. Когда они норма — это 100% факап недальновидного и глупого руководства или стиль ведения бизнеса. В обоих случаях я не хочу быть рядом.
                                      • НЛО прилетело и опубликовало эту надпись здесь
                              • +6
                                «3. проект не планируется сильно или вообще ни как менятся в ближаешем будущем.»

                                Вы очевидно ничего не поняли в TDD.

                                Как раз если предполагается развитие и доработка системы в течение всего жизненного цикла (особенно когда приложение должно находится в продакшне), то тесты просто жизненно необходимы.

                                Это вещи из серии: тише едешь, дальше будешь…
                                • –1
                                  Как отличается
                                  «3. проект не планируется сильно или вообще ни как менятся в ближаешем будущем.»
                                  от
                                  «Это вещи из серии: тише едешь, дальше будешь…»

                                  Разве это не одно и тоже? Проект у нас меняется медленно и неторопливо, все протестировано, заказчик никуда не торопится, мы все счастливы, пьем чай и болтаем в курилке, и начальник нам все время повторяет, неторопитесь так ребята, отдохните, все успеем :)
                                  Вот ТДД в самый раз тут.
                                  • 0
                                    Во-первых п. 3 тут вообще не правда.
                                    Одним из преимуществом TDD является получением на выходе кода, который более приспособлен к изменениям, за счет того что меняется подход к разработке архитектуре классов и методов. Код получается более изолированным что как раз позволяет легко менять все подряд.

                                    Тише едешь правда на 50%. Без ТДД получается медленно когда и только начинаешь заниматься ТДД и в краткосрочной перспективе.
                                    • –1
                                      Я не говорю, что ТДД плох или не надо писать тесты вообще, я говорю что для ТДД нужно выполнение некоторых условий.

                                      1. Скажем прототип на который ушло бы месяц, займет 2, и это при учете, что мы ничего менять там не будем, иначе +2х времени на каждое изменение.
                                      2. Конечно же ТДД позволяет менять код, и ЛЮБОЙ проект меняется, различается лишь скорость изменений. В случае ТДД почти 2х медленнее.

                                      То есть опять же:
                                      1. нормальные стабильные спеки
                                      2. долгосрочный проект (куча времени)
                                      3. проект не планируется сильно менятся — вытекает из п1
                                  • +1
                                    Я бы даже сказал: вначале тише не поедешь, дальше вообще не будешь ехать.

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

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

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

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

                                    Это из-за отсутствия тестов ходят анекдоты про программистов:
                                    — Сынок, Солнце светит? Ты проверял? Тогда ничего не трогай.

                                    Что за чушь, что ТДД мешает быстрому развитию проекта. Основа экстремального программирования. Философия поддержки постоянных изменений.
                                    • 0
                                      Это вещи из серии: тише едешь, дальше будешь…

                                      мне нравится аналогия «спринт» vs «марафон». т.е. скорость важна, но разная.

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

                                      в длинных проектах важна не предельно возможная скорость, а сохранение темпа разработки на всем протяжении его развития (т.е. предсказуемость). поэтому тесты себя оправдывают.
                                      • 0
                                        Тесты это хорошая привычка независимо от размера проекта. Все проекты когда-то были маленькими.
                                    • +6
                                      Меня тоже всегда беспокоило то, что в случае с тестами время разработки увеличивается минимум на 50%. для себя вывел такое правило: стараться покрыть как можно больше функционала интеграционыыми тестами (выходит быстрее), при этом этот ф-ал должен быть стабильным чтобы не переписывать эти тесты по многу раз. Юнит-тестами покрываю тоько сложные алгоритмические части. Как правило они тестируются крайне просто, т.к. Имеют минимум зависимостей
                                      • +1
                                        2. куча времени

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

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

                                          Ну а вообще, на самом деле, все зависит от заказчика — согласен ли он оплачивать ТДД?
                                          А то все хотят ТДД, а платить за него ни кто не хочет.
                                          • 0
                                            Если в проекте всё равно заложена необходимость писать тесты, то какая для заказчика разница что именно будет написано в первую очередь? Но, если верить статье, это разные подходы, которые дают разработчикам разные выходные состояния кода.
                                            • 0
                                              Заказчик дает требования и обсуждает сроки. Это хреновый, очень хреновый заказчик, который будет говорить, как вам реализовывать и в какой последовательности что делать.

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

                                              Тут надо у заказчика спрашивать — согласен ли он оплачивать процесс целиком с вот такими-то сроками? А ТДД как раз эти сроки уменьшает и еще и надежность заметно повышает.

                                              Спрашивать «согласен ли заказчик оплачивать ТДД» равносильно «Согласны ли вы, чтобы мы сделали проект быстрее и качественнее?»
                                            • 0
                                              Проблема, мне кажется, в том, чтобы убедить руководство, что с этим подходом у нас не было таких, таких и таких проблем. Пока на своей голове не прочувствуют проблемы, не поверят. Не везде же руководство шарит в программировании )
                                              • 0
                                                >>Не везде же руководство шарит в программировании )
                                                Вы действительно уверены, что сможете убедить в пользе TDD тех кто не шарит в программировании?
                                                • 0
                                                  Когда будут реальные проблемы, и вы будете их обосновывать, я думаю, вы сможете уговорить руководство на использование того подхода, который от этих проблем избавляет. Если и это не поможет, то нужно валить как можно быстрее )
                                                  • 0
                                                    Не надо никого убеждать. Заказчику об этом знать не обязательно. Это в водопаде была фаза тестирования, а автоматические тесты до этого не писались.

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

                                                    Давайте посмотрим несколько вариантов:
                                                    1. Пишем код. Вручную дебажим. Пробегаем по веточкам в коде, чтобы увидеть, что проблем нет.
                                                    2. Пишем код. Пишем тест. При достаточном опыте, время не очень больше 1.
                                                    3. Пишем тест. Пишем код. Не очень отличается от 2.

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

                                                    А у меня например, всегда открыто окно еще одного функционального языка. Посчитать быстро что-то или даже код на шарп сгенерировать. И никто не запрещает. Если заказчик настолько умный в процессах, что начнет экономить время на тестах — пусть сам и пишет код.
                                                  • 0
                                                    Я бы сказал, что если руководство не шарит в программировании, оно и не должно лезть в то, как вы программируете, но подозреваю, что убедить его в этом будет еще сложнее. Могу только посочувствовать.
                                                • 0
                                                  >>проект не сильно или вообще ни как меняется в ближайшем будущем
                                                  Полностью согласен. Т.к. в обычных условиях (когда мы часто вносим много изменений) тесты будут просто либо всегда сваливаться, либо возвращать другой результат. Но ведь это не свидетельствует об ошибке — я намеренно изменил функционал и теперь все работает по-другому. Каждый раз актуализировать тесты ИМХО нецелесообразно и приведет лишь к потере времени: внес 1 изменение -> привел 20 тестов в соответствие -> внес 1 изменение -> привел 10 тестов в соответствие и т.д. Как с этим жить, лично мне непонятно. Потому автоматизированные тесты не использую.
                                                  • 0
                                                    То есть вас беспокоит, что падают тесты, но ничуть не беспокоит, что приложение может в разных местах начать работать неправильно, о чем вы узнаете только когда вам сообщит заказчик? Да, пожалуй TDD вам не нужно.
                                                    • 0
                                                      Дык в том и засада, что «неправильно» и «по-другому» — это разные вещи. Я изменил приложение и теперь оно работает по-другому, не так как раньше. Переписывать кучу тестов при каждом изменении, чтобы они соответствовали этому изменению — это слишком уж затратно. Ну и еще наверно от масштаба приложения зависит. Функционал в каком-то смысле поделен на уровни. Если писать кучу тестов для тестирования каждого из этих уровней — это ж застрелиться можно (будет 10-20% полезного кода, и 80-90% кода, тестирующего полезный код). А есть еще многопоточные участки кода — там видимо тесты должны имитировать различные проблемы конкурентного доступа. А кто будет отлаживать сами эти тесты? Давайте напишем еще тесты на тесты. Нет уж, не в этой жизни.
                                                      • 0
                                                        По идее тесты должны быть структурированы так, чтобы «одно изменение» в функционале было «одним изменением» в тестах.
                                                        • 0
                                                          Добавлю, что большие изменения нужно делать маленькими шагами, тогда это утверждение будет близко к истине )
                                                        • 0
                                                          Нет, не слишком затратно. Вы опять же совершенно не учитываете время на отладку и поиск ошибок. Любые крупные изменения делаются маленькими шагами. Да, это затратнее, чем просто взять и перекроить классы. Зато в каждый момент у вас стабильная система, и даже можно посередине отложить рефакторинг, чтобы реализовать какую-то срочную фичу или пофиксить баг. Альтернатива — рефакторинг в отдельной ветке, который придется долго и мучительно сливать в основную ветку, заново тестировать, а в процессе постоянно думать как это реализовано в основной ветке, а как в новой. Простите, я вижу «слишком затратно» совершенно в другом ) Впрочем, я вас не убеждаю, у каждого свой подход к разработке.
                                                      • +2
                                                        >>>тесты будут просто либо всегда сваливаться, либо возвращать другой результат

                                                        тесты не будут сваливаться, так как они изменены до изменения функционала
                                                        • 0
                                                          Совершенно верно, а если сваливаются — значит на самом деле поломалось приложение в каком-то другом месте.
                                                      • 0
                                                        По-моему, вы всё перепутали. Вообще всё.
                                                      • +1
                                                        • 0
                                                          У вашего кода покрытие тестами 100%, да?
                                                          • +1
                                                            100% не бывает. Это дикий оверхед.
                                                            Для меня, например, минимум 60%. Оптимально 70%-80%
                                                            • +1
                                                              Тогда вижу логическое противоречие с правилами №1 и №2:
                                                              В TDD есть 3 основных правила от дядюшки Боба:
                                                              • Пиши только тот код, который протестирован.
                                                              • Начинай писать тесты с малого, а затем наращивай их.
                                                              • Пиши ровно столько кода, сколько необходимо для прохождения теста.
                                                              • 0
                                                                Это уже перебор. И я ни разу не видел 100% покрытия.
                                                                • 0
                                                                  Посмотрите на sqlite
                                                              • 0
                                                                Позвольте узнать, а как тогда можно быть уверенным в приложении? Ведь соль тестов, как я понимаю — быть уверенным, что все работает как надо (помимо того, что написание тестов меняет подход к программированию). Но я вроде не такой олень, что бы ломать очевидные вещи, баги зачастую появляются или выявляются при не тривиальном использовании.
                                                                • 0
                                                                  А как можно быть уверенным в приложении вообще без тестов? )
                                                                  • 0
                                                                    Вполне можно. Разработка->Ревью->QA->Продакшн
                                                                    • 0
                                                                      Так тесты же не отменяют этого. Тесты снижают количество ошибок а не делают программу 100% рабочей. Это не панацея.
                                                                      • –1
                                                                        Тогда о чем мы здесь говорим?) На мой взгляд тесты хорошо подходят для каких нибудь фундаментальных продуктов, которыми, возможно, будет пользоватся огромная куча народа — всякие фреймворки, либы и т.д., где важно максимально возможное качество. Для рыночных же продуктов необязательно так заморачиваться и писать для всего тесты — может быть потеряно конкурентное преимущество.
                                                                        • +1
                                                                          Неа )
                                                                          Тут уже в нескольких комментах было о том что тесты!=потеря времени. Это начинает окупаться через несколько месяцев.

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

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

                                                                            Не отрицаю плюсов TDD, но для себя я выработал стратегию — сначала отвечаю на вопрос «что этот код должен делать» и «какие данные в нем могут обрабатываться», а затем уже пишу. Иногда помогает вайтборд. Как-то так.
                                                                            • 0
                                                                              Да, возможно, но чаще всего фатальность является переоценной )

                                                                              Нормальный подход. Но если вы запишите эти требования тестами — вы будете уверены что код отвечает им спустя несколько итераций рефакторинга.
                                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                                • 0
                                                                                  эм. если это приватная функция, тогда проблема не в том, что код не защищен от фывы, а где-то в голове. Если же функция публичная и\или является частью API, тогда очевидно, что надо защиту от дурака встраивать или бросать эксепшн.
                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                  • 0
                                                                                    Для этого существует типизация.
                                                                                    Используя сильно типизированные языки, будем защищены по крайней мере от таких ошибок. И чем сильнее система типов — тем больше будет множество ошибок, отсекаемых на этапе компиляции (при грамотном её использовании).
                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                      • 0
                                                                                        Для таких вещей можно и использовать code contracts, я думаю
                                                                          • 0
                                                                            A QA всегда протестирует хорошо?
                                                                            Мне вот самому любопытно, какой % тестировщиков проверяет на xss и подобные инпуты :)
                                                                            • 0
                                                                              QA есть разное. Есть просто люди, которые по стандартным кейсам проходятся, а есть люди которые и тесты сами пишут.
                                                                    • +1
                                                                      Даже 100% — не панацея, неучтенную ситуацию не протестируешь заранее. К тому же не всегда можно посчитать покрытие, в рельсах, например, вьюхи и некоторые неявно включаемые файлы не учитываются. К тому же есть код, который исполняется в принципе только на продакшене, а для тестов заменяется на заглушки (в основном работа с внешними сервисами, конечно). Так что 100% просто не будет в реальном проекте. У меня модели покрыты на 71%, при том что проект начал не я, тестов в начале вообще не было, да и TDD начал не сразу применять, я считаю, что тестов вполне достаточно, по-крайней мере срабатывают довольно часто и определенную степень уверенности обеспечивают при внесении изменений.
                                                                      PS. а вообще спасибо, что сподвигли меня проверить покрытие, оказывается Rubymine просто замечательно показывает покрытие и подсвечивает пропущенный код.
                                                                      • 0
                                                                        абсолютная величина % покрытия кода тестами, штука бессмысленная — факт. что 100% что 2%.

                                                                        показатель code coverage полезен, когда есть возможность прослеживать его в ретроспективе (как меняется от билда к билду) и соотносить с количеством багов, отлавливаемых в проекте с использованием других способов тестирования.
                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                        • +3
                                                                          Очень не хватает примеров. Это ведь самое главное.
                                                                          Спросите, кто не знает про ТТД? Большинство в какой-то мере слышали и пробовали. Но мало кто действительно применяет ТТД на практике, потому что в голове не укладывается, как перевернуть стандартный процесс с ног на голову. На переучивание уходит много времени, которое, чаще всего, не оплачивается :) Мало того, что нужно держать в голове будущую архитектуру, так еще и владеть написанием тестов в совершенстве.

                                                                          ТТД даёт большое преимущество в долгосрочной перспективе, когда проект уже выбрался из песочницы и имеет хотя бы ядро с устоявшейся архитектурой. На моём личном опыте затраты на создание окружения для тестирования на начальном этапе занимает очень много времени. Создание начального прототипа проекта очень итерационный процесс, когда ты еще только планируешь, как будешь решать поставленную задачу. И к каждой итерации по написанию кода добавляется пара итераций по написанию тестов — спроектировать тесты + написать тесты.
                                                                          • 0
                                                                            Да, переучиваться это писец как тяжело.
                                                                            Во-первых вроде как тесты не необходимость, поэтому пишешь через силу.
                                                                            Во-вторых очень хочется написать еще кучу кода, который будет «на потом». ТДД это убирает со временем.
                                                                            • +1
                                                                              Да, начать довольно сложно. Простые тесты слабо доказывают свою ценность, а что-то посложнее с непривычки писать тяжеловато. Плюс в начале проекта работа кипит, совсем не хочется спотыкаться о тесты, все ведь в голове, просто и понятно. А потом навешивать тесты — теряется смысл и главные преимущества TDD, да и времени всегда не хватает. Тут уж либо волевое решение, после осознания преимуществ такого подхода, либо, если повезет, — поработать в команде, где этот подход принят. Последний вариант, конечно, идеален.
                                                                              • 0
                                                                                Набрав TDD в поисковой строке хабра я нашёл множество примеров, и ни одной теоретической статьи(вполне может быть и невнимательность, но почти все остальные статьи — примеры). А сам я привык начинать с основ.
                                                                                • +3
                                                                                  Читайте Бека )
                                                                                  image
                                                                              • +7
                                                                                > Одно из преимуществ TDD — это постоянное наличие правильно работающего кода

                                                                                Неправда. Да, оно гарантирует, что код будет работать. Но не гарантирует, что код будет работать правильно. Потому что:
                                                                                1. Тесты могут не полностью покрывать код
                                                                                2. Тесты полностью покрывают код, но может не хватать проверок (assert'ов то бишь)
                                                                                3. В самих тестах могут быть допущены ошибки
                                                                                4. Самое главное: если отдельные блоки (классы, методы) по отдельности работают правильно, то это не значит, что весь модуль будет работать правильно. Хотя этот пробел компенсируется небольшим количеством интеграционных тестов.
                                                                                • +1
                                                                                  Тесты сами по себе не исправят ошибки за разработчика. Они позволяют разработчику легко удостоверится в том, что то, что работало вчера, работает и сегодня. Качество самих тестов, покрытие кода и необходимость интеграционных тестов — совершенно иной вопрос. Относитесь к тестам как к замене отладки — программе, которая за вас повызывает все методы в вашем коде и проверит, действительно ли они возвращают то, что предполагается. Очевидно, она это сделает быстрее и надежнее, чем вы сами.
                                                                                  • +1
                                                                                    Это понятно, что ТДД не дает стопроцентной гарантии. И со всеми пунктами согласен.

                                                                                    А какая альтернатива? Утки?

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

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

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

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

                                                                                    ТДД — это на самом деле прямой метод кодирования. Сначала требования — потом код. Читай — сначала тест на требование — потом код. Не ТДД — это сначала код, который как кажется будет удовлетворять еще не поставленному требованию, а потом требование.
                                                                                  • +7
                                                                                    Извините, но основной причиной не писать тесты является лень. Никто в обратном меня не убедит. Самому сложно было переучиваться и писать сначала тесты, а потом код, но оно того стоило. Даже когда возникает мысль «а я вот сейчас это вот быстренько набросаю, а уж потом...», всегда останавливаюсь и всё равно пишу сначала тесты. Плюс, я всегда рассматриваю тесты, как программирование: часто вылезет какая-то заковырка, которую тоже необходимо решать, чтобы она потом не вылезла. Ну и это дополнительное удовольствие видеть в консоли всё зелёненькое (-:
                                                                                    • 0
                                                                                      простое написание без самого написания не особо продвинуло меня в этом направлении).
                                                                                      • 0
                                                                                        В юнит-тестах, как известно, тяжело тестировать GUI, БД и ввод-вывод на внешние ресурсы. Всю жизнь занимаюсь разработкой приложений, на 90% состоящих из этих трех вещей. TDD может что-нибудь предложить для таких как я?
                                                                                        • +3
                                                                                          А какая разница юнит-тестам, с чем работает ваше приложение? Юнит-тесты тестируют модуль в изоляции. Все внешние зависимости мокаются. Тут совершенно не важно, идет ли взаимодействие с БД или по HTTP, либо оно не взаимодействует вообще ни с чем — писать тесты по сложности одинаково.
                                                                                          • +1
                                                                                            в случае с gui, внешние зависимости это пользователь, с одной стороны, и модель предметной области — с другой. «замокать» аспекты поведения которых может быть проблемой. :)
                                                                                            • +1
                                                                                              Как вообще предлагается тестировать GUI? Если используется MVC, то протестить можно модель и, если повезёт, ещё контроллеры. Но как тестить представления? Типичные примеры ошибок:
                                                                                              • При передаче некоторой комбинации параметров GUI подвисает секунд на 5, потом как ни в чём не бывало продолжает работу
                                                                                              • В некоторых режимах кнопки мерцают при отрисовке или анимации
                                                                                              • В ряде случаев «едут» координаты кнопок
                                                                                              • При некоторых настройках ОС (локализация, размеры шрифтов, разрешение экрана) часть окна вылезает за пределы экрана, надписи лезут за кнопки и т.д.

                                                                                              Все подобные глюки малореально покрыть тестами, т.к. имеет место внешняя зависимость.
                                                                                              Вообще, тесты хороши только для программ, написанных в функциональном стиле, когда результат зависит только от переданных в функцию параметров.
                                                                                              А если результат работы класса зависит ещё и от некоторого контекста, тесты вообще больше похожи на потерю времени, т.к. придётся ещё придумывать, как сэмулировать разные варианты контекста. И, между прочим, тесты сильно искажают архитектуру — её приходится усложнять, чтоб только втиснуть возможность тестирования нужных классов.
                                                                                              П.С.: Вот вам последний пример: habrahabr.ru/company/apps4all/blog/162291/
                                                                                              Хром (между прочим покрытый тестами!) просто и без затей падал, потому что сервер возвращал код ошибки. Отличный пример того, что код, зависящий от контекста, слабо поддаётся тестированию.
                                                                                              • 0
                                                                                                Тестировать представление? Вот у меня, к примеру, представление — это чистый html. Его что можно протестировать? Ну разве что проверить на валидность? Юнит-тесты — хорошая вещь, но до маразма-то не надо доходить.

                                                                                                Тесты усложняют архитектуру? А она и так будет усложняться, если у вас более-менее большое приложение. При правильном проектировании вам придется делать декомпозицию на мелкие классы, вводить наследование, интерфейсы, инверсию и внедрение зависимостей, применять шаблоны проектирования и т.д. А иначе ваш проект рано или поздно просто развалится, как карточный домик. Тесты, если и вносят, какую-то сложность, то очень небольшую. Ну максимум где-то придется отказаться от final классов/методов да повысить видимость метода с private на package (в случае java).
                                                                                                • 0
                                                                                                  Все подобные глюки малореально покрыть тестами, т.к. имеет место внешняя зависимость.

                                                                                                  не сочтите за буквоедство, но глюки не покрываются тестами — они ими выявляются, как побочный эффект.
                                                                                                  тесты бывают разные и не только автоматические. их природа не влияет на покрытие — вопрос лишь времени и стоимости).
                                                                                                • 0
                                                                                                  Все верно, только если огородить все внешнее окружение — останется 10% функциональности, покрытой тестами, и толку от таких тестов? Повторюсь, речь идет о сегменте корпоративных приложений. В одной книжке от HP, недавно попавшей мне в руки, продвигается идея о том что тесты должны быть направлены на проверку конкретных бизнес-процессов. Т.е. функциональные тесты. Они не отрицают юнит-тестирование, но дополняют его. И они могут выявить проблемы с бизнес-логикой, в отличие от юнит-тестов.
                                                                                                  Кое-что уже удалось внедрить и даже выявить и решить некторые проблемы, да.
                                                                                                • 0
                                                                                                  MVP паттерн. Само ГУИ делать так, чтобы там не было логики. Выбрать такую реализацию паттерна, где данные связаны с контролами через биндинг. Это позволит меньше кодировать этот самый паттерн.

                                                                                                  Далее, т.к. логики в представлении нет, то мокается интерфейс и всё нормально.
                                                                                                  • 0
                                                                                                    Как протестировать масштабирование интерфейса? Видимость контролов? Переключение слоев представлений? Проверить что текст везде помещается? Картинки не съезжают? И еще over9000 кейсов

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

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

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

                                                                                                      Ну и последнее предложение — можно использовать некоторые вещи, которые тестируют по настоящему ГУИ. Нажатие кнопочек и т.д. Я лично не пользовался такими, только слышал. Но на самом деле — примитив. Это можно сделать даже просто поняв идею и самому. Тестировщик нажимает в некоторой последовательности по приложению и получает отклик. Эта ерунда параллельно фиксирует координаты мыши и снимает картинки с экрана. А потом, она умеет повторять действия автоматически. На самом деле это не ТДД. И на самом деле такой тест можно зафиксировать, когда действительно всё работает как хотелось. Польза таких тестов только в том, что вы фиксируете правильное поведение. И если вдруг оно изменится, тест сломается.
                                                                                                      Надобность этих тестов под вопросом, если у вас действительно очень «тонкое» ГУИ представление. Но все таки какой-то плюс в копилку надежности. Это вроде ручного тестирования, просто оно уже может прогоняться автоматически.

                                                                                                      «И еще over9000 кейсов»
                                                                                                      Да хоть миллиард. Тестами не надо покрывать всё. Есть определенный баланс. Но он близкий к 100. Понятие «всё» в покрытии тестами субъективно. А еще более субъективно — 80 процентов, ну или другая цифра. Программист определяет, что ему покрывать тестами. По сути, это параллельное программирование «против себя». Т.е. ну вроде вы играете в шахматы сами с собой. То за себя, то за противника. Тесты пишутся за противника. Тесты — это параллельная программа, которая устанавливает ограничения основной программе.
                                                                                                      Исходя из этого вы сами нащупаете «больные места» вашей программы, сможете вынести всё что можно из представления в модель, чтобы надлежащим образом протестировать. Гарантии того, что тесты всё покроют, никто дать не может. Точно также как нельзя дать гарантию, что ваша программа делает то, что задумано. Но если вы делаете другую программу, которая контролирует первую — вероятность того, что вы сделаете то, что вы понимаете в требованиях без отклонений — вырастает во много раз (в сотни?).

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

                                                                                                        Ну и последнее предложение — можно использовать некоторые вещи, которые тестируют по настоящему ГУИ. Нажатие кнопочек и т.д

                                                                                                        Знаем, умеем, давно пользуемся.
                                                                                                • 0
                                                                                                  Лично я вижу преимущество использования TDD в том, что когда ты поймал баг не покрытый тестом, ты единожды исправляешь тест. Имел опыт общения с одним западным разработчиком. Я ему баг, он тест кейс и фикс. Был немного поражен данным подходом.
                                                                                                  • 0
                                                                                                    Вы знаете, это две разные вещи. Тесты могут быть написаны как ДО, так и ПОСЛЕ. Самое главное назначение тестов — обеспечить регрессию. И в обоих случаях они ее обеспечивают. Бонус TDD в том, что кроме регрессии, он еще и вырисовывает сипатичный дизайн.
                                                                                                    • 0
                                                                                                      Тесты ПОСЛЕ, без теста ДО — это уже не TDD.
                                                                                                      Особенность TDD в том что тест пишется ДО написания целевого кода. Вся загвоздка именно в этом «ДО». Все однозначно: Не написал тестовый код, до основного кода, значит не применил TDD.

                                                                                                      >>Самое главное назначение тестов — обеспечить регрессию
                                                                                                      Это из другой оперы обширного моря «тестирование ПО».
                                                                                                      Никто не говорит что регрессия или что-то другое из этого плохо.
                                                                                                      TDD лишь говорит и подчеркивает что разработчик должен сначала написать тест и только потом код. И только так!

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

                                                                                                      И:
                                                                                                      TDD это инструмент разработчика, а не тестировщика.
                                                                                                      • 0
                                                                                                        Да, но какой конкретно бонус от написания до? Самодисциалина? На счёт перечисленных в статье преимуществ я написал ниже.
                                                                                                        • 0
                                                                                                          Преимуществ достаточно много вот несколько:

                                                                                                          1)
                                                                                                          Тест к будущему коду это отличный способ раздачи задач своим подчиненным. Они получают точное понимание того что Тимлид хочет от них, а Тимлид получает быстрый способ проверить что код работает так как он задумал. Также подчиненный может смело отмазываться «Так ты же сам написал так!»
                                                                                                          2)
                                                                                                          У человека не получится написать тестового кода, если у него нет точного понимания как должен работать основной код. Другими словами написать тест означает полностью понять что вы хотите получить в конечном итоге
                                                                                                          3)
                                                                                                          Очень часто откладывание на ПОСЛЕ так и остается желанием написать, которое не всегда претворяется в жизнь. Вы всегда сможете пересмотреть набор тестов и удалить те которые уже не нужны потому что «транзитивны», т.е. то что проверяют они проверяются и другими, но удалять проще, чем писать.

                                                                                                          TDD рождает:
                                                                                                          * Отличную и актуальную документацию о том как что-то должно работать
                                                                                                          * Четкое понимание того что пишется
                                                                                                          * Уверенность в том, что новая фича действительно реализована в том виде в котором просили(тест зеленый)

                                                                                                          Об этом можно долго писать и рассуждать. Я предпочитаю пробовать и на «своей шкуре» понимать «работает это у меня или нет». Вы попробуйте, а потом поймете что что-то не работает и будут вполне реальные вопросы.
                                                                                                          • +1
                                                                                                            >>>Тест к будущему коду это отличный способ раздачи задач своим подчиненным

                                                                                                            Это надо писать big test upfront, а обычно рекомендут быстрые циклы reg -> green -> refactor
                                                                                                        • 0
                                                                                                          Да, я все это знаю :). Эти был скорее не комментарий к статье, а комментарий к обсуждению статьи.
                                                                                                      • 0
                                                                                                        Мысли на счёт преимуществ именно TDD…

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

                                                                                                        > Изменения без страха
                                                                                                        > Живая документация
                                                                                                        Это не преимущества TDD, а вообще юнит-тестов. Если их писать после, а не до, то эти преимущества не уходят.

                                                                                                        > Архитектура через код
                                                                                                        какая-то архитектура выйдет, да. Но будет ли это оптимальная архитектура? Может если продумать архитектуру заранее, вышло бы быстрее и\или оптимальнее? Гарантий вроде как нету.
                                                                                                        • +1
                                                                                                          Тут скорее имеется в виду постоянное прохождение кодом тестов. Но например посередине имплементации какой-нибудь большой фичи тесты будут проходится, но реально фича работать не будет.


                                                                                                          Это зависит от личной ответственности. Если вы пишете тесты ПОСЛЕ, то тогда часто они для галочки и пишутся. Потому как кажется, что код УЖЕ написан и работает.
                                                                                                          Если же вы точно знаете требование заказчика, то выделить существенные вещи и написать тест вполне по силам программисту. Если же он не понимает назначение тестов и хочет, чтобы в глазах начальства и тесты были и просто проходили, то смысл эти тесты и писать тогда?
                                                                                                          В любом случае вы правы, что тест не дает полную гарантию. Но это совершенно не значит, что тратить время на тесты бесполезно. Тесты при нормальном подходе дают высокую гарантию качества.

                                                                                                          какая-то архитектура выйдет, да. Но будет ли это оптимальная архитектура? Может если продумать архитектуру заранее, вышло бы быстрее и\или оптимальнее? Гарантий вроде как нету

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

                                                                                                          Мой опыт показывает — не будет быстрее и оптимальнее. Всегда при продумывании наперед проекты неимоверно затягивались, а код выдавал сюрпризы еще очень долго после завершения проекта. И наоборот. С ТДД написание кода шло совсем немного медленнее, но код становился неубиваемым и время на переписывание (при изменении требований) уменьшалось. И волшебным образом вдруг проекты перестали затягиваться по времени. А поддержка их становилась гораздо проще — практически багов не возникало потом.
                                                                                                          • 0
                                                                                                            Про архитектуру: быстрее и оптимальнее может быть, но дешевле в сопровождении — вряд ли. В современном мире важнее скорость и стоимость разработки, поддержки, нежели оптимальность и производительность.
                                                                                                            • 0
                                                                                                              Оптимальнее будет с тестами. Устал объяснять в другом посте.

                                                                                                              Кратко и более точно. Никогда (НИКОГДА) в проектировании не закладывают оптимальность. (Макконел, «Совершенный код»). Преждевременная оптимизация — наибольшее зло (Кнут).

                                                                                                              Фаза оптимизации проекта находится в самом конце, после написания кода. И совсем не зря. Любая оптимизация, даже мелкая, в процессе получения первого кода — является преждевременной.

                                                                                                              Дело в том, что цель оптимизации — найти глобальный максимум оптимизации. И это возможно, когда код написан полностью по DRY и YAGNI. Если нет дублирования кода и данных — оптимизация становится довольно тривиальной задачей. Когда код написан самым простым способом, он потенциально легко меняется в любом направлении. Не в смысле «настраивается», когда чрезмерную гибкость закладывают с помощью разных паттернов, а просто кода минимум и значит не вызывает больших проблем переписывание.
                                                                                                              Когда код находится в таком состоянии, оптимизация происходит итерационно: замеры; определение самого узкого места; оптимизация. При этом стандартные методы оптимизации есть.
                                                                                                              Если же человек оптимизировал заранее, то во-первых, код значительно хуже поддается изменениям, если вообще поддается. Во-вторых, картинка изменилась и он уже попал в какой-то бугорок — подъем стандартными методами оптимизации вряд ли даст глобальный максимум. В первом случае тоже нет гарантии, но во втором всё намного плачевнее.

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

                                                                                                              Главная ерунда, которая заставляет людей заранее оптимизировать — это отсутствие опыта в реальных проектах, требующих оптимальности. Если человек хоть раз делал замеры и оптимизировал, как надо, то вдруг появляется другое понимание. А именно: люди оптимизирующие заранее, пользуются «чутьем», которое основано на понимании «дорогой операции». Так вот, неграмотные студенты: дорогих операций нет самих по себе. Всегда есть совокупность факторов. И получается всегда некоторая сумма факторов. И вот, если некоторая операция выполняется день, а вторая секунду, то вторая может убить производительность, если выполняется миллионы раз, а первая 1 раз. День никак не критичен с потерей нескольких лет. Оптимизировать операцию, занимающую день — не смысла. А если эта оптимизация еще и вторую операцию и потом нельзя будет оптимизировать вторую — проект пропал.

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

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

                                                                                                              В общем ТДД и оптимизация очень дружат на самом деле.

                                                                                                              А желание оптимизировать всё и вся, выдает студентов (возможно вечных), при этом не объясняется логически. Просто люди убеждены, что это круто. И упрекают друг друга, если у кого-то код неоптимальный.
                                                                                                              • 0
                                                                                                                Конечно, я вас не хочу оскорбить и не к вам относится «неграмотные студенты». Таких оптимизаторов Макконел студентами называл.

                                                                                                                Вот я к ним и обращаюсь. Сразу в гнездо. Потому как на местах, где работаем, эта «оптимизация» захлестывает. И наверное надо их как-то обзывать, оскорблять и говорить, что их «профессионализм» — это «посредственность и бездарность». Потому что их понимание, как надо писать код, как раз основано на комплексах и взаимных упреках. Это психологическое что-то. Надо клин клином.
                                                                                                                • 0
                                                                                                                  Вы меня не до конца поняли. Я в своём комментарии написал, что без тестов — возможно архитектура и будет оптимальнее и производительнее. Возможно. Но с тестами она точно будет яснее, нагляднее, проще и дешевле в поддержке. Так что с вашим мнением я совершенно согласен :)

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