Що я втрачаю, приймаючи тестовий дизайн?
Список лише негативів; не перераховуйте пільги, написані у негативній формі.
Що я втрачаю, приймаючи тестовий дизайн?
Список лише негативів; не перераховуйте пільги, написані у негативній формі.
Відповіді:
Кілька недоліків (і я не стверджую, що переваг немає - особливо при написанні фундаменту проекту - це заощадить багато часу в кінці):
Якщо ви хочете зробити "справжній" TDD (прочитайте: спершу тестуйте з червоними, зеленими, рефакторними кроками), тоді ви також повинні почати використовувати макети / заглушки, коли ви хочете перевірити точки інтеграції.
Коли ви почнете використовувати макети, через деякий час вам захочеться почати використовувати залежність впорскування (DI) та контейнер інверсії управління (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 (Дивіться мій блог для оновлень моїх тестувальних пригод, якщо вас цікавить), і я буквально витратив години на початок роботи.
Потрібно тривати довгий час, щоб ваш мозок перейшов у "тестовий режим", а написання "перевіряемого коду" - це вміння саме по собі.
ТБХ, я з повагою не погоджуюся з коментарями Джейсона Коена щодо оприлюднення приватних методів, це не про що йдеться. У новому способі роботи я більше не публікував публічних методів, ніж раніше . Однак це включає в себе архітектурні зміни і дозволяє вам "гарячу модуль" модулів коду, щоб полегшити тестування всього іншого. Ви не повинні робити внутрішні дані свого коду більш доступними для цього. Інакше ми повертаємося до квадратного, коли все публічне, де інкапсуляція в цьому?
Отже, (IMO) у двох словах:
PS: Якщо ви хочете посилань на позитиви, я попросив і відповів на декілька питань, перегляньте мій профіль .
Протягом кількох років, які я займаюся розробкою тестових програм, я повинен сказати, що найбільші недоліки:
TDD найкраще робити парами. Для одного важко протистояти прагненню просто написати реалізацію, коли ви ЗНАЄМО, як написати оператор if / else . Але пара буде тримати вас у завданні, тому що ви тримаєте його перед завданням. На жаль, багато компаній / менеджерів не вважають, що це вдале використання ресурсів. Навіщо платити двом людям, щоб написати одну функцію, коли у мене є дві функції, які потрібно зробити одночасно?
Деякі люди просто не мають терпіння писати одиничні тести. Деякі дуже пишаються своєю роботою. Або деякі просто люблять бачити згорнуті методи / функції, що кровоточать з кінця екрана. TDD не для всіх, але я дуже хочу, щоб це було. Це полегшило б підтримання речей для тих бідних душ, які успадковують код.
В ідеалі ваші тести будуть зламані лише тоді, коли ви приймете неправильне рішення коду. Тобто ви думали, що система працювала в один бік, і виявляється, що це не так. Побивши тест або (невеликий) набір тестів, це насправді хороша новина. Ви точно знаєте , як ваш новий код вплине на систему. Однак якщо ваші тести погано написані, щільно поєднані або, що ще гірше, породжені ( тест на кашель VS), то підтримка ваших тестів може швидко стати хором. І після того, як достатньо тестів почне спричиняти більше роботи, ніж сприймане значення, яке вони створюють, тести будуть першим, що потрібно видалити, коли графіки стискаються (наприклад, це потрапляє на час стискання)
В ідеалі, знову ж таки, якщо ви дотримуєтесь методології, ваш код буде перевірений на 100% за замовчуванням. Як правило, подумав, я закінчую покриття коду вгору на 90%. Зазвичай це відбувається, коли у мене є якась архітектура стилю шаблону, і база перевірена, і я намагаюся вирізати кути, а не перевіряти налаштування шаблону. Крім того, я виявив, що коли я стикаюся з новим бар'єром, якого раніше не стикався, у мене є крива навчання при його тестуванні. Я визнаю, що писав кілька рядків коду старим способом, але мені дуже подобається, що це 100%. (Я здогадуюсь, що я був надто успішним у школі, ер skool).
Однак з цим я б сказав, що переваги TDD набагато перевершують негативи для простої ідеї, що якщо ви зможете досягти гарного набору тестів, які охоплюють вашу програму, але не такі крихкі, що одна зміна все їх порушує, ви будете зможете продовжувати додавати нові функції в 300-й день свого проекту, як ви робили в перший день. Це не трапляється з усіма, хто намагається TDD, думаючи, що це чарівна куля до всього їхнього коду з помилками, і тому вони думають, що це може не працюю, період.
Особисто я виявив, що за допомогою TDD я пишу простіший код, я витрачаю менше часу на дебати, чи спрацює певне рішення коду чи ні, і що я не боюся змінити будь-яку рядок коду, який не відповідає критеріям, встановленим команда.
TDD - це сувора дисципліна, яку я опановую, і я займаюся цим уже кілька років, і я все ще вивчаю нові методи тестування. Попереду це величезні інвестиції, але, в довгостроковій перспективі, ваша стійкість буде набагато більшою, ніж якби у вас не було автоматизованих тестових одиниць. Тепер, якби тільки мої начальники могли це зрозуміти.
У вашому першому проекті TDD є дві великі втрати, час та особиста свобода
Ви втрачаєте час, тому що:
Ви втрачаєте особисту свободу через:
Сподіваюся, це допомагає
TDD вимагає, щоб ви планували, як працюватимуть ваші заняття, перш ніж писати код, щоб здати ці тести. Це і плюс, і мінус.
Мені важко писати тести у "вакуумі" - перед тим, як писався будь-який код. На моєму досвіді я схильний подорожувати своїми тестами всякий раз, коли неминуче щось придумую під час написання своїх занять, які я забув під час написання своїх початкових тестів. Тоді настав час не лише рефакторировать мої заняття, але ТАКОЖ мої тести. Повторіть це три-чотири рази, і це може розчаруватися.
Я вважаю за краще спершу написати чернету моїх занять, потім написати (і підтримати) акумуляторну батарею тестів. Після того, як у мене є проект, TDD працює для мене чудово. Наприклад, якщо буде повідомлено про помилку, я напишу тест для використання цієї помилки, а потім виправлю код, щоб тест пройшов.
Проведення прототипів може бути дуже складним із TDD - коли ви не впевнені, яку дорогу ви збираєтеся взяти до рішення, написання тестів на передній план може бути важким (крім дуже широких). Це може бути біль.
Чесно кажучи, я не думаю, що для «основної розробки» для переважної більшості проектів існує реальний мінус; про це говорять набагато більше, ніж це має бути, як правило, люди, які вважають, що їх код достатньо хороший, що їм не потрібні тести (це ніколи не буває), і люди, які просто не можуть потурбуватися їх писати.
Ну, і це розтягнення, вам потрібно налагодити свої тести. Крім того, є певна вартість часу для написання тестів, хоча більшість людей погоджуються з тим, що це передова інвестиція, яка окупається протягом життя програми як в економії часу, так і в стабільності.
Найбільша проблема, з якою я особисто з цим стикалася, - це дотримання дисципліни, щоб насправді писати тести. У колективі, особливо створеному колективі, важко переконати їх у тому, що витрачений час варто.
Якщо ваші тести не дуже ретельні, ви можете потрапити в помилкове відчуття "все працює" тільки тому, що ви проходили тести. Теоретично, якщо ваші тести пройдуть, код працює; але якби ми могли чудово написати код, перший раз нам не знадобляться тести. Мораль тут полягає в тому, щоб переконатися в тому, щоб зробити перевірку добросовісності самостійно, перш ніж викликати щось повне, не покладайтеся лише на тести.
На цій замітці, якщо ваша перевірка санітарної перевірки знайде те, що не перевірено, обов'язково поверніться та напишіть тест на це.
Недоліком TDD є те, що він зазвичай тісно пов'язаний з методологією "Agile", яка не надає значення документації системи, а розуміння того, чому тест "повинен" повертати одне конкретне значення, а не будь-яке інше, що знаходиться тільки в розробнику голова.
Як тільки розробник залишає або забуває причину того, що тест повертає одне конкретне значення, а не якесь інше, ви накрутили. TDD чудово, якщо він належним чином задокументований та оточений читабельною людиною (т. Е. Гострим менеджером) документацією, на яку можна звернутися через 5 років, коли світ зміниться, і ваш додаток також повинен.
Коли я кажу про документацію, це не розмиття в коді, це офіційне написання, яке існує поза додатком, наприклад, випадки використання та довідкова інформація, на яку можуть звертатися менеджери, адвокати та бідний сік, який має оновити ваш код у 2011 році.
Я стикався з декількома ситуаціями, коли TDD зводить мене з розуму. Щоб назвати деякі:
Ремонтопридатність тестового випадку:
Якщо ви на великому підприємстві, багато шансів на те, що вам не доведеться писати тестові справи самостійно або принаймні більшість з них пише хтось інший, коли ви входите в компанію. Особливості програми час від часу змінюються, і якщо у вас немає такої системи, як, наприклад, Центр якості HP, щоб відстежувати їх, ви з глузду зникнете з розуму.
Це також означає, що для нових членів команди знадобиться досить багато часу, щоб схопити те, що відбувається з тестовими кейсами. У свою чергу, це можна перекласти на більше необхідних грошей.
Складність тестування автоматизації:
Якщо ви автоматизуєте деякі або всі тестові випадки у тестових сценаріях, керованих машиною, вам доведеться переконатися, що ці тестові сценарії синхронізовані з відповідними тестами вручну та відповідно до змін програми.
Крім того, ви витратите час на налагодження кодів, які допоможуть вам зловити помилки. На мою думку, більшість цих помилок походить від того, що команда тестування не відображає зміни програми у сценарії тестування автоматизації. Зміни в бізнес-логіці, графічному інтерфейсі та інших внутрішніх матеріалах можуть змусити ваші сценарії припиняти роботу або працювати ненадійно. Іноді зміни дуже тонкі і їх важко виявити. Колись усі мої сценарії повідомляли про помилку, тому що вони засновували свій розрахунок на інформації з таблиці 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 вимагає певної організації для вашого коду. Це може бути малоефективним чи важким для читання. Або навіть архітектурно неправильно; наприклад, оскільки private
методи не можна викликати поза класом, ви повинні зробити методи не приватними, щоб зробити їх перевірятими, що просто неправильно.
Коли код змінюється, ви також повинні змінити тести. З рефакторингом це може бути багато додаткової роботи.
Дозвольте додати, що якщо ви застосовуєте принципи BDD до проекту TDD, ви можете усунути деякі основні недоліки, перелічені тут (плутанина, непорозуміння тощо). Якщо ви не знайомі з BDD, прочитайте вступ Дена Норта. Він придумав цю концепцію у відповідь на деякі питання, що виникли внаслідок застосування TDD на робочому місці. Вступ Дана до BDD можна знайти тут .
Я висловлюю цю пропозицію лише тому, що BDD вирішує деякі з цих негативів і виступає як пробіл. Ви захочете врахувати це, збираючи відгуки.
Ви повинні переконатися, що ваші тести завжди актуальні, і миттєво, коли ви починаєте ігнорувати червоні вогні, це момент, коли тести стають безглуздими.
Ви також повинні переконатися, що тести є всебічними, або, коли з’явиться велика помилка, задушливий тип управління, який ви нарешті переконали, що дозволяє витратити час на написання більше коду, скаржиться.
Людина, яка навчила мою команду спритному розвитку, не вірила в планування, ви написали лише стільки найменших вимог.
Його девізом був рефактор, рефактор, рефактор. Я зрозумів, що рефактор означає «не планувати заздалегідь».
Час розробки збільшується: кожен метод потребує тестування, і якщо у вас є велике застосування із залежностями, вам потрібно підготувати та очистити свої дані для тестів.