Создание тестов API на JavaScript при помощи Pactum |
10.10.2022 00:00 |
Автор: Баз Дейкстра (Bas Dijkstra) Я часто говорю себе (а также участникам моих тренингов), что JavaScript не очень-то со мной дружит. Возможно, проблема во мне, возможно, в JavaScript, но по какой-то причине я не могу вникнуть в этот язык. Университетское воспитание на куда более жестких языках (особенно Java), возможно, приложило к этому руку. Нельзя, однако, отрицать, что JavaScript – популярный язык, и спрос на автоматизацию на нем довольно высок. Поэтому я решил, что будет хорошей идеей потратить время на исследование языка и доступные нынче инструменты. Так как множество моих технических статей в той или иной степени посвящено тестированию API (включая имитацию API и контрактное тестирование), а ранее меня не впечатлили библиотеки для тестирования API в JavaScript, я решил, что было бы неплохо взять это за точку отсчета. Я большой поклонник API-библиотек вроде REST Assured для Java и requests для Python, так как с их помощью очень легко писать тесты API. Аналогично простая в использовании библиотека JavaScript была мне не знакома до тех пор, пока кто-то на LinkedIn не написал статью про Pactum (к сожалению, не могу найти оригинальный пост). Выглядело это неплохо, поэтому я решил проверить, как оно в деле. Конечно, еще помогло то, что я обязался сделать доклад и живое демо по API-тестированию на JavaScript для группы студентов-тестировщиков. Ничто не заставляет меня изучать что-то новое так, как обязанность говорить публично. Судя по документации, Pactum вроде бы способен на довольно-таки многое. Интеграционное тестирование, имитация API, тестирование контрактов… Все это там есть. В этой статье я сконцентрируюсь на возможностях библиотеки для тестировании API (интеграционного тестирования), но, возможно, в будущем исследую другие функции Pactum и сделаю серию статей. Примеры, которые вы найдете в этой статье, написаны на фреймворке Jest. Начнем с "Hello, world!" API-тестирования: выполним GET-запрос к конечно точке и проверим код статуса ответа. В Pactum это можно сделать так: describe('Retrieving data for user with ID 1', () => { test('should yield HTTP status code 200', async () => { await pactum.spec() .get('http://jsonplaceholder.typicode.com/users/1') pactum.spec() показывает все методы в Pactum, создающие запрос. Так как нам не нужно задавать заголовки, куки или тело запроса, мы можем напрямую вызвать HTTP GET через метод get(), передавая любую конечную точку, а затем указать ожидания от ответа. В нашем случае мы ожидаем только того, чтобы код статуса HTTP был 200, что можно проверить методом expectStatus(). Запуск этого теста (с использованием npm run test, что, в свою очередь, вызывает Jest) показывает, что тест пройден:
В качестве следующего шага посмотрим, можем ли мы проверить заголовок ответа, в этом случае – заголовок Content-Type: test('should yield Content-Type header containing value "application/json"', async () => { await pactum.spec() .get('http://jsonplaceholder.typicode.com/users/1') .expectHeaderContains('content-type', 'application/json') }); Метод expectHeaderContains() делает именно то, о чем заявляет: ищет заголовок ответа и проверяет, содержит ли он заданное ожидаемое значение, в данном случае application/json. Надо иметь в виду, что по какой-то причине вам нужно задавать имя заголовка в нижнем регистре. Изначально я использовал Content-Type, но тест упал, потому что не нашел соответствующий заголовок. Если вам нужен метод для точного совпадения, используйте expectHeader(). Затем давайте посмотрим на тело ответа. Pactum очень хорошо поддерживает тела ответа JSON, а поддержка остальных вариантов (чистый текст, XML, …) ограничена построчным сравнением – это значит, что придется выполнить побольше самостоятельной работы. Наш тестируемый API возвращает данные в формате JSON, поэтому в данном случае это не проблема. Допустим, мы хотим проверить, что имя элемента верхнего уровня равно "Leanne Graham" в ответе JSON. Это очень просто сделать, используя метод expectJsonMatch() в Pactum: test('should yield "name" JSON body element with value "Leanne Graham"', async () => { await pactum.spec() Первый аргумент в expectJsonMatch() – это на самом деле выражение json-query, его можно использовать и для вложенных объектов: test('should yield "Gwenborough" as the city within the address', async () => { await pactum.spec() .get('http://jsonplaceholder.typicode.com/users/1') .expectJsonMatch('address.city', 'Gwenborough') }); Как насчет POST-передачи чего-то конечной точке вместо получения и проверки данных от нее? Оказывается, это с Pactum тоже довольно просто: describe('Posting a new post item', () => { test('should yield HTTP status code 201', async () => { let new_post = { "title": "My awesome new post title", await pactum.spec() Создать содержимое JSON очень просто: нужно написать его и использовать метод withJson(), чтобы добавить его в запрос. В качестве финального примера я часто смотрю на то, насколько легко создавать тесты, управляемые через данные, при помощи библиотеки API. Так как API часто демонстрируют бизнес-логику, и вам нужно более одной комбинации ввода и соответствующего ожидаемого вывода для правильной проверки этой логики, то тесты, управляемые через данные, очень распространены в API-тестировании. Здесь Jest делает все сложное за нас (как JUnit делал бы в Java, а pytest в Python), давая нам механизм для таких тестов с test.each(): describe('Retrieving user data for users', () => { test.each( await pactum.spec() Все, что нам остается сделать, создавая Pactum-тест – это задать параметр пути, используя метод withPathParams(), и используя его для наполнения плейсхолдера {user} в конечной точке. Механизм очень похож на аналогичную работу в Java, C# или Python, что сильно помогает мне ценить Pactum (и Jest, и даже в целом JavaScript). Запуск этого теста вернет вот такой результат: То, что вы увидели в этой статье – всего лишь некоторые примеры возможностей Pactum. Судя по документации, с библиотекой можно сделать намного больше, и я предвкушаю исследование его функций – особенно возможностей имитации и контрактного тестирования. Никогда не думал, что скажу это про библиотеку JavaScript… Весь код и примеры из статьи можно найти здесь. |