Як ви протестуєте функцію, єдиною метою якої є запит на зовнішній API, але API використовує складний синтаксис запитів?


16

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

function retrieve_related_data(id)
{
  query = "[potentially long, syntactically complex query that
            uses param id to get some data]";
  results = api_wrapper.query(query);
  return results;
}

Більш конкретний приклад зі складеним API:

function retrieveLifeSupportingObjectsWithinRegion(id)
{
  query = "
    within region(" + id + ") as r
    find objects matching hydration>0 and temp_range has 75
    send name, id, relative(position, r)        
  ";
  results = astronomicalObjectApiWrapper.query(query);
  return results;
}

The query is in a syntax custom to the API and is complex and there are multiple ways to achieve the same or similar results. The purpose of the function is not to get data identified by id but to find a subset of other data based on a fuzzy relationship to the data identified by id that also meets a few other requirements. The other requirements are always the same regardless of id but may change over time as the system is modified. For example, if the example api added support for gravity information, we may want to change the query to also use gravity to refine the results. Or maybe we come up with a more efficient way to check the temp range, but it doesn't change the results.

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

Варіанти, які я розглядав:

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

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

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

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


Я думав про це як одиничне тестування, але, можливо, це справді інтеграційний тест або тест прийняття низького рівня?
Джошуа Коуді

2
Це API лише для читання? Або ви можете записати дані, на яких можна надійно перевірити свої прочитані ?
svidgen

Чи відрізняється це запитання від "як перевірити, що мій sql (= складний синтаксис) повертає точні дані"? З базами даних у вас зазвичай є кілька тестів на інтеграцію, які перевіряють синтаксис crud-sql та знущається сховище, щоб перевірити businesslogic
k3b

Відповіді:


7

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

Наші тести повинні бути вирішені, щоб гарантувати очікувану поведінку написаного нами коду, а не того, який він написав треті сторони.

Певною мірою ми маємо довіряти правильній функції API та ліб, на які ми покладаємось. Наприклад, ми зазвичай не тестуємо компоненти рамки, які ми реалізуємо.

Чому я так кажу?

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

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

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

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

Що робити, якщо запит у порядку, але дані неправильні через помилки в API? Не тільки дані не в нашому контролі. Логіка теж.

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

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

Я пропоную застосувати інструмент для такої мети. Це може бути так само просто, як:

  • Клас, який працює як тест, але він не належить до плану тестування
  • Скрипт оболонки + завиток

Або щось більш витончене. Наприклад, окремий клієнт.

У будь-якому випадку, функція, про яку йдеться, цілком вартує двох видів тестів:

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

  • Інтеграційний тест. Переконайтеся, що код не тільки надсилає правильний запит, але чи правильно він обробляє вміст відповідей, помилки, переадресації тощо. Робіть тести для всіх цих випадків, але не перевіряйте дані .

Побічна примітка: Ваше запитання схоже на -Як ви перевіряєте SQL заяви програми?

Пов’язані запитання :


1: Вас може зацікавити відповідь @ DocBrown щодо цієї теми


"Проблема (IMO) полягає в тому, що ви занадто зосереджені на тестуванні зовнішнього API." - Я не бачу нічого, що свідчить про те, що запитувач взагалі зацікавлений у тестуванні зовнішнього API. Крім того, ви говорите "заглушити зовнішній API", але чи є у вас якісь пропозиції щодо того, чи повинен користувач, що використовує запит, використовувати "занадто простий" варіант, "занадто крихкий" варіант, "занадто складний" варіант чи якийсь четвертий варіант?
Таннер Світт

ОП питання - це питання тестування функції, яка викликає зовнішній API. Але читаючи його сумніви, мені здається, що він надто багато акцентує на тестуванні запиту та його результатів. Я зробив 4 пропозиції: (1) не робіть тестування API. (2) не використовуйте тести інтеграції як робочий стіл для налаштування запиту. Зробіть замість цього інструмент. (3) повернемося до головного питання, зробіть його унітарний та інтеграційний тест. Але не підтверджує вміст відповіді API. (4) Запитайте менеджера проекту, чи повинні вони / можуть скласти тестовий набір зовнішнього API як частина тестового плану проекту.
Лаїв

1
Я розглядаю сам запит як "написаний нами код". Кінцева мета - це автоматизоване тестування, щоб повідомити нас, якщо ми ввели помилку в свій код. Зважаючи на те, що ви сказали про SQL-висловлювання, я думаю, це схоже на це - я думаю, моє запитання таке, як ви перевіряєте, що ваш код запитує зовнішній API таким чином, що API відповість за призначенням (припустимо, що номінальна відповідь). Я думаю, що ви говорите - це не робити тесту для блоку та інтеграції, але якщо запити є критично важливими, ми можемо встановити деякі інші автоматизовані тести окремо для тестування живих зовнішніх програм.
Джошуа Коді

1
ІМО, найкращий спосіб - це зробити функціональний тест, зміна пункту де, яке ніколи не буде істинним, спричинить іншу поведінку в одному або декількох моїх функціональних тестах. УТ - лише невеликий шматочок у плані тестування.
Лаїв

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

2

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

Однак. На мою думку, це було обмеженим використанням. Синтаксис запитів був складним, можливо, помилковим, тому A було нескінченна можливість перевірити, а B навіть у тому випадку, якщо рядок 'правильно' генеровано, несподівані результати можуть бути повернуті в прямому середовищі.

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

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

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


0

Це залежить від API, але якщо можливо, перейдіть до опції №3 (приватний тестовий екземпляр).

Забивання API (варіант №1) - найгірший варіант, з-за вказаних вами причин, і проходження цього маршруту, ймовірно, принесе більше шкоди, ніж користі (багато витраченого часу).

Працюючи з реальним API (варіант №2) робить тести невмілими та ненадійними, і після кількох помилкових позитивних результатів люди просто перестануть їх використовувати. Дані не тільки можуть змінюватись, але і сервіс може бути знижений. На мою думку, це схоже на відсутність тестів на запити, а для пошуку проблем покладаються на інтеграційні / системні тести. Однак, якщо дані API рідко змінюються, а сам API майже завжди працює, то це може бути життєздатним варіантом. Більшість API не відповідають цьому опису.

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


Отже, ви в основному говорите про те, що одиничні тести (№1) та інтеграційні тести (№2) шкідливі? Хоча номер 3 може здатися найкращим серед них, він може бути і найдорожчим. Його потрібно підтримувати щоразу, коли API змінюється. Без №2 ви не будете в курсі можливих змін помилок у реальному API, поки ваша програма не з’явиться у виробництві (занадто пізно для вжиття заходів). Гаразд, №1 здається непотрібним, тому що для тестування немає рядків коду ... сьогодні ... Завтра, як відомо ...
Laiv

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

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