Чи корисно мати окремі методи тестування для кожного кроку?


10

Я тестую REST api. Скажімо, він повертає структуру JSON. Який найкращий підхід до тестування сервера? Кожен крок випробування може досягти успіху, лише якщо всі попередні були успішними.

Структура A: перевірити все одразу

- Test method 1:
    - make server request
    - assert http response code was 200
    - assert returned file is not empty
    - assert returned file has valid JSON syntax
    - assert returned JSON contains key X

Це, здається, найкраще рішення.

Переваги:

  • Лише один запит сервера
  • Я тестую поведінку в цілому "Чи повертає сервер JSON з ключем X?"

Структура В: поступово додайте твердження до кожного тесту

 - Test method 1:
     - make server request
     - assert http response code was 200
 - Test method 2:
     - make server request
     - assert returned file is not empty
 - Test method 3:
     - make server request
     - assert returned file has valid JSON syntax
 - Test method 4:
     - make server request
     - assert returned JSON contains key X

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

Структура C: зробіть запит один раз і запустіть окремі методи тестування на кешовану відповідь

- make server request and cache it (allow read-only access)

 - Test method 1:
     - assert http response code was 200 on cached server request
 - Test method 2:
     - assert returned file is not empty on cached server request
 - Test method 3:
     - assert returned file has valid JSON syntax on cached server request
 - Test method 4:
     - assert returned JSON contains key X on cached server request

Переваги:

  • Немає повторного (дорогого) запиту сервера
  • Ще є односпроможні методи тестування

Яка найбільш розумна структура тесту для використання?


Будь ласка, перестаньте потім змінювати своє запитання таким чином, що визнає недійсними відповіді! Дякую.
Док Браун

Вибачте за те, що заподіяли вам незручності, але ви б запропонували зробити інакше?
mrplow

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

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

Відповіді:


3

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

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

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

Отже, вам потрібно запитати себе - "чи мені справді тут потрібна ця гарантія?"

Скажімо, у першому тестовому випадку є помилка - код відповіді HTTP не є 200. Отже, ви почнете зламати код, з’ясуйте, чому ви не отримали код відповіді, який у вас був, і вирішіть проблему. А тепер що?

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

Є ще кілька речей, які слід врахувати:

Затвердження залежності

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

Якщо у вас є служба REST (або будь-який інший протокол HTTP), який повертає відповіді у форматі JSON, ви зазвичай пишете простий клас клієнта, який дозволяє використовувати методи REST, як звичайні методи, що повертають звичайні об'єкти. Якщо припустити, що клієнт має окремі тести, щоб переконатися, що він працює, я б дістав перші 3 твердження і зберег би лише 4!

Чому?

  • Перше твердження є зайвим - клас клієнта повинен викинути виняток, якщо код відповіді HTTP не 200.
  • Друге твердження є зайвим - якщо відповідь порожня, об’єкт результату буде нульовим або якесь інше представлення порожнього об'єкта, і вам не доведеться ніде класти ключ X.
  • Третє твердження є зайвим - якщо JSON недійсний, ви отримаєте виняток, коли спробуєте його розібрати.

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

Як ви хочете отримувати звіти?

Скажімо, ви не отримуєте електронні листи від тестового сервера, але натомість відділ QA запускає тести та повідомляє про невдалі тести.

Джек від QA стукає у ваші двері. Він каже, що перший метод тестування виявився невдалим, а метод REST повернув поганий код відповіді. Ви дякуєте йому і починаєте шукати першопричину.

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

Ви повертаєтесь до роботи, але потім приїжджає Джим із QA, кажучи, що четвертий метод тестування не вдався і у відповіді немає ключа X ...

Ви навіть не можете шукати причину, тому що важко дивитися на код, коли у вас немає екрана комп'ютера. Якби Джим був досить швидким, він міг би уникнути часу ...

Електронні листи з тестового сервера простіше відхилити, але все-таки - чи не варто було б вам просто повідомити НАДЕ, що з методом тестування щось не так, і самостійно подивитися відповідні журнали тесту?


3

Якщо можна сміливо припускати, що запит сервера з однаковими параметрами буде вести себе завжди однаково, метод B майже безглуздий - навіщо вам чотири рази викликати один і той же метод, щоб отримати однакові дані відповіді чотири рази, коли одного дзвінка достатньо?

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

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

Здається, альтернатива C поєднує A з тією перевагою, яку я згадав вище для B. Якщо ваша тестувальна рамка дозволяє легко структурувати ваш код, без великих витрат над B, це підхідний підхід. Однак це додає A додаткової складності, тому я би використовував його лише в тому випадку, коли мені хочеться вмикати та вимикати окремі тести, інакше застосувати принцип YAGNI та дотримуватися найпростішого рішення (A).

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


0

Як і будь-який код, уникайте передчасної оптимізації. Спочатку напишіть свої тести, щоб вони були простими для читання та простими в обслуговуванні. Коли тести починають надто повільно, тоді оптимізуйте їх. У вашому досить простому прикладі і A, і B буде легко читати і підтримувати, тому вибирайте будь-який, який вам захочеться, поки все не стане надто повільним (структура B) або занадто складним (структура A).

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

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


0

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


Пишучи будь-який код (а може, навіть створювати щось інше), завжди запитуйте себе: "чому існує така практика?"
Чому ми кажемо, що для всіх повинні бути різні тести?

Є два випадки, коли вам це потрібно:

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

Є дві причини, чому ви стикаєтеся з цими випадками:

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

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


В іншому випадку (я сподіваюся , що ви тут) ви вибираєте A .


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

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