Чи повинен кожний тест одиниці можна проводити незалежно від інших тестів?


24

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

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

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

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

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


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

Відповіді:


11

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

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

а) Працюйте правильно, якщо вони представлені з дійсними даними.

b) Збиток розумно та послідовно, коли вони представлені недійсними даними.

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

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


27

Якщо тести не можуть виконуватися самостійно, вони не є одиничними тестами.

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

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


@Steve, тому в цьому прикладі ви б сказали: один тест для методу 1, один тест для методу 2 і один тест, який виконує 1 і 2 в одному тесті?
Морган Херлокер

2
Так. перші два будуть одиничними тестами, третій звучить як тест на інтеграцію.
Стів

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

@Dainius. У сценарії тестування одиниць ви зазвичай використовуєте макетні об’єкти, тож ви передасте клієнту-макету модуль замовлення. Ви маєте рацію в тому, що не хотіли б використовувати sql в цьому випадку.
Стів

видається, що в будь-якому сценарії, де метод B залежить від методу A, майже завжди буде метод C, який викликає A, а потім викликає B. Оскільки це так, ви могли б протестувати A, B і C незалежно.
Морган Херлокер

9

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

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


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

3

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

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

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