Як я можу написати тести проти сервісної послуги?


17

Я будую службу на основі даних Google Store Engine Datastore, яка з часом є послідовною сховищем даних. Для моєї заявки це добре.

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

Як ви протестуєте послугу з часом?


2
Чому ви протестуєте, спочатку очікуючи на відтворюваність відносно зовнішньої служби?

... а що ви насправді намагаєтесь перевірити? Ваш код? чи Google?

5
Я тестую всю систему. Тобто це інтеграційні тести, а не одиничні тести.
Дуг Річардсон,

3
How can I reproducibly test an eventually consistent service? - Ти не можеш. Ви повинні вилучити слово "відтворюється" або слово "врешті-решт"; ви не можете мати обох.
Роберт Харві

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

Відповіді:


16

Розгляньте нефункціональні вимоги під час проектування своїх функціональних тестів - якщо у вашій службі є нефункціональна вимога "Послідовно протягом x (секунд / хвилин / тощо)", просто запустіть запити PUT, зачекайте x, а потім запустіть GET-запити.

У той момент, якщо дані ще не "надійшли", ви можете вважати, що запит PUT не відповідає вашим вимогам.


7

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

Створіть підроблену службу, яка обробляє запити PUT та GET, але має додаткову операцію, щоб зробити її послідовною. Потім ваш тест:

datastore.do_put(myobj);
datastore.make_consistent();
validate(datastore.do_get(), myobj);

Це дозволяє перевірити поведінку програмного забезпечення, коли GET успішно отримує об'єкт PUT. Це також дозволяє перевірити поведінку програмного забезпечення, коли GET не знайде об'єкт (або правильний об'єкт) через те, що служба ще не є послідовною. Просто відмовтеся від дзвінка make_consistent().

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

  1. надавати показники в середньому та найгіршому випадку між PUT та наступним GET, стаючи послідовними; і
  2. переконайтеся, що ваша підроблена служба поводиться аналогічно реальній службі. Дивіться https://codewithoutrules.com/2016/07/31/verified-fakes/

6

Добре, так. "Що ти тестуєш" - ключове питання.

  • Я перевіряю свою внутрішню логіку того, що трапляється, припускаючи, що роботи Google

У цьому випадку ви повинні знущатися над службами google і завжди повертати відповідь.

  • Я тестую свою логіку, можу впоратися з тимчасовими помилками, за якими я знаю, що Google викличе

У цьому випадку слід знущатися над службами google і завжди повертати минущу помилку перед правильною відповіддю

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

Вам слід ввести справжні сервіси google і запустити тест. Але! У коді, який ви тестуєте, має бути вбудований режим переробки помилок (спроба). Отже, ви повинні отримати послідовну відповідь. (якщо тільки Google не дуже поводиться)


+1 за пропозицію Макету - я би дав більше голосів за додаткові варіанти, якби міг.
mcottle

6

Скористайтеся одним із наступних дій:

  • Після PUT, повторіть GET N разів до успіху. Не вдасться, якщо успіху після N не буде.
  • Сон між PUT та GET

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


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

1
Правильно, я мав на увазі, що вони будуть альтернативними.
Дуг Річардсон

2

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

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

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

Наприклад, ви можете мати методи, що називаються start_debug_strong_consistency()і end_debug_strong_consistency().

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

Єдиною зміною фактичних запитів, які ви тестуєте, було б зателефонувати, setAncestor(your_debug_key)якщо цей ключ існує.


1

Один із підходів, який приємно теоретично, але не завжди може бути практичним, - це зробити всі операції запису в системі під тестом ідентифікованими . Це означає, що припускаючи, що ваш тестовий код тестує речі у фіксованому послідовному порядку, ви можете повторити всі прочитані та всі записи окремо, поки не отримаєте очікуваний результат, повторюючи, поки не буде перевищено деякий час, визначений у тестовому коді. Тобто зробіть річ A1, якщо потрібно, повторіть, поки результат не стане B1, потім зробіть те, що A2, при необхідності повторіть, поки результат не стане B2, і так далі.

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

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


1

Такий сервіс, як Google App Engine Datastore, заснований на реплікації даних у кількох точках присутності (POP). Будь-який тест на інтеграцію для зрештою послідовного сервісу справді є тестом швидкості тиражування цієї служби через її набір POP. Швидкість, з якою вміст поширюється на кожен POP в даній службі, не буде однаковою для кожного POP в межах послуги залежно від ряду факторів, таких як метод реплікації та різні проблеми інтернет-транспорту - це два приклади які складають більшість звітів у будь-якій послідовній службі зберігання даних (принаймні, це був мій досвід, коли я працював у великому CDN).

Для ефективного тестування реплікації об'єкта на певній платформі вам потрібно встановити тест, щоб запитувати той самий нещодавно розміщений об'єкт конкретно з кожного POP-сервісу служби. Я пропоную тестувати список POPs один-п’ять разів або до тих пір, поки всі POPs у вашому списку POPs не стануть об'єктом. Ось набір інтервалів, протягом яких можна виконати тест, який ви можете вільно налаштувати: 1, 5, 60 хвилин, 12 годин, 25 годин після розміщення його в сховищі даних. Ключовим моментом є реєстрація результатів на кожному інтервалі для подальшого огляду та аналізу, щоб відчути здатність даної служби глобально копіювати об’єкти. Часто служби зберігання даних лише перетягують локальну копію на POP лише після того, як її запитують локально [маршрутизація проводиться через протокол BGP, тому ваш тест повинен запитувати об'єкт від кожного конкретного POP, щоб він був глобально дійсним для даної платформи] . Що стосується Datastore Google, ви б хотіли налаштувати свій тест для запиту певного об’єкта з "понад 70 точок присутності в 33 країнах"; вам, ймовірно, доведеться отримати список URL-адрес певної адреси POP із служби підтримки Google [ref:https://cloud.google.com/about/locations/ ] або якщо Google швидко використовує для тиражування, швидку підтримку [ https://www.fastly.com/resources ].

Кілька переваг цього методу: 1) Ви відчуєте уявлення про платформу реплікації даного сервісу, знаєте його моменти та слабкі місця в цілому в глобальному масштабі [як це було під час тесту на інтеграцію]. 2) Для будь-якого об'єкта, який ви тестуєте, у вас буде доступний інструмент для нагрівання контенту [зробіть перший запит, який створює копію в заданому локальному POP] - таким чином, ви зможете забезпечити поширення вмісту в усьому світі, перш ніж ваші клієнти вимагатимуть його де завгодно на землі.


0

Я маю досвід роботи з Google App Engine Datastore. Бігаючи локально, на диво, це часто більше "зрештою", ніж "послідовно". Найпростіший приклад: створіть нову сутність, а потім отримайте її. Часто за останні 5 років я бачив, що локальний SDK не знаходить нову сутність одразу, а знаходить її приблизно через півсекунди.

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

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


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