TDD, нові тести, поки старі ще не впроваджені


13

Я експериментую з тестовою розробкою, і я виявив, що часто стикаюся з такою ситуацією:

  1. Я пишу тести на деяку функціональність X. Ці тести виходять з ладу.
  2. Намагаючись реалізувати X, я бачу, що мені потрібно реалізувати деяку функцію Y у нижньому шарі свого коду. Так...
  3. Я пишу тести на Y. Зараз обидва тести на X і Y провалюються.

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

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

Що мені робити в таких випадках? Чи має TDD якісь рекомендації?

Відповіді:


9

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


Мої тести, як правило, не мають знань про те, що повинен робити метод внутрішньо (наприклад, який API нижчого рівня викликати). Чи варто просто налаштувати тести, щоб знущатися над усім, що мені потрібно в тестованому коді?
liori

2
Аналогічно, ваші тестовані класи не повинні дбати про те, що роблять "нижчі шари". Використовуйте макети / заглушки замість фактичних класів / об’єктів. Це може зажадати трохи більше зусиль у розробці, але приводить до коду, який менш сполучений і простіше використовувати повторно.
Mchl

1
Ви використовуєте ін'єкцію залежності? Ось так можна легко відокремити проблеми нижчого рівня від класів вищого рівня. У вашому тестовому класі є конструктор з параметрами його залежностей (як інтерфейси) у вашому тесті ви створюєте макети для інтерфейсів. В основному ви робите вигляд, що вже впровадили послуги нижчого рівня.
Майкл Браун

@Mike Brown, так, я. Я знаю, що можу створювати знущаються об’єкти. Але потім у своєму тесті на особливості Xя повинен знати, яку частину залежностей Xмені потрібно знущатися. Я вважаю, що це частина деталей щодо впровадження, яка не повинна бути частиною тестів - інакше мені може знадобитися змінити тести під час рефакторингу реалізації. Чи варто переживати з цього приводу?
liori

1
Зовсім не ... тести повинні відображати припущення тестуваної системи. Це також допомагає виявити, що вам потрібно від послуг, на які покладається система. Раніше я погоджувався з вами з цього приводу, але я порівнюю це з тим, як я зрозумів рекурсивне програмування. Спочатку ви пишете код, припускаючи, що у вас є функція, яка виконує те, що ви хочете. Потім ви пишете код, який робить те, що ви хочете.
Майкл Браун

4

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

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

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

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


Так, я шукав функцію, щоб вимкнути тест під час пробного запуску в моєму IDE, і не знайшов його. Тепер я виявив, що пітон unittestвже має тестові пропуски. Цього мені може бути достатньо.
liori

Ми використовуємо тест C ++ google test - і він має можливість відключити тести. Тести з обмеженими можливостями не виконуються, а компілюються - у той момент, коли вони вам знадобляться - вони готові до запуску (крім того, ви можете «примусово виконувати» тести з обмеженими можливостями - вид «включення часу виконання») - відмінна функція ...
ratkok

3

Стій

Це здається, що тут можуть бути два окремих питання:

  1. ви забули деякі історії та тестові сценарії та не відкрили їх, поки не почали працювати над певним тестовим сценарієм та / або

  2. ви фактично проводите тестування одиниць, а не тестування функцій TDD

Для №1 зупиніться , поверніться та оновіть історії та тестові сценарії, а потім почніть із іншого сценарію.

Для №2 зупиніться і пам’ятайте, що ви тестуєте функції, а не одиниці, тому використовуйте макети, щоб промальовувати інші інтерфейси та / або впроваджувати більше коду, щоб зробити тестовий пропуск без додавання нових тестових сценаріїв. Це передбачає, що ви не пропускаєте тестові сценарії, але натомість - і це дійсно часто - поєднуючи тестування модулів та TDD.


Мені дуже подобається ваша відповідь, вона краще справляє пояснення, що насправді відбувається.
maple_shaft

... З урахуванням того, що я не знаю прем'єр-міністра у світі, який не втратить розуму повністю на фразу: "СТОП, нам потрібно відмовитися". Вони намагатимуться всього, що не принесе в жертву своїх перших народжених біля вівтаря, щоб проект рухався вперед, технічна заборгованість і незавершені одиничні випробування були прокляті. Я думаю, ви не можете звинувачувати їх, коли єдиний показник в організації виконує проект вчасно. Деякі орґіни просто цінують час над якістю, і саме тому я, мабуть, ніколи не бачив, щоб TDD успішно працював у таких типах організацій, що, на жаль, НАЙБІЛЬШЕ з них IMO.
maple_shaft

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

0

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

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

Прототип

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

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

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


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

Чому ви вважаєте, що прототипування - це неофіційний процес? Кожна оцінка повинна враховувати складання прототипів, а розклади проектів повинні враховувати її, а також необхідну розробку. Я бачу це так само, як Design або Code-Review. З цього приводу він формалізований і його слід враховувати, навіть більше, якщо це стосується завдань з великою кількістю невідомих. Без прототипування та можливості виконувати програму Proof-of-Concept, тоді переслідуючи TDD, просто передбачається, що розробники знають ВСЕ ПРО ВСЕ ЩЕ з ВСІМ функціями. Реальний світ не працює таким чином, і мені байдуже, наскільки ви розумні чи досвідчені.
maple_shaft

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

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

1
TDD має ідеальний сенс для прототипування. Це дозволяє швидко викрити речі, якими ви є (об’єкт, функція, API, вся програма) у вигляді повторюваного виконуваного набору вимог. Зробіть собі послугу і прочитайте Зростаюче об’єктно-орієнтоване програмне забезпечення, кероване тестами ; це веде вас крок за кроком шляхом складання цілої програми (включаючи інтеграцію) тестовим способом.
Френк Ширар

0

Це залежить від того, які тести ви пишете, роблячи TDD.

Класична модель полягає в написанні одиничних тестів і використанні макетів або заглушок для від'єднання тесту від інших "одиниць" коду.

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

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