Тестування модуля клієнта API та обгортки


14

Я ходив по колах, намагаючись зрозуміти найкращий спосіб перевірити клієнтську бібліотеку API, яку я розробляю. Бібліотека має Clientклас, який в основному має зіставлення 1: 1 з API, та додатковий Wrapperклас, який забезпечує більш зручний інтерфейс у верхній частині Client.

Wrapper --> Client --> External API

Я спершу написав купу тестів проти обох Clientі Wrapper, фактично просто перевіривши, що вони пересилають на відповідні функції будь-якої операції ( Wrapperпрацює Clientі Clientпрацює на HTTP-з’єднанні). Однак я почав відчувати себе незручно, тому що відчуваю, що я тестую реалізацію цих класів, а не інтерфейс. Теоретично я міг би змінити класи, щоб мати іншу ідеально реалізовану реалізацію, але мої тести не зможуть, оскільки функції, які я очікував, будуть викликані, не викликаються. Це звучить як тендітне тестування для мене.

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

Нарешті, я прочитав це з іншої відповіді на програмістів SE :

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

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

Однак я все-таки застряг із Wrapperкласом. Я бачу такі варіанти:

  1. Я замовчую Clientклас і просто перевіряю, чи називаються відповідні методи. Таким чином я роблю те саме, що вище, але трактую ClientAPI як резервний інтерфейс для API. Це повертає мене туди, де я почав. Знову ж таки, це дає мені незручне відчуття щодо тестової реалізації, а не інтерфейсу. Це Wrapperдуже вдало реалізувати за допомогою зовсім іншого клієнта.

  2. Я створюю макет Client. Тепер я маю вирішити, як далеко пройти з його глузуванням - створення повноцінного знущання над сервісом зайняло б багато зусиль (більше роботи, ніж пройшло в самій бібліотеці). API сам по собі простий, але сервіс досить складний (по суті це сховище даних з операціями над цими даними). І знову, мені доведеться тримати свою глузування синхронно з реальною Client.

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

Тому я не особливо задоволений жодним із цих рішень. Що б ти зробив? Чи є правильний шлях для цього?


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

Відповіді:


10

TLDR : Незважаючи на труднощі, вам слід зупинити послугу та використовувати для тестування клієнтських підрозділів.


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

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

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

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

Ви можете розглянути можливість використання рішення на основі DI для цього, реалізація шаблону репозиторію під ресурсами REST:

  • Замініть весь функціональний код у обробниках REST на виклики до IWeverRepository.
  • Створіть ProductionWeverRepository з кодом, який було витягнуто з ресурсів REST, і TestWeverRespository, який повертає консервовані відповіді для використання під час тестування одиниць.
  • Використовуйте контейнер DI для введення DLL / класу ProductionWeverRepository або TestWeverRepository і т.д. залежно від конфігурації.

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

HTH

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