Чому спритний все стосується тестової розробки (TDD), а не тесту, орієнтованого на розробку (DDT)?


74

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

Ось як я уявляю TDD і чому мене це бентежить. Якби я будував будинок як підрядник TDD.

  1. Дайте мені всі ваші характеристики (історії).

  2. Отримайте схвалення щодо специфікацій.

  3. Розбийте всі характеристики на перевірку, я думаю, мені знадобиться (дивіться у майбутнє).

  4. Зателефонуйте інспектору, щоб подивитися на ці пункти і скажіть мені, що я закінчую перевірку (спасибі).

  5. Почніть будувати будинок.

  6. Щодня телефонуйте інспектору (проходить 2/100).

  7. О, стріляйте, виникла проблема з моїм розумінням, і тепер мені потрібно додати ще 9 перевірок і змінити 27 з них.

  8. Викличте інспектора, який проходить 1/109.

  9. Блін. Чому інспектор не любить цього ... о, я оновив ім'я цього методу ...

  10. Побудуйте ще кілька.

  11. UGGGGHHHH БІЛЬШІ ЗМІНИ дозвольте мені оновити проклятий інспектор. О, я не вживаю жодної ** t.

  12. Я вже закінчив?

Гаразд, це може бути чужим, але я просто не бачу, як я повинен знати всі свої методи і як все буде працювати, поки мій код не знайдеться. У 99% часу мені доводиться повертатися та оновлювати тест на будь-які способи та додавати більше, коли я йду. Це просто здається назад.

Те, що здається більш підходящим, - це тестування DDT або тестування на основі розробки, що, як видається, все, про що спільнота забула.

З мого розуміння DDT для будинку виглядав би так:

  1. Дайте мені всі ваші характеристики (історії).

  2. Отримайте схвалення щодо специфікацій та розбийте їх.

  3. Почніть одиницю (фундамент).

  4. Робіть замітки (коментарі) якоїсь хитрої логіки.

  5. Наприкінці перед початком наступного підрозділу проводять перевірку (створіть тест).

  6. Виправте будь-яку виявлену проблему та перевірте ще раз.

  7. Схвалено цей пристрій перейти до наступного.

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


60
Яскравий відключення для мене - це думка, що перед тим, як написати код, який починає їх проходити, ви можете пройти 100+ тестів, що не справляються. Як говорить @Telastyn, одночасно повинно бути не більше декількох провальних тестів. "Тести, а потім код - тест" не означає писати всі тести програми, перш ніж писати будь-який код.
Ерік Кінг

33
Метафори - антипатерн! Люди витрачатимуть більше часу на пояснення, чому ваша метафора не відповідає темі, а не на вирішення вашої реальної проблеми. У такому випадку, здається, ваша справжня стурбованість полягає в тому, що ви думаєте, що ви повинні написати всі тести наперед.
ЖакБ

21
В якості додаткового зауваження тут TDD зазвичай використовується в гнучких проектах, але я думаю, що важливо розрізняти спритний менеджмент проектів і спритний досвід розвитку. Не існує дуже міцних стосунків між ними. Ви можете використовувати найбільш гнучкі практики розробки незалежно від методології проекту та навпаки. Часто забувають, що спритний, в основі його, насправді полягає в адаптації вашого підходу до необхідності, щоб досягти найкращого результату, а не про перелік рецептів речей, які ви повинні робити. Іншими словами, Agile! = Scrum + TDD.
JimmyJames

35
Натомість, порівнювати розробку програмного забезпечення з будівництвом будинку безглуздо. Дослідження зроблено. Результати є. Відповідь зрозуміла. Ви просто не будуєте програмне забезпечення так само, як ви будуєте будинок. The. Два. Є. Інший.
riwalk

14
Agile - все про швидкі петлі зворотного зв'язку, TDD - лише один певний тип циклу зворотного зв'язку
jk.

Відповіді:


83

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

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

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

Тепер напишіть наступний тест, повторивши процес вище.

Це може здатися марним підходом на самому початку, коли очевидно, що має на увазі ваш код, але найкраще при такому підході - тест покриття завжди високий, а дизайн коду таким чином чистіший.

Як метод, він йде рука об руку з парним програмуванням; одна пара пише тест, наступна пише код, щоб він пройшов, потім пише наступний тест тощо.

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

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

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


46
Термін "Невідкладний дизайн" дає змогу розробити дизайн програмного забезпечення, пройшовши тести. Ви не можете.
Роберт Харві

28
@nerdlyist: Не забувайте про дизайн. Вам ще потрібно розробити програмне забезпечення; гарний дизайн не просто природно випливає з червоно-зеленого рефактора. TDD заохочує гарний дизайн, але він не створює його.
Роберт Харві

19
@RobertHarvey, я повністю не погоджуюся з вашим твердженням " Термін" Невідкладний дизайн "дає змогу розробити дизайн програмного забезпечення, пройшовши тести. Не можете ". Зробивши саме це кілька разів, можу запевнити, що це можна зробити.
Девід Арно

12
@DavidArno: Ви починаєте із специфікації вимог? Як ти переводиш цю специфікацію в розумну архітектуру? Чи ви винаходите її кожен раз за допомогою тестів, чи маєте на увазі попередні архітектурні принципи? Ніхто цього не робить у сліпих; взагалі немає нічого магічного в тому, щоб спершу писати свої тести, крім того, що це змушує вас зробити свій код більш перевіреним.
Роберт Харві

45
@DavidArno Я думаю, що ваше заперечення випливає з того, що ви не отримаєте достатньо кредиту як досвідченого розробника / архітектора. Оскільки ви вже знаєте, як виглядає модуль X інтуїтивно , ваші тести будуть рухати вашу розробку в хорошому напрямку. Недосвідчений розробник, який не має інтуїтивного поняття про те, як повинен виглядати модуль, перш ніж писати тести, створить добре перевірений, хитрий модуль.
svidgen

86

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

Розбийте всі характеристики на перевірку, я думаю, мені знадобиться (дивіться у майбутнє).

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

Щодня телефонуйте інспектору (проходить 2/100).

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

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

Здається, зміни можна вносити швидше і без накладних TDD, здається, створюються.

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

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

Мої професори в коледжі були в курсі ідеї Тести, а потім Код і Тест.

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


18
+1 лише за останній абзац. Приклади ваших будинків дійсно підкреслюють, наскільки дурним може бути "релігійний ТДД".
Роберт Харві

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

1
@TrevorBoydSmith ти б не писав документацію в той момент, не вимоги.
nerdlyist

8
Оскільки TDD ставить перспективу користувача коду, [у кращому випадку] він сприяє кращим інтерфейсам. Наприклад, коли я дзвоню, open_doorя не повинен був би передавати прапор toilet_flushed; тому я не пишу свій тест таким чином, і тому мій код не має цих "грубих країв". Код, написаний повністю без належного врахування того, як його називають, часто має дивні інтерфейси або припущення / передумови.
brian_o

3
@TrevorBoydSmith, щоб поставити ім'я, я чув, що називається "Спайк і стабілізувати", і так, це зручна техніка, коли ви дізнаєтесь, як зробити те, що ви ще не знаєте, як робити.
RubberDuck

13

Подібність між побудовою фізичної речі та написанням програмного забезпечення досить мінімальна.

Однак це є одна важлива відмінність:

Існує різниця між "автором тесту" та "виконанням тесту".

У прикладі будівництва будинку, вимога і випробування дійсно передують фізичний Buildout. А частини тестового набору виконуються постійно - навіть декількома агентами! Коли будівельник забирає 2x4, він негайно і автоматично "перевіряє" пристрій на його поняття "як виглядає звук 2x4". Він не вимагає авторських вимог після того, як він підніме його; він проводить попередні перевірки на це.

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

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

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

І це нормально. Не все має передувати суворим випробуванням.

тл; д-р

Незважаючи на те, що конструкція! = Програмне забезпечення для написання: Будівництво працює в тестовому порядку. У «роз'їзд» умови для кожної одиниці роблять передують їх Buildout.

Не пов'язуйте "виконання тестів" з "написанням тестів".

Не все має бути TDD.


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

@nerdlyist Певним чином, так. Але якщо ваші тести перевіряють "правильні" речі, ви хочете "перешкоди" .
svidgen

4
Повернення до аналогії будинку: якщо ваш клієнт раптом захоче поміняти двері іншим стилем, і у нього немає однакових розмірів, вимоги щодо розмірів дверей та відкривання зміниться, і робота вимагає змінити ці "тести" "повинен відображати роботу, необхідну для зміни впровадження. Але, існує багато тестів, які не зміняться: дверцята повинні відкриватися та закриватися, замикатися і бути P% повітронепроникними в отворі, коли вони закриваються, і т. Д. ... Багато тестів, які не змінюють "заваду" фізичні зміни відповідно .
svidgen

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

1
@nerdlyist Інтеграційні та регресійні тести також можна зробити тестовими спочатку. Це не зовсім відповідає циклу розвитку «догматиків TDD», але результат майже однаковий: ви закінчуєте тестований код, з мінімальним стороннім кодом, і тести, які фактично підтверджують те, на що вони претендують. Тестування після написання коду може зробити виконання будь-яких або всіх цих речей трохи складніше. Зовсім не неможливо, але потенційно складніше.
svidgen

11

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

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

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

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


1
Я бачу, ви тоді мали справу з контролем будівництва ... :)
Жюль

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

2
@Giorgio - великі переписування трапляються, тому що поодинокі рішення відображаються у багатьох місцях коду. Коли рішення змінюється, то код змінюється в багатьох місцях. Постійний рефакторинг пом'якшує цю проблему, видаляючи дублювання та обмежуючи кількість коду, що відображає одне рішення. Хороше тестове покриття підтримує постійне рефакторинг.
Кевін Клайн

7

Перше і головне, авансова вартість не настільки висока, як ви думаєте . Так, ви витрачаєте більше часу на тестування, ніж якщо ви не робите тестування. Але якщо ви робите метод "тестування після", що ви насправді витрачаєте? Скажімо, TDD займає 10 годин, а DDT - 6 годин. Ваші "додаткові" авансові витрати - лише 4 години. Тепер, якщо ви застосуєте метрику коду або вимогу, наприклад 90% покриття, то ваші TDD та DDT ще більше зближуються за витратами.

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

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

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

var foo = function(in) {
    if(in == 0) {
      return true
    }
}

Тепер у вашій програмі ви телефонуєте if(foo()){ doStuff() }Що відбувається, коли я виправляю foo?

var foo = function(in) {
    if(in === 0) {
      return true
    }
}

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

Я просто не бачу, як я повинен знати всі свої методи і як все буде працювати, поки мій код не знайдеться.

Ну, не варто. Ви повинні написати тест, який перевіряє, що якась одиниця роботи виконана. Якщо ви відчуваєте, що ви тестуєте речі, про які ви, можливо, не можете знати, то ви думаєте, що занадто великі, АБО тестування занадто мало.

Наприклад, потрібно знати, що двері закриваються та замикаються. Я б перевірив door.close () і door.lock (), і що door.open () повертає false, коли двері заблоковані. Це все. Якщо ваші тести door.lock () встановлює прапор у базі даних. Тоді ви тестуєте занадто мало. Тест не повинен знати, як працює door.lock (), саме це і робиться.

Тепер, якщо ви пишете тест, який говорить, що house.isSecure () повертає значення true, коли всі двері та вікна заблоковані. Не дивлячись спочатку на двері чи вікна, тоді ви занадто великі.

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

По суті, ваше розуміння (перелік) того, як має працювати TDD, вимкнено. Ніколи не повинно проходити 2/100 проходження. Ви повинні мати 1/1 проходження, потім 2/2 проходження, потім 3/3 проходження, потім 4/4 проходження тощо.

Перероблений список для вас

  1. Отримати всі технічні характеристики
  2. Виберіть одну специфікацію
  3. Перевірте це
  4. Зашифруйте це
  5. Перевірте це
  6. Якщо пройдете тести, перейдіть до 7, перейдіть до 4
  7. Якщо ви виконали всі характеристики, перейдіть до 8, перейдіть до 2
  8. Перегляньте технічні характеристики зі споживачем та додайте нові технічні характеристики, де потрібно. Якщо все зроблено правильно, вам взагалі не доведеться міняти тести. Просто додайте нові. Іноді збір вимог може розвалитися, і вам доведеться додавати тести, що суперечать попереднім тестам, але вам рідко доведеться міняти тести.

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

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

Що тут вискакує на мене, це те, що важливо відзначити, що коли ви пишете одиничний тест в TDD, ви не пишете тест на частину клієнтської функціональної специфікації, ви пишете тест на поведінку одиниця, як ви - програміст - визначила це у вашому мозку, тобто "цей клас повинен викликати подію, коли трапляється X, давайте написати тест на це". Це невиразне "ваші тести - ваша специфікація!" риторика чудова, коли ви вже отримуєте TDD, але хтось із циклу викликає більше запитань, ніж відповідає.
Мураха P

4

Є деякі ключі, на які я вважаю, що інших відповідей бракує.

Три переваги

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

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

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

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

Аналіз витрат

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

Аналогія з будинком - це збірка будинку проти компілятора програмного забезпечення.

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

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

За винятком ...

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


1
Чудовий момент у перевірці тесту! Також: будуючи будинок, ТРУДНО переміщати стіну (а це залишає шрами). За допомогою програмного забезпечення переміщення коду відносно просто - за умови автоматизованого тестування, щоб виявити будь-які непередбачувані зміни.
Технофіл

4

Раніше я багато цікавився з цього приводу, поки не зробив декілька проектів TDD. Є дуже лаконічне і всебічне пояснення, яке з’явилося мені, коли я це робив:

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

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

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

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


4

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

Коли ви пишете щось нове, те, чого ви ніколи раніше не робили, немає суттєвої різниці між TDD і не робити TDD.

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

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

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


2

Чому спритний все стосується тестової розробки (TDD), а не тесту, орієнтованого на розробку (DDT)?

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

https://en.wikipedia.org/wiki/Agile_software_development#Agile_methods перелічує багато десятків і більше різних моделей розробки.

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

Тож моя відповідь:

  • "DDT" (також написання тестів після або "на вершині" впровадження) не працює з реальних причин; як тільки ви отримуєте тиск часу або грошей, тести виходять з вікна; і просто тести на користь проведення тестів - це швидше мене, все одно, ІМО.
  • Agile - це не все про тестову розробку (TDD), якщо ви інтерпретуєте цей термін як в основному означає "одиничні тести для всіх будівельних блоків / класів" (що, принаймні, згідно Вікіпедії). TDD - це лише одна можливість зробити спритний розвиток.
  • Існують й інші методи, такі як BDD або FDD, які роблять підхід із повним стеком. Ви все ще пишете свої сценарії наперед, у вас все ще є цикл червоно-зеленого рефактора, і ви все ще реалізовуєте лише до тих пір, поки ваші сценарії не стануть зеленими, але ваші "тести" за визначенням вправляють усе програмне забезпечення (діючи як взаємодія з користувачем) і ніколи лише одна одиниця.

Я вважаю за краще застосувати програму з повним покриттям BDD / FDD і без тестових одиниць, ніж тестування з повним покриттям одиничних тестів і без тестів на повний стек.

(TDD має своє місце, звичайно, в API, але це не те, про що ми говоримо тут.)

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


Я знав про інше, але в той час, як написання цього ДДТ, здавалося, має більше сенсу. Слід подбати про те, чому TDD краще для API? Як би його використовувати, скажімо, веб-клієнт з MVC відрізнявся?
nerdlyist

1
Для API дуже важливо, щоб вони виконували дуже детальний контракт ; кожен виклик методу повинен вести себе дуже передбачувано, щоб користувачі (які є іншими програмами) правильно його використовувати. Тут справді світить одиничне тестування. OTOH, у додатку, це найважливіше для функцій, які потрібні вашим людям для роботи за призначенням. Звичайно, і ваші «внутрішні особи» краще бути правильними, але важливіше добре охопити функціональність «від кінця до кінця» (тобто, з інтерфейсу користувача прямо в БД і назад) замість тестування кожного окремого методу (який кінцеві користувачі люди все одно не побачать).
AnoE

Звичайно, тут все в різних ступенях - можливо, тут має сенс провести одиничні тести, якщо вам десь мають бути дуже складні методи / класи (наприклад: обчислення відстаней між геокоординатами); але основна частина (наприклад, у бізнес-додатках) - це загальний робочий процес.
AnoE

0

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

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

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

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

Якби вам довелося будувати серію мостів без наших попередніх століть архітектурних знань, зразків, регламентів та математики, які ми маємо довести, що наші мости працюватимуть, перш ніж ми будувати їх, ви, ймовірно, будете тестувати та перебудовувати мости ВЕЛИКОГО.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.