Тестирование VK API при помощи VK Java SDK

На митапе VK Tech Talks | QA, прошедшем 9 сентября, инженер по автоматизации тестирования Михаил Кузнецов выступил с докладом «Тестирование VK API при помощи VK Java SDK». Представляем расшифровку выступления.

Несколько слов о VK API

Существует несколько версий VK API, с которыми можно работать, и два типа токенов: групповые и пользовательские. Также существуют сервис-токены, но в тему доклада они не вошли. В API имеется больше 40 разделов с более чем 400 методами, которые разделяются на приватные и публичные. VK API работает напрямую с JSON-схемой.

JSON-схема

JSON-схема — это некоторый стандарт описания JSON-объектов. Посредством ключевых слов она валидируется и проверяется на актуальность ожидаемого.

В качестве примера возьмём простой JSON с тремя полями: id, first_name и last_name. Чтобы описать поля, нужно написать такой JSON:

Тестирование VK API при помощи VK Java SDK, image #1

Каждое поле находится в секции properties, содержит информацию о своём типе и описание. Мы можем указать поля required, которые обязательно должны присутствовать в JSON-объекте, иначе это будет невалидная схема. Настройка additionalProperties говорит, что в этом JSON не может быть больше полей, чем представлено.

Как JSON-схема генерируется в VK?

Сначала разработчики пишут код. Прописывают бэковые ручки, ответы, модель ответов, после чего сложными манипуляциями код преобразуется в JSON. В итоге мы получаем большую JSON-схему, которая описывает методы, ответы и запросы.

Как будет выглядеть метод API в рамках схемы?

Тестирование VK API при помощи VK Java SDK, image #2

У метода есть поля name, description, acces_token_type (это типы токенов, с которыми может быть вызван этот метод). Будут указаны параметры, чтобы вызвать запрос, и помечены параметры обязательные и необязательные. Могут быть и другие настройки: responses, который указывает реферальной ссылкой на JSON-объект к JSON-схеме и встраивается туда.

Ошибки

Ошибки конкретно этого метода:

Тестирование VK API при помощи VK Java SDK, image #3

Ответы выглядит намного проще:

Тестирование VK API при помощи VK Java SDK, image #4

Здесь есть название этого объекта и ссылка на то, что он вернёт. Бывают простые объекты и более сложные — они являются объектом, но могут содержать внутри такие поля, как array. Например, если мы хотим получить архив историй, то мы получим объект, у которого будет в модели response, properties, count (количество архивных историй) и items (сами истории). Они могут быть и объектом, и не объектом.

Возвращаемый объект выглядит так:

Тестирование VK API при помощи VK Java SDK, image #5

Он большой, содержит тип, properties (это поля), поля required и additionalProperties (эту настройку вы видели на одном из первых слайдов).

Как генерируется документация VK API?

Документация генерируется на основе схемы. Это упрощает генерацию странички, которую вы видите в документации API. Например, у есть группы, такие как «Авторизация». В группах есть список методов, их описание и аннотация к группам. К группе «Авторизация» относится метод checkPhone. Он отображается в документации на своей страничке с параметрами, результатом и кодами ошибок. На последнем слайде в «карусели» есть пример того, как параметры запроса описаны в схеме и в документации. К сожалению, это старый скриншот, поэтому описание сделано вручную. Сейчас всё генерируется автоматически.

Тестирование VK API при помощи VK Java SDK, image #6
Тестирование VK API при помощи VK Java SDK, image #7
Тестирование VK API при помощи VK Java SDK, image #8
1 of 3

Java SDK

Java SDK — это набор готовых реализаций для работы с API VK. Для «ВКонтакте» существует шесть SDK, но здесь поговорим только о Java.

Как она генерируется?

У нас есть JSON-схема, в которой описаны все запросы, ответы, модели возвращаемых объектов. Потом эта схема парсится и превращается в Java-код, который представляет модели ответов, запросов и возвращаемых объектов. Он «прикручивается» к существующему коду, написанному вручную.

Типы пользователей

Тестирование VK API при помощи VK Java SDK, image #9

Существует три типа пользовательских токенов, но мы поговорим только о двух, потому что третий в наших автотестах пока не используется. Это UserActor и GroupActor. Я буду говорить о них в контексте Java SDK. Это интерпретация связки токенов пользователей и его ID, необходимого для передачи параметра AccesKey. Они экстендятся от объекта Actor.

Как выглядит запрос Java SDK?

Все запросы описаны как некоторые Query, которые наследуются от абстрактного Rebuilder, которые в свою очередь наследуются от абстрактного класса APIRequest. Каждый класс Query генерируется на основе схемы и превращается в то, что вы видите справа на слайде.

Тестирование VK API при помощи VK Java SDK, image #10

Параметры

Чтобы параметризовать Query, мы можем пойти двумя путями:

  1. Подход в виде билдеров, где мы указываем Query. В данном случае это create album. Параметризуем его методами title, description и comments_disabled. Это метод создания альбома. Title — название, descriptionописание, и третий параметр — доступность комментирования. Далее вызывается метод execute, который реализован уже непосредственно в классе pre request.
  2. Во втором методе мы можем использовать встроенный на уровень AbstractQuery метода SafeParam. Он переопределён для разных типов данных и мы можем задать параметр Query, где .unsafeParam принимает в качестве первого аргумента и вторым аргументом значение параметра. Всё это переопределено в классах AbstractPreBuilder для разных типов.
Тестирование VK API при помощи VK Java SDK, image #11

Запрос Java SDK

Если мы «провалимся» в метод execute, который вызывается для выполнения запроса из Query, то увидим, что запрос уже выполняется на уровне HTTP, после чего реализуется в JSON-объект и проверяется на наличие поля error, которое скажет нам об ошибке от API, либо response, которое скажет, что ошибки нет.

Для серверизации внутри используется GSON (библиотека Google). После этого объект возвращается, и мы уже можем с ним работать.

Тестирование VK API при помощи VK Java SDK, image #12

Модель Java SDK

Модель Java SDK — самая простая SDK-модель, созданная на основе схемы и содержащая в себе поля обязательные и необязательные. Обязательность регулируется аннотацией Required (GSON-аннотация). У нас тут есть геттеры, сеттеры, переопределённые методы и String prettifier.

Тестирование VK API при помощи VK Java SDK, image #13

Тестирование Java SDK

Java SDK работает с ошибками как с Exceptions: если внутри executor JSON-объект, то снаружи этот JSON-объект будет либо валидным, либо Exception. Другими словами, метод Execute создаст исключение в том случае, если API вернёт нам “error”. Поэтому в рамках разработки это отличное решение, но тестирование осложняется.

Как мы решили эту сложность?

Тестирование VK API при помощи VK Java SDK, image #14

Приведу пример Exception, бросаемого из SDK. Здесь написано, что есть параметр title, у которого минимальная длина обозначена как 2 символа. Мы напишем код, который будет вызывать QueryCreateAlbum с параметром title длиной 1 символ — символ “x”. На выходе получаем exception, где будет указано API Exception Error. Он расскажет нам о появившихся проблемах и предоставит код ошибки.

Тестирование VK API при помощи VK Java SDK, image #15

Это наш типичный тест. Мы придерживаемся концепции «Три А”» (Arrange App Assert). Здесь всё разделено на логические блоки:

  1. инициализация пользователя, с которого мы будем выполнять запрос;
  2. execution, то есть здесь мы выполняем запрос.

Поскольку мы не хотим писать много лишнего кода, самым оптимальным вариантам является параметризация и работа через подход DDT (Data Driven Testing), что ложится очень красиво на концепцию TestNG. Также у нас есть обработка ожидаемых исключений. Как известно, DDT предполагает как позитивные, так и негативные кейсы. Поэтому в случае негативных кейсов мы должны как-то обрабатывать исключения, которые появляются в методе Execute. Так у нас появился блок Assert, где реализованы специальные самодельные компараторы. Для Assert используется AssertJ, потому что это просто удобно.

Организация автотестов

Мы написали ActorProvider — это класс, который раздаёт пользователей в рамках нескольких потоков. Каждый тест приходит к ActorProvider и берёт пользователя. Но количество пользователей ограничено. Поэтому, если пользователя нет, тест встаёт в очередь на ожидание свободного.

Тестирование VK API при помощи VK Java SDK, image #16

Как это работает изнутри?

ActorProvider активируется по всем нашим токенам и делит их на функциональные группы. Когда у нас есть готовые пользователи, в рамках тестов мы используем их параллели. После завершения каждого теста пользователи освобождаются и тесты снова могут их взять. Внутри ActorProvider реализован BlockingQueue (очередь с N количеством пользователей). Когда пользователи кончаются, тесты встают в очередь на получение новых. Объекты пользователей реализуют интерфейс AutoClosable, что позволяет нам условно интерпретировать эти объекта как ресурсы и возвращать их после окончания блока try, используя в тестах конструкцию try-with-resources.

Тестирование VK API при помощи VK Java SDK, image #17

В ActorProvider существует две очереди: для групповых и пользовательских токенов. Чтобы можно было работать с очередью, UserActor и GroupActor были обёрнуты в специальные объекты: PoolUserActor и GroupUserActor. Они наследуются, что обязывает их выполнить метод Close в конце своей работы, тем самым вернувшись в pool.

Тестирование VK API при помощи VK Java SDK, image #18

Следующий блок — Act. Здесь тоже реализован кастомный executor запросов. Метод performRequest принимает на вход разного рода Query и Test Data в качестве второго аргумента. TestData у нас предоставляется через сайт провайдера.

Тестирование VK API при помощи VK Java SDK, image #19

Как это выглядит внутри?

Существует два метода, один из которых предопределённый:

  1. выполнить запрос без параметров;
  2. выполнить запрос с параметрами.

В качестве параметра принимается объект Request_Data. Наши методы натированы Allur-аннотациями, что позволяет нам генерировать репорты. В AllurReport передаются параметры запросов, которые были использованы, и то, что мы получили обратно Response. Также здесь у нас реализована обработка ожидаемых исключений.

Внутри метода CompareException происходит сравнение фактического exception с ожидаемым. Если они совпадают, значит исключение было ожидаемым и тест пройден. Если нет, мы получаем ошибку exception на уровень выше и тест краснеет.

Тестирование VK API при помощи VK Java SDK, image #20

Data driven

Тестирование VK API при помощи VK Java SDK, image #21

Здесь существуют DataProvider, которые реализуются для каждой из групп. В свою очередь они наследуются от такого класса, как BaseDataProvider. У нас существуют наборы данных, которых может быть произвольное количество. Есть метод Initialize, реализованный в классе BaseDataProvider, поэтому можно удобно всем этим пользоваться.

Как мы храним тестовые данные?

Тестирование VK API при помощи VK Java SDK, image #22
Тестирование VK API при помощи VK Java SDK, image #23
1 of 2

Тестовые данные мы тоже храним в виде JSON, где каждый набор — это request. Другими словами, у нас существует массив запросов в количестве, необходимом для каждого quest’а. Каждый запрос содержит имя, эквивалентное методу API, который описан в спецификации. В блоке параметров есть два параметра и ожидаемый результат. Вместо такого поля может быть ExpectedException, куда мы передаём ожидаемые исключения. Вот пример ещё одного набора тестовых данных эквивалентных предыдущим, но с той разницей, что здесь уже три параметра. Таким образом мы можем не написав ни одной строчки кода запустить новый тест. Также здесь есть ExpectedResponse — это будет уже другой объект.

Тестирование VK API при помощи VK Java SDK, image #24

Блок Assert

Нашим компаратором реализована логика сравнения двух строковых объектов типа object или списка объектов. Метод CompareObjects переопределён для сравнения со строкой двух объектов. Ещё у нас есть метод для сравнения списка объектов. Благодаря этим методам мы можем игнорировать поля, которые нам не интересны, до любого уровня вложенности.

Представим, что у нас есть ожидаемый JSON и фактический. Но в виду того, что в некоторых JSON существуют поля, которые динамически меняются, например дата добавления или ID, мы не можем их сравнить один к одному, потому что в этом случае получим ошибку. Исключая эти поля, мы игнорируем их в сравнении. Сравнение происходит таким образом, что каждый объект интерпретируется как мапа вложенных мап до уровня вложенности, эквивалентного уровню JSON, и рекурсивно сравнивается. Также у нас реализован метод CompareExceptions, чтобы сравнивать фактические и ожидаемые исключения.

Вот как выглядит блок, когда мы сравниваем два объекта, которые не соответствуют друг другу. Здесь ожидается, что объект, который мы получили, содержит поля description, privacy_comment, privacy_view, size, thumb_id и title. Но по факту, к сожалению, он содержит пустое поле description, и мы получаем ошибку. Таким образом исключение выводится на такой красивый лог.

Тестирование VK API при помощи VK Java SDK, image #25

Заключение

В завершение доклада хочу сказать, для чего мы использовали SDK:

  1. Модели описания возвращаемых объектов реализованы, что избавляет нас от рутины.
  2. Объекты в JSON-схеме провалидированы уже на этапе создания.
  3. API-методы уже реализованы, и нам остаётся только немного прикрутить всё так, как нужно нам, и сконфигурировать.

Полную запись выступления Михаила можно посмотреть здесь:

Тестирование VK API при помощи VK Java SDK, image #26

The Brown Room — независимое интернет-издание про социальные сети и современные технологии

Автор: Влад Воробьёв
Корректоры: Лена NL, Арсений Метелев
Слайды и данные: VK Tech

988 views·10 shares