Что я потеряю, приняв тестовый дизайн?
Список только негативов; не перечисляйте льготы, написанные в отрицательной форме.
Что я потеряю, приняв тестовый дизайн?
Список только негативов; не перечисляйте льготы, написанные в отрицательной форме.
Ответы:
Несколько недостатков (и я не утверждаю, что нет никаких преимуществ - особенно при написании основы проекта - это сэкономит много времени в конце):
Если вы хотите создать «настоящий» TDD (читай: сначала тестируйте с красным, зеленым, с шагами рефакторинга), то вам также нужно начать использовать макеты / заглушки, когда вы хотите протестировать точки интеграции.
Когда вы начнете использовать mocks, через некоторое время вы захотите начать использовать Dependency Injection (DI) и контейнер Inversion of Control (IoC). Для этого вам нужно использовать интерфейсы для всего (что само по себе имеет много подводных камней).
В конце концов, вы должны написать намного больше кода, чем если бы вы просто делали это «простым старым способом». Вместо того, чтобы просто использовать класс клиента, вам также нужно написать интерфейс, макет класса, некоторую конфигурацию IoC и несколько тестов.
И помните, что тестовый код также следует поддерживать и заботиться. Тесты должны быть такими же удобочитаемыми, как и все остальное, и для написания хорошего кода требуется время.
Многие разработчики не совсем понимают, как сделать все это «правильным способом». Но поскольку все говорят им, что TDD - единственный верный способ разработки программного обеспечения, они просто стараются изо всех сил.
Это гораздо сложнее, чем можно подумать. Часто проекты, выполненные с использованием TDD, заканчиваются большим количеством кода, который никто на самом деле не понимает. Модульные тесты часто проверяют не то, что неправильно. И никто не согласен с тем, как должен выглядеть хороший тест, даже так называемые гуру.
Все эти тесты усложняют «изменение» (в отличие от рефакторинга) поведения вашей системы, а простые изменения становятся слишком сложными и отнимающими много времени.
Если вы читаете литературу по TDD, всегда есть несколько очень хороших примеров, но часто в реальных приложениях вы должны иметь пользовательский интерфейс и базу данных. Здесь TDD становится действительно трудным, и большинство источников не предлагают хороших ответов. И если они это делают, это всегда включает в себя больше абстракций: фиктивные объекты, программирование на интерфейс, шаблоны MVC / MVP и т. Д., Что опять же требует много знаний, и ... вы должны написать еще больше кода.
Так что будьте осторожны ... если у вас нет команды энтузиастов и хотя бы одного опытного разработчика, который знает, как писать хорошие тесты, а также знает несколько вещей о хорошей архитектуре, вам действительно нужно дважды подумать, прежде чем идти по дороге TDD ,
Когда вы достигаете точки, где у вас есть большое количество тестов, изменение системы может потребовать переписывания некоторых или всех ваших тестов, в зависимости от того, какие из них были признаны недействительными в результате изменений. Это может превратить относительно быструю модификацию в очень трудоемкую.
Кроме того, вы можете начать принимать проектные решения, основываясь больше на TDD, чем на действительно хороших дизайнерах. В то время как у вас могло быть очень простое и легкое решение, которое невозможно протестировать в соответствии с требованиями TDD, теперь у вас гораздо более сложная система, которая на самом деле более подвержена ошибкам.
if part of the system is covered by tests and they pass, then everything is fine (including design)
.
Я думаю, что самая большая проблема для меня - ОГРОМНАЯ потеря времени, необходимая для того, чтобы «войти в нее». Я все еще очень в начале моего пути с TDD (см. Мой блог для обновлений моих тестовых приключений, если вам интересно), и я буквально потратил часы, чтобы начать.
Требуется много времени, чтобы привести ваш мозг в «режим тестирования», и написание «тестируемого кода» само по себе является навыком.
TBH, я с уважением не согласен с комментариями Джейсона Коэна по поводу обнародования частных методов, но это не совсем так.Я сделал не более публичных методов в моем новом способе работы, чем раньше . Однако он включает в себя архитектурные изменения и позволяет вам «горячо подключать» модули кода для упрощения тестирования всего остального. Вы не должны делать внутреннюю часть вашего кода более доступной для этого. В противном случае мы вернемся к исходной точке, где все открыто, где инкапсуляция в этом?
Итак, (IMO) в двух словах:
PS: Если вам нужны ссылки на позитивы, я задавал и отвечал на несколько вопросов, проверьте мой профиль .
За те несколько лет, когда я практиковался в разработке через тестирование, я бы сказал, что самые большие недостатки:
TDD лучше всего делать парами. Во-первых, трудно сопротивляться желанию просто написать реализацию, когда вы ЗНАЕТЕ, как написать оператор if / else . Но пара будет держать вас на задании, потому что вы держите его на задании. К сожалению, многие компании / менеджеры не считают, что это хорошее использование ресурсов. Зачем платить двум людям за написание одной функции, если у меня есть две функции, которые нужно сделать одновременно?
Некоторые люди просто не имеют терпения для написания модульных тестов. Некоторые очень гордятся своей работой. Или некоторые просто любят видеть, как замысловатые методы / функции стекают с края экрана. TDD не для всех, но мне бы очень хотелось. Это сделало бы поддержку вещей намного проще для тех бедных душ, которые наследуют код.
В идеале ваши тесты будут ломаться только тогда, когда вы примете неверное решение. То есть вы думали, что система работает в одном направлении, а оказывается, что нет. Нарушая тест или (небольшой) набор тестов, это на самом деле хорошие новости. Вы точно знаете , как ваш новый код повлияет на систему. Однако, если ваши тесты плохо написаны, тесно связаны или, что еще хуже, генерируются ( кашель VS Test), то поддержание ваших тестов может быстро стать хором. И после того, как достаточное количество тестов начнет вызывать больше работы по сравнению с воспринимаемой ценностью, которую они создают, тесты будут удалены в первую очередь, когда графики будут сжаты (например, оно дойдет до времени обработки)
В идеале, если вы придерживаетесь методологии, ваш код будет на 100% протестирован по умолчанию. Как правило, подумал я, в конечном итоге охват кода выше 90%. Это обычно происходит, когда у меня есть некоторая архитектура стиля шаблона, и тестируется основа, и я пытаюсь срезать углы, а не тестировать настройки шаблона. Кроме того, я обнаружил, что, когда я сталкиваюсь с новым барьером, с которым я ранее не сталкивался, у меня есть кривая обучения в тестировании этого. Я признаю, что написал несколько строк кода по-старому, но мне бы очень хотелось, чтобы это было на 100%. (Полагаю, я был в школе более успешным, э-э-школа).
Тем не менее, с учетом этого я бы сказал, что преимущества TDD намного перевешивают недостатки простой идеи: если вы сможете получить хороший набор тестов, которые охватывают ваше приложение, но не настолько хрупки, что одно изменение нарушит их все, вы будете быть в состоянии добавлять новые функции на 300-й день вашего проекта, как вы делали на 1-й день. Этого не происходит со всеми теми, кто пытается использовать TDD, думая, что это волшебная пуля для всего их кода с ошибками, и поэтому они считают, что это не работает, точка.
Лично я обнаружил, что с помощью TDD я пишу более простой код, я трачу меньше времени на обсуждения, будет ли работать конкретное кодовое решение или нет, и что я не боюсь изменить любую строку кода, которая не соответствует критериям, установленным команда.
TDD - сложная дисциплина для освоения, и я занимаюсь ею несколько лет, и я все еще изучаю новые методы тестирования все время. Это огромные затраты времени, но в долгосрочной перспективе ваша устойчивость будет намного выше, чем если бы у вас не было автоматических модульных тестов. Теперь, если бы только мои начальники могли понять это.
В вашем первом проекте TDD есть две большие потери, время и личная свобода
Вы теряете время, потому что:
Вы теряете личную свободу, потому что:
Надеюсь это поможет
TDD требует, чтобы вы спланировали, как будут работать ваши классы, прежде чем писать код для прохождения этих тестов. Это и плюс, и минус.
Мне трудно писать тесты в «вакууме» - до того, как был написан какой-либо код. По своему опыту я склонен спотыкаться о своих тестах всякий раз, когда я неизбежно думаю о чем-то во время написания своих классов, которые я забыл при написании своих первоначальных тестов. Тогда пришло время не только реорганизовать мои занятия, но и мои тесты. Повторите это три или четыре раза, и это может расстроить вас.
Я предпочитаю сначала написать черновик своих уроков, а затем написать (и поддерживать) блок юнит-тестов. После того, как у меня есть черновой вариант, TDD работает нормально. Например, если сообщается об ошибке, я напишу тест, чтобы использовать эту ошибку, а затем исправлю код, чтобы тест прошел.
Прототипирование может быть очень трудным с TDD - когда вы не уверены, какую дорогу вы собираетесь предпринять, написать предварительные тесты может быть сложно (кроме очень широких). Это может быть болью.
Честно говоря, я не думаю, что для «основной разработки» для подавляющего большинства проектов есть какой-то реальный недостаток; о нем говорят гораздо больше, чем следовало бы, обычно люди, которые считают, что их код достаточно хорош, чтобы им не нужны тесты (никогда не бывает), и просто люди не могут их написать.
Ну, и для этого нужно отлаживать свои тесты. Кроме того, для написания тестов существует определенная стоимость времени, хотя большинство людей согласны с тем, что это предварительные инвестиции, которые окупаются в течение всего срока службы приложения как с точки зрения экономии времени, так и с точки зрения стабильности.
Однако самая большая проблема, с которой я лично столкнулся, - это научиться писать тесты. В команде, особенно в устоявшейся команде, может быть трудно убедить их, что потраченное время того стоит.
Если ваши тесты не очень тщательны, вы можете впасть в ложное чувство «все работает» только потому, что тесты пройдены. Теоретически, если ваши тесты пройдены, код работает; но если бы мы могли писать код идеально в первый раз, нам бы не понадобились тесты. Мораль здесь состоит в том, чтобы удостовериться в том, что вы делаете проверку работоспособности самостоятельно, прежде чем вызывать что-то завершенное, а не просто полагайтесь на тесты.
На этой ноте, если ваша проверка работоспособности обнаружит что-то, что не было проверено, обязательно вернитесь назад и напишите для него тест.
Недостатком TDD является то, что он обычно тесно связан с методологией Agile, которая не важна по документации системы, а понимающих позади , почему тест «должен» возвращать одно значение конкретного , а не какой - либо другие пребывают только в разработчике глава.
Как только разработчик оставляет или забывает причину, по которой тест возвращает одно конкретное значение, а не какое-то другое, вы облажались. С TDD все в порядке, если он надлежащим образом задокументирован и окружен удобочитаемой (то есть диспетчером с острыми волосами) документацией, на которую можно ссылаться через 5 лет, когда мир изменится, и ваше приложение также будет нуждаться в этом.
Когда я говорю о документации, это не реклама в коде, это официальное письмо, которое существует за пределами приложения, например, случаи использования и справочная информация, на которую могут ссылаться менеджеры, юристы и бедняга, который должен обновить Ваш код в 2011 году.
Я столкнулся с несколькими ситуациями, когда TDD сводит меня с ума. Чтобы назвать некоторые:
Ремонтопригодность сопровождения:
Если вы работаете на большом предприятии, есть много шансов, что вам не нужно писать тестовые примеры самостоятельно, или, по крайней мере, большинство из них написаны кем-то другим, когда вы входите в компанию. Функции приложения время от времени меняются, и если у вас нет системы, такой как HP Quality Center, чтобы отслеживать их, вы сразу же сходите с ума.
Это также означает, что новым членам команды потребуется достаточно времени, чтобы понять, что происходит с тестовыми примерами. В свою очередь, это можно перевести на большее количество необходимых денег.
Сложность автоматизации тестирования:
Если вы автоматизируете некоторые или все тестовые случаи в машинно-управляемые тестовые сценарии, вы должны будете убедиться, что эти тестовые сценарии синхронизированы с соответствующими ручными тестовыми сценариями и соответствуют изменениям приложения.
Кроме того, вы потратите время на отладку кодов, которые помогут вам обнаруживать ошибки. На мой взгляд, большинство этих ошибок связано с тем, что команда тестирования не отражала изменения приложения в сценарии тестирования автоматизации. Изменения в бизнес-логике, графическом интерфейсе и других внутренних вещах могут заставить ваши сценарии перестать работать или работать ненадежно. Иногда изменения очень тонкие и их трудно обнаружить. Когда-то все мои скрипты сообщали об ошибке, потому что они основывали свои вычисления на информации из таблицы 1, а таблица 1 теперь была таблицей 2 (потому что кто-то поменял местами имена объектов таблицы в коде приложения).
Самая большая проблема - это люди, которые не знают, как правильно писать модульные тесты. Они пишут тесты, которые зависят друг от друга (и они отлично работают при работе с Ant, но внезапно терпят неудачу, когда я запускаю их из Eclipse, просто потому, что они работают в другом порядке). Они пишут тесты, которые ничего не тестируют - они просто отлаживают код, проверяют результат и превращают его в тест, называя его «test1». Они расширяют область применения классов и методов только потому, что им будет проще писать модульные тесты. Код модульных тестов ужасен, со всеми классическими проблемами программирования (сильная связь, методы длиной 500 строк, жестко запрограммированные значения, дублирование кода), и это адское обслуживание. По какой-то странной причине люди относятся к юнит-тестам как к чему-то хуже "реального" кода, и они не не заботятся об их качестве вообще. :-(
Вы теряете много времени, потраченного на написание тестов. Конечно, это может быть сохранено к концу проекта, быстрее обнаруживая ошибки.
Самым большим недостатком является то, что если вы действительно хотите сделать TDD правильно, вам придется много потерпеть неудачу, прежде чем вы добьетесь успеха. Учитывая, сколько программных компаний работает (доллар за KLOC), вас в конечном итоге уволят. Даже если ваш код быстрее, чище, проще в обслуживании и содержит меньше ошибок.
Если вы работаете в компании, которая платит вам KLOC (или выполненными требованиями - даже если они не проверены), держитесь подальше от TDD (или проверок кода, или парного программирования, или непрерывной интеграции и т. Д. И т. Д. И т. Д.).
Вы теряете способность сказать, что вы сделали, прежде чем тестировать весь свой код.
Вы теряете возможность писать сотни или тысячи строк кода перед его запуском.
Вы теряете возможность учиться через отладку.
Вы теряете гибкость при отправке кода, в котором вы не уверены.
Вы теряете свободу крепко соединять свои модули.
Вы теряете возможность пропустить написание низкоуровневой проектной документации.
Вы теряете стабильность, которая приходит с кодом, который все боятся изменить.
Я второй ответ о начальном времени разработки. Вы также теряете способность комфортно работать без безопасности испытаний. Я также был описан как чокнутый TDD, так что вы можете потерять несколько друзей;)
Переориентация на сложные, непредвиденные требования является постоянной проблемой программиста. Разработка, основанная на тестировании, заставляет вас сосредоточиться на уже известных, обыденных требованиях и ограничивает вашу разработку тем, что вы уже вообразили.
Подумайте об этом, вы, скорее всего, в конечном итоге будете проектировать под конкретные тестовые случаи, поэтому вы не станете креативными и начнете думать, что «было бы здорово, если бы пользователь мог выполнять X, Y и Z». Поэтому, когда этот пользователь начинает волноваться по поводу потенциальных требований к прохладе X, Y и Z, ваш дизайн может быть слишком жестко сфокусирован на уже заданных тестовых случаях, и его будет сложно настроить.
Это, конечно, обоюдоострый меч. Если вы тратите все свое время на разработку для всех мыслимых, мыслимых, X, Y и Z, которые может когда-либо захотеть пользователь, вы неизбежно никогда ничего не завершите. Если вы что-то завершите, никто (включая вас) не сможет понять, что вы делаете в своем коде / дизайне.
Написание тестов для «случайных» данных, таких как XML-каналы и базы данных, может быть трудным и длительным (не так сложно). В последнее время я провел некоторое время, работая с фидами данных о погоде. Написание тестов для этого довольно запутанно, по крайней мере, потому что у меня нет большого опыта работы с TDD.
Вы потеряете большие классы с множеством обязанностей. Вы также, вероятно, потеряете большие методы с множеством обязанностей. Вы можете потерять некоторую способность к рефакторингу, но вы также потеряете часть необходимости рефакторинга.
Джейсон Коэн сказал что-то вроде: TDD требует определенной организации для вашего кода. Это может быть архитектурно неправильно; например, поскольку частные методы нельзя вызывать вне класса, необходимо сделать методы не закрытыми, чтобы сделать их тестируемыми.
Я говорю, что это указывает на пропущенную абстракцию - если частный код действительно нуждается в тестировании, он, вероятно, должен быть в отдельном классе.
Дейв Манн
Вы должны писать приложения по-другому: тот, который делает их тестируемыми. Вы будете удивлены, насколько сложно это поначалу.
Некоторые люди находят концепцию обдумывания того, что они собираются написать, прежде чем писать слишком сложно. Такие понятия, как издевательство, могут быть трудными для некоторых тоже. TDD в старых приложениях может быть очень сложным, если он не предназначен для тестирования. TDD вокруг фреймворков, которые не являются дружественными TDD, также может быть проблемой.
TDD - это навык, поэтому младшие разработчики могут поначалу бороться (в основном потому, что их так не учили).
В целом, хотя недостатки становятся решаемыми, когда люди становятся квалифицированными, и вы в конечном итоге абстрагируетесь от «вонючего» кода и получаете более стабильную систему.
Требуется некоторое время, чтобы разобраться в этом, и некоторое время, чтобы начать делать это в проекте, но ... Я всегда сожалею о том, что не использую тестовый подход, когда нахожу глупые ошибки, которые автоматизированный тест мог бы найти очень быстро. Кроме того, TDD улучшает качество кода.
Хорошие ответы на все. Я бы добавил несколько способов избежать темной стороны TDD:
Я написал приложения для самостоятельной проверки. Проблема написания конкретных тестов заключается в том, что даже если вы пишете множество тестов, они охватывают только те случаи, о которых вы думаете. Генераторы случайных тестов обнаруживают проблемы, о которых вы не задумывались.
Вся концепция множества модульных тестов подразумевает, что у вас есть компоненты, которые могут попасть в недопустимые состояния, например сложные структуры данных. Если вы будете держаться подальше от сложных структур данных, тестирование будет намного меньше.
В той степени, в которой это позволяет ваше приложение, избегайте дизайна, который опирается на правильный порядок уведомлений, событий и побочных эффектов. Их можно легко уронить или взломать, поэтому им нужно много тестировать.
TDD требует определенной организации для вашего кода. Это может быть неэффективным или трудным для чтения. Или даже архитектурно неправильно; Например, поскольку private
методы нельзя вызывать вне класса, необходимо сделать методы не закрытыми, чтобы сделать их тестируемыми, что просто неправильно.
Когда код изменяется, вы должны также изменить тесты. С рефакторингом это может быть много дополнительной работы.
Позвольте мне добавить, что если вы применяете принципы BDD к проекту TDD, вы можете устранить некоторые из основных недостатков, перечисленных здесь (путаница, недоразумения и т. Д.). Если вы не знакомы с BDD, вам следует прочитать введение Дэна Норта. Он придумал концепцию в ответ на некоторые вопросы, возникшие в результате применения TDD на рабочем месте. Введение Дэна в BDD можно найти здесь .
Я только делаю это предложение, потому что BDD обращается к некоторым из этих негативов и действует как пробел. Вы захотите учесть это при сборе отзывов.
Вы должны убедиться, что ваши тесты всегда актуальны, момент, когда вы начинаете игнорировать красные огни, - момент, когда тесты теряют смысл.
Вы также должны убедиться, что тесты являются исчерпывающими, или в случае появления большой ошибки, тип «душного» управления, который вы, наконец, убедили, что потратите время на написание большего количества кода, будет жаловаться.
Человек, который учил мою команду гибкому развитию, не верил в планирование, вы написали столько же, что и для крошечного требования.
Его девизом был рефакторинг, рефакторинг, рефакторинг. Я понял, что рефакторинг означает «не планировать заранее».
Время разработки увеличивается: каждый метод нуждается в тестировании, и если у вас большое приложение с зависимостями, вам нужно подготовить и очистить данные для тестов.