Пишем API автотесты на TypeScript + Playwright
Вступление
В данной статье мы разберем, как писать API автотесты на языке TypeScript + Playwright.
Хочется, чтобы наши автотесты отвечали следующим требованиям:
- Проверки должны быть полными, то есть мы должны проверить статус код ответа, данные в теле ответа, провалидировать JSON схему;
- Подготовка тестовых данных должна быть на уровне фикстур;
- Понятный и красивый отчет;
Requirements
Для написания API автотестов мы будем использовать:
- playwright - yarn add playwright/npm install playwright;
- allure-playwright - yarn add allure-playwright/npm install allure-playwright;
- dotenv - yarn add dotenv /npm install dotenv, - для чтения настроек из .env файла;
- ajv- yarn add ajv/npm install ajv, - для валидации JSON схемы;
Тесты будем писать на публичный API https://api.sampleapis.com/futurama/questions. Данный API всего лишь пример. На реальных проектах API может быть гораздо сложнее, но суть написания автотестов остается та же.
Settings
Добавим базовые настройки проекта в .env файл
Файл конфигурации playwright будет выглядеть стандартным образом, добавим лишь allure-report. Исключим ненужные для API тестов настройки, по типу projects, headless, video, screenshot. Более подробно про конфигурацию playwright можно почитать тут.
Обратим внимание на строчку:
Тут мы загружаем настройки и .env файла, который создавали ранее.
Лайфхак. Если у вас есть несколько окружений (dev, test, staging, local), то вы можете создать несколько файлов .env, например, .env.dev, .env.test, .env.staging, в каждый из них поместить настройки для определенного окружения. Тогда загрузка файла с настройками будет выглядеть примерно так:
Переменную ENV_FILE придется заранее добавить в окружение либо в команду запуска export ENV_FILE=".env.test" && npx playwright test
Types
Напишем типы для объекта question из API https://api.sampleapis.com/futurama/questions. Сам объект выглядит примерно так:
AuthUser возьмем просто для примера (на вашем проекте могут быть другие требования для аутентификации).
APIClient понадобится нам для имплементации API клиентов. Об этом поговорим ниже, когда будем описывать клиенты.
Context
Сначала напишем базовый контекст, который будет использоваться для всех запросов без авторизации
Теперь напишем контекст, который будет использоваться для выполнения запросов к API с аутентификацией. В этом API https://api.sampleapis.com/futurama/questions нет аутентификации, я указал заголовок для аутентификации по API Key ради примера. Скорее всего на вашем проекте у вас будет другой заголовок для аутентификации.
API Clients
Теперь опишем клиенты для взаимодействия с API.
Для примера опишем методы, которые будут работать с аутентификацией. Для https://api.sampleapis.com/futurama/questions аутентификация не требуется, но в своем проекте вы можете указать ваши методы для получения токена.
Обратите внимание, что мы имплементируем APIClient и прописываем context в конструкторе. Далее будем передавать нужный нам контекст внутрь клиента и c помощью клиента будем выполнять запросы.
Клиент для questions:
Используя QuestionsAPIClientсможем выполнять простые CRUD запросы к API https://api.sampleapis.com/futurama/questions.
Utils
Добавим необходимые утилиты, которые помогут сделать тесты лучше.
Хранить роутинги будем enum, чтобы не дублировать код и наглядно видеть, какие роутинги используются:
Добавим утилиты для рандомной генерации данных:
Я использовал нативные средства, чтобы сгенерировать рандомную строку, число; нам этого будет более чем достаточно. В своих же проектах вы можете использовать фейкеры для генерации данных, например, faker-js.
Теперь напишем утилиты, которые помогут нам сгенерировать данные для отправки в API:
В данном примере combineFixtures - это вспомогательный метод, который поможет нам собрать несколько объектов фикстур в один. Можно обойтись и без него, но мне так комфортнее.
Assertions
Перед тем, как начнем писать тесты, необходимо подготовить проверки.
Опишем базовые проверки, которые будут использоваться во всем проекте:
По сути вы можете не писать эти обертки, но тогда в отчете вместо читабельного шага будет отображаться что-то по типу expect.toEqual, что неинформативно. Поэтому лучше все же воспользоваться решением выше.
Добавим проверки для questions:
Мы написали функции assertUpdateQuestion, assertQuestion, чтобы потом использовать и переиспользовать их в тестах. Если отказаться от этого слоя, то мы получим кучу дубликатов в тестах.
Schema
Нам нужно описать модуль валидации JSON схемы. Для валидации будем использовать библиотеку https://ajv.js.org/guide/typescript.html
Напишем валидатор:
Функция validateSchema будет принимать схему и объект JSON, который должен быть провалидирован.
Далее нужно описать схему для questions:
О том, как писать JSON схему можно посмотреть тут https://json-schema.org/understanding-json-schema/. А сгенерировать JSON схему можно, например, тут https://www.liquid-technologies.com/online-json-to-schema-converter.
Fixtures
И последнее, что нам нужно сделать перед написанием тестов, - это описать фикстуры.
Сперва напишем фикстуру для получения тестового пользователя:
Теперь напишем фикстуры для questions:
Фикстура questionsClient будет конструировать и передавать нам в тесты клиент для взаимодействия с questions API. Фикстура question будет создавать объект question через API и по окончанию теста удалит созданный объект.
Testing
Теперь можно писать тесты, используя все клиенты, функции, фикстуры, проверки, которые были написаны выше.
Сделаем extend стандартного test объекта из playwright и добавим в него свои фикстуры:
Тут пять тестов на стандартные CRUD операции для questions API https://api.sampleapis.com/futurama/questions.
Возвращаясь к нашим требованиям:
- Проверяем статус код ответа, тело ответа, JSON схему;
- Данные готовятся внутри фикстур;
- На отчет посмотрим ниже.
Report
Перед генерацией отчета хочу показать одну интересную фичу playwright, с помощью которой мы можем делать глобальные setup, teardown.
В playwright.config.ts мы добавляли такую запись:
Которая указывает на путь к файлу, из которого экспортирована функция globalTeardown. Playwright запустит эту функцию по окончанию тестовой сессии. Для примера давайте сделаем отображение всех переменных окружения в allure отчете с помощью global-teardown:
По аналогии вы можете сделать, например, получение токена в начале тестовой сессии globalSetup, а потом очистку базы данных после окончания тестовой сессии globalTeardown.
В отчете увидим переменные окружения, которые мы прописывали в globalTeardown
Запустим тесты и посмотрим на отчет:
Теперь запустим отчет:
Либо можете собрать отчет и в папке allure-reports открыть файл index.html:
Заключение
Весь исходный код проекта расположен на моем github.