Чи потрібно тестування, якщо я вже маю тест на інтеграцію?


47

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

Те, що я знаю, користь одиничного тесту над інтеграційним тестом

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

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


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

Це питання видається неоднозначним. Скажімо, у мене є метод контролера Rails, який викликає інтерактор ( github.com/collectiveidea/interactor ). Я вирішив написати інтеграційні тести для свого методу контролера (оскільки без них я не можу повірити, що моя кінцева точка API працює). Тут є щонайменше два питання: (1) чи слід також писати одиничні тести для моїх методів контролера (тобто, чи слід писати одиничні тести, які перевіряють те саме, що і мої інтеграційні тести), і (2) чи слід також писати одиничні тести? для мого інтерактора? Я б відповів на ці два питання по-різному в певних бізнес-контекстах.
Даніель

Відповіді:


33

Ви виклали хороші аргументи за і проти тестування одиниць. Таким чином , ви повинні запитати себе, « Я бачу цінність позитивних аргументів , які переважують витрати на негативних робити? » Я , звичайно , робити:

  • Невеликий і швидкий - хороший аспект тестування одиниць, хоча аж ніяк не найважливіший.
  • Виявлення помилок [s] -easier надзвичайно цінне. Багато досліджень професійної розробки програмного забезпечення показали, що вартість помилки стрімко зростає з віком і рухається вниз по лінії доставки програмного забезпечення.
  • Пошук-маски-помилки є цінним. Коли ви знаєте, що певний компонент перевіряє всю свою поведінку, ви можете з упевненістю використовувати його таким чином, який раніше не використовувався. Якщо єдине підтвердження проводиться за допомогою тестування інтеграції, ви знаєте лише, що його поточне використання поводиться правильно.
  • Знущання в реальних випадках затратні, а підтримка знущань удвічі більше. Насправді, під час знущання над "цікавими" об'єктами чи інтерфейсами вам можуть знадобитися навіть тести, які підтверджують, що ваші знущаються об'єкти правильно моделюють ваші реальні об'єкти!

У моїй книжці плюси переважують мінуси.


2
Чи не знущається з дешевших у реальних випадках? Ви налаштовуєте лише очікування щодо того, які повідомлення отримує макет, і вказуєте, що він буде повертати.
Dogweather

10
@Dogweather Mocks добре працює при першому створенні. Із плином часу і зміною реального об'єкта макети мають змінюватися разом з ним. 10 років і 6000 одиничних тестів у дорозі, дуже важко знати, що ваші "успішні" тести справді успішні.
Росс Паттерсон

1
На відміну від того, що "10 років і 6000 одиничних тестів" - це цифри з особистого досвіду, а не гіперболи.
Росс Паттерсон

3
Я почав писати автоматизовані тести для розробників (блок та інтеграція, але в основному останній) ще в 2004 або 2005 роках, і розробив розширену глузуючу бібліотеку для Java. Багато разів я бачив кілька тестів інтеграції ламати по тій же причині (наприклад , зміна в БД, або зміна мережі), і я іноді пишу «нижчого рівня» інтеграційні тести для повторно використовуваних компонентів, але все ж, я вважаю за краще тільки мати інтеграційні тести. Ізольовані одиничні тести з глузуванням здебільшого просто не варті; Я застосовую глузування лише як допомогу для інтеграційних тестів.
Rogério

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

8

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

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

> Then what are the reasons to write/add unit tests?

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

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

Якщо ви робите TDD, код автоматично перевіряється.


2
Якщо у мене є застаріле додаток, яке не існує unit-tests, і я хочу включити його unit-testsдля певних частин, чи вважаєте ви, що краще спершу виписати integration testsкод для спадщини. Після того, як це написано, тоді ви можете від'єднати тісну сполуку та створити функції з інтерфейсами, які можна перевірити? Оскільки ви integration-testвже написали, то можете на кожному етапі рефакторингу переконатися, що нова версія коду все ще працює за бажанням?
alpha_989

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

5

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


4

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

Також велика помилка, яку ви можете зробити, - це довіряти цьому

Find bug that may not be caught in integration test. e.g. masking/offsetting bugs.

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

Я думаю, що канонічне посилання на інтегровані тести - це повідомлення JBrains:

http://www.jbrains.ca/permalink/integrated-tests-are-a-scam-part-1

якщо ви їх ще не прочитали.

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


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

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

1

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

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


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