Що розуміється під "одиницею" під час одиничного тестування


9

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

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

Відповіді:


11

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

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

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

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

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

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

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

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

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


10

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

Ви називаєте це тендітним. Я думаю, що це неправильно. Неміцні тести - це те, що відбувається при найменшій зміні коду, що не пов'язаний. Тобто ті, які покладаються на код, який не має відношення до функцій, які тестуються.

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

Це саме проблема, яку має вирішити поведінка, орієнтована на поведінку , а саме розвиток , орієнтований на прийняття-тест . Але це не знімає потреби в одиничних тестах / тестових розробках; це лише доповнює його.


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

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

під станом я маю на увазі тест, який перевіряє стан, результат якоїсь функції; Під поведінкою я маю на увазі тест, який підтверджує не результат, а те, що якусь функцію викликали
SiberianGuy

@Idsa: У цьому випадку я повністю не згоден. Те, що ви називаєте тестом стану, я називаю інтеграцією. Те, що ви викликаєте поведінку, я називаю одиницею. Інтеграційні тести за власним визначенням є більш крихкими. Google "тестовий блок інтеграції крихкий", і ви побачите, що я не один.
пдр

є журнал статей про тестування, але які з них поділяють вашу думку?
SiberianGuy

2

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

При одиничному тестуванні метод повинен бути перевірений ізольовано, тобто шляхом заглушення / глузування / підробки будь-яких залежностей. В іншому випадку тестування блоку на "реальні" залежності робить його інтеграційним тестом. Для обох типів тестів є час і місце. Експертні тести забезпечують, що окремий предмет працює, як очікувалося, окремо. Інтеграційні тести забезпечують коректну співпрацю «реальних» суб'єктів.


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

1

Моє правило: Найменша одиниця коду, яка все ще є досить складною, щоб містити помилки.

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

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

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

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

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