Які недоліки тестування першого програмування?


47

Сьогодні все це лють. «Всі» рекомендують це. Це саме по собі робить мене підозрілим.

Які ваші недоліки ви виявили під час розробки тестових розробок? Я шукаю особистого досвіду знаючих практиків - я можу прочитати гіпотетичні міркування ста баб в інших місцях в Інтернеті.

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

Відповіді:


41

Їх досить багато, але переваги значно переважають недоліки.

Існує крута крива навчання.

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

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

Ви робите більше кодування спереду.

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

Може бути жорстким продажем менеджерам.

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

Може бути жорстким продажем іншим розробникам.

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

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


Це хороші відповіді, але чи можна конкретніше щодо №1? Мені особливо цікаво почути, як / чи змогли ви відновити швидкість програмування - що ви дізналися, що не знали, коли почали робити TDD?
Алекс Фейнман

Оновлено, щоб дати уточнення
Яко Преторіус,

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

1
@JeffO, ви знайомі з "Я буду писати собі мінівен!" школа кодування?
Алекс Фейнман

1
@tvanfosson - тому що вони намагаються змінити дві речі одночасно - і початкове тестування, і також TDD - що може бути проблематично. Це також додає до оцінок часу - цілком правильно - тому менеджери та клієнти бачать лише збільшення переднього фронту, не те, що загальний час фактично відомий (за один раз) і може бути навіть меншим. Якщо вони роблять тестування, то це збільшення буде меншим.
ChrisF

35

Тест-перший передбачає, що ви пишете код, який є:

  • перевіряється в одиничному тесті
  • що те, що ви розробляєте, має очевидний підхід і не потребуватиме широкого складання прототипів чи експериментів
  • що вам не знадобиться занадто сильно переробляти або що у вас є час кілька разів переписувати сотні чи тисячі тестових випадків
  • нічого не запечатано
  • все модульно
  • все є ін'єкційним або макетним
  • що ваша організація виставляє достатньо високе значення для низьких дефектів, щоб виправдати пропуск ресурсів
  • що є щось корисне для тестування на рівні одиничного тесту

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

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

Приклади:

Мій особистий найкращий приклад - це написання коду безпеки для asp.net. Якщо вони призначені для запуску у ворожій середовищі з конфігурації машини, вони отримують підпис, підписують та скріплюють печаткою, а тому, що вони працюють проти об'єктів богів IIS, їм дуже важко дуже правильно знущатися. Додайте деякі обмеження для продуктивності та використання пам’яті, і ви дуже швидко втрачаєте гнучкість для використання об’єктів-заповнювачів на інших ділянках.

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


Чи можете ви дати кілька контрприкладів? Коли б я не писав те, що перевіряється в тестовому режимі? Чому б я не писав код, який може бути виправданим або ін'єкційним (крім застарілого коду, який є темою для себе)?
Алекс Фейнман

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

4
Домовились. TDD працює, схоже, спирається на набір припущень щодо машин, з якими ви працюєте; Схоже, це не відповідає дійсності приблизно 50% моїх проектів.
Пол Натан

Я повністю згоден ... Відмінна відповідь
Khelben

2
Це як що-небудь у цій грі - підходить для багатьох ситуацій, не підходить для інших. Остерігайтеся тих, хто виступає за єдиний вірний шлях у будь-якій галузі розробки програмного забезпечення.
Алан Б

25

Найбільший недолік, який я бачив, - це не сам TDD, а практикуючі. Вони дотримуються догматичного та завзятого підходу, де все повинно бути перевірене . Іноді (багато разів це є), це не обов'язково. Крім того, це може бути не практичним (наприклад, введення організації в TDD.)

Хороший інженер знаходить компроміси і застосовує правильний баланс, коли / де / як застосувати тест-перше. Крім того, якщо ви постійно витрачаєте набагато більше часу на розробку тестів замість фактичного коду (в 2-3 рази і більше), ви переживаєте проблеми.

Іншими словами, будьте прагматичними та розумними щодо TDD (або будь-чого в розробці програмного забезпечення з цього приводу.)


Це, можливо, звідки походить "нове" визначення спадкового кодексу Майкла Пір'я (тобто "Кодекс без тестів")?
Phill W.

Це визначення для мене не працює :) Для мене будь-який код, який працює у виробництві і який може бути змінений - це застарілий код, незалежно від коду чи якості тесту. Зазвичай ми пов'язуємо "застарілий код" з "поганим кодом" або "застарілим кодом", коли насправді поганий код і застарілий код вже присутній в коді, який розробляється, і ще не бачив виробничого використання. Наша мета повинна полягати в тому, щоб наш код був спадщиною з початку роботи та був такою якістю та корисністю, що залишається у використанні протягом багатьох років, десятиліть.
luis.espinal

6

Я почав займатися TDD на початку серпня 2009 року і переконав всю свою компанію перейти на це у вересні / жовтні 2009 року. В даний час вся команда розробників повністю перетворена, і вчинення неперевіреного коду до репо вважається поганою річчю і на нього накидається. Для нас це чудово працює, і я не уявляю, як повернутися до ковбойського кодування.

Однак є дві проблеми, які досить помітні.

Набір тестів повинен підтримуватися

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

Час від часу тестування абстракцій протікає

Ми використовуємо Django, який має досить чудові рамки тестування. Однак іноді це робить припущення, які трохи не врізаються з реальністю. Наприклад, деякі проміжні програми можуть зламати тести. Або деякі тести роблять припущення щодо резервного кешування. Крім того, якщо ви використовуєте "справжній" db (не SQLite3), то підготовка db до тестів займе багато часу. Звичайно, ви можете (і повинні) використовувати SQLite3 та db в пам'яті для тестів, які ви робите локально, але якийсь код просто поводитиметься по-різному в залежності від бази даних, яку ви використовуєте. Налаштування сервера безперервної інтеграції, який працює в реалістичній установці, є обов'язковим.

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

Це все сказано, проблеми, які я описав, починають помітні лише тоді, коли ви досить розвинуті з TDD ... Коли ви тільки починаєте з TDD (або працюєте над меншими проектами), рефакторинг тестів не буде проблемою.


3
+1. "Доводиться підтримувати": це набагато менше проблем при тестуванні коду для багаторазового використання, оскільки його інтерфейс і поведінка зазвичай повинні бути стабільними. З цієї причини я зазвичай роблю лише TDD для нашої бібліотеки для багаторазового використання.
Димитрій К.

4

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

Можливо, це тільки я. Але я також десь читав, що автомобілі з усіма видами дзвіночків безпеки, як правило, врізаються більше (адже водії знають, що функції безпеки є), тож, можливо, це щось слід визнати; TDD може бути несумісним з деякими людьми.


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

1
Це просто показує, що різні люди дійсно по-різному реагують. Я не б'є TDD - очевидно, дуже багато людей вважають це корисним - але факт полягає в тому, що це не для всіх.
Joonas Pulakka

2
Я згоден на 100%. Я пишу код краще і швидше без автоматизованих тестів. Звичайно, було б абсурдно не тестувати, я просто думаю, що автоматизація - це поганий вибір (принаймні для мене). Я вважаю, що ручне тестування є і швидшим, ніж підтримка тестового набору, і більш безпечним, але я також досвідчений розробник, тому я дуже добре знаю, що тестувати і де і чому, тому мої доповнення до коду та повторні фактори регресія.
Бен Лі

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

Ви виходите з кроку рефакторингу?
rjnilsson

2

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

Мій підхід зазвичай:

  1. Реалізуйте щось, що працює (доказ концепції).
  2. Якщо це працює, консолідуйтесь, додаючи тести, вдосконалюючи дизайн, рефакторинг.

Іноді я не дістаюсь до кроку 2.

У цьому випадку використання TDD виявилося для мене більше недоліків, ніж переваг:

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

Отже, коли мені доводиться вивчати нові ідеї, я не використовую TDD і впроваджую тільки тести одиниць, коли відчуваю, що новий код десь потрапляє.


1
Це здається, що ви плутаєте код прототипу з корисним кодом. Код прототипу - код тесту . Це не потрібно тестувати, і ви не повинні створювати тести, які працюють проти нього. Крок, який вам не вистачає, становить від 1 до 2: ви говорите "консолідуйтесь, написавши тести". Проблема в тому, що ти не маєш чого консолідувати, а щось написати. Плануйте переписувати код прототипу, не плануйте його повторно використовувати. Його повторне використання залишає багато місця для компромісів. Переписування формалізує розподіл між фазою розвідки та фазою "коду якості".
utnapistim

3
@utnapistim: Я не плутаю код прототипу з корисним кодом, скоріше, TDD-завзятці плутають їх і пропонують також використовувати TDD для коду прототипу. А точніше, вони припускають, що коду прототипу взагалі немає. Також я погоджуюся з вами, що часто вам доводиться переписувати, коли ви переходите від прототипу до реальної реалізації. Іноді ви можете повторно використовувати частини прототипу коду, але ви повинні бути готові до перезапису. Ви дійсно повинні вирішувати від конкретного випадку.
Джорджіо

3
@utnapistim: Дивіться також відповідь luis.espinal: "Найбільший недолік, який я бачив, - це не сам TDD, а практикуючі. Вони застосовують догматичний і ревний підхід, де все повинно бути перевірене".
Джорджо

1

Недоліки або витрати на TDD

Примітка. Існує цілий ряд різних видів TDD. Незалежно від одиниці, BDD, ATDD або інших варіантів багато труднощів залишаються

Побічні ефекти

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

  • Глузування: забудьте затвердити порядок дзвінків
  • Знущання: макет не відповідає реальному дзвінку чи відповіді
  • Закріплення: тест покладається на нереалістичні дані, маскуючи інші проблеми
  • Кріплення: перевірити неможливий стан у виробництві
  • Функціональний: помилкові розриви збірки через те, що залежна система тимчасово недоступна
  • Функціональний: швидкість тесту дуже повільна

Вам доведеться змінити підхід до кодування, для деяких це буде кардинальна зміна.

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

Потрібен час, щоб зрозуміти, що вам важливо щодо тестування, а що - для тестування.

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

Специфічний випробувальний пристрій: великі рефактори

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


0

Моя аналогія - бар'єри на трасі Scalextric. Якщо надіти їх, ви станете набагато менш обережними.

Люди також отримують трохи місця для кадетів щодо своїх тестів - оскільки вони працюють добре, вони вважають, що код повністю перевірений, тоді як це лише початок процесу тестування.

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


-1

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


1
Якщо ви самі не розумієте свій власний код, то як жменька мільярдів можливих тестів може захистити від неправильного коду?
Майкл Шоу

2
Тому що ти зрозумів це, коли написав це, але забув про нього по дорозі?
Йоган

+1 TDD не захищає від розробника, який неправильно зрозумів вимогу бізнесу. Ось де заходить BDD ...
Роббі Ді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.