null

Функциональные тесты с Postman

Однажды я устроился работать в небольшую компанию и там.... я не нашел тестов!

 

Введение

Не мне холиварить насчет того, надо ли писать тесты или не надо. Как говорится "не дорос еще". Однако опыт участия в нескольких проектах за полгода показал, что тесты разработчики писать не любят. Чего греха таить, я сам не люблю их писать. В написании тестов нет ничего творческого, а ведь программист рожден творить! Протестировать CRUD операции? Да чего там тестировать, я их 100500 раз писал, лучше пойду напишу интеграцию с каким-нибудь Keycloak. И мне интереснее, и для проекта профитнее...

Постойте, как это пользователь в Keycloak-е не создается? Я же совсем недавно проверял руками в постмане, все работало!

Думаю, для некоторых моих коллег ситуация знакомая. Проект горит, надо пилить фичи, писать тесты нет ни времени, ни желания. А по факту каждая новая фича, которая "вроде бы работает", требует еще многократных правок и порой необходимость этих правок обнаруживается на проде... 

Мем: "за это не благодарят это грустно только" - Все шаблоны -  Meme-arsenal.com

И после неприятно опыта, полученного на своей шкуре, я принял для себя, так сказать "внутренее решение". Ни одна фича не является работающей, а значит я ее не сдаю, пока либо от и до не протестирую руками, либо пока не напишу для нее хоть какие-нибудь тесты. Потратив пару часов на изучение вопроса "как организовать тестирование на бэке силами самого разработчика", я пришел к следующему решению:

Коммит -> Unit тесты -> Деплой на тестовый контур -> Функциональные тесты.

Вообще говоря, в этом нет ничего нового, никакого откровения. Unit тесты? JUnit или Kotest. Деплой на тестовый контур? Попроси девопса настроить. И только функциональные тесты лично для меня  встали под вопросом.

 

Функциональные тесты с Postman

Что хочется: протестировать новые эндпоинты и проверить, что старые работают.

Что не хочется: тратить много времени, осваивать новые инструменты.

Решение: Postman!

Как оказалось, всем нам знакомый Postman не только позволяет кидать запросы "руками" и проверять ответ сервера "глазами", но и автоматизировать проверку ответа сервера на короткие тесты, написанные на JS. (JS конечно вызывает отдельное бэкендерское отвращение). Кроме того, у Postman-а есть возможность упорядочивать коллекции запросов и прогонять их в соответствии с этим порядком. То есть, постман предоставляет из коробки возможность как угодно тестить ломать эндпоинты сервера. В том числе даже возможно автоматизировать тестирование сложных сценариев, например:

1. Проверить, что пользователя с логином qwerty не существует (условно GET /users/)

2. Создать пользователя с логином qwerty (условно POST /users/) и сохранить его id (в переменных уровня коллекции, например)

3. Получить пользователя по его id (условно GET /users/{id}, id берем из переменных коллекции, куда мы сохранили значения с шага 2)

(За конкретным how-to перенаправляю в документацию: тык)

Итого постман позволяет:

1. Кидать запросы на сервер.

2. Автоматически проверять ответ сервера.

3. Связывать несколько запросов в один тестовый сценарий засчет их упорядочивания и передачи информации между ними через переменные коллекции.

Остается 2 вопроса:

1. На какой сервер кидать запросы?- практически на всех проектах есть тестовый контур - идеальный кандидат для тестерских извращений.

2. Как автоматизировать запуск тестов? - последние версии постмана поддерживают интеграцию с Gitlab CI (подробнее тут).

 

Заключение

Итак, как лично я вижу процесс тестирования бэкенд части наших проектов:

1. Автоматизированные Unit тесты запускаются на каждый коммит в любой ветке.

2. На коммиты или MR в защищенные ветки типо dev и master после успешный unit-тестов, коммит разворачивается на тестовом контуре.

3. После деплоя прогоняются функциональные тесты на основе коллекций запросов Postman-а. Когда все тесты зеленые, коммит считается работоспособным.

Данный подход, на мой взгляд, не требует больших временных затрат разработчиков, так как модульными тестами можно покрывать только наиболее критичные участки кода, например, сложные валидации на уровне бизнесс-логики, сложные маппинги между моделями (если их, конечно, больше, чем одна). Функциональные же тесты произрастают прямиком из коллекций запросов Postman-а, которые бэкенд разработчики обычно всегда пишут, чтобы проверить руками локально, что их код работает.

Как результат мы сможем получить следующие преимущества:

1. Большая уверенность нас и заказчика в том, что новая фича действительно работает. Причем важно отметить, что функциональные тесты на основе эндпоинтов могут выступать также в роли интгерационных тестов. Например, интеграция с бд (если задуматься, это ведь тоже интеграция), интеграции с SSO или 1С, интеграции между нашими собственными сервисами и т.д. Как показывает практика, большинство багов, которые разработчики пропускают в продакшн, связаны как раз с проблемами интеграции.

2. Меньше шанс сломать то, что работает. Очевидно и известно, что большой набор тестов любого рода позволяет заметить, что наш коммит ломает что-то старое раньше, чем коммит попадет в прод. Причем ручные тесты подобного рода ошибки практически никогда не поймают, так как разработчику всегда лениво проверить все 100+ фич, которые уже есть в проекте. Тем более, что разработчик чаще всего не знает, как некоторые фичи работают, потому что писал их не он.

3. "Живая" документация для фронтэнд-разработчиков. Практически на всех проектах у нас принято использовать spring-doc для генерации openapi спеки на основе контроллеров, чтобы фронтэндерам было проще понять, какие запросы им нужно кидать на сервер. Использование коллекций запросов Postman-а как функциональных тестов позволит пойти еще дальше. Генерируемая openapi документация хотя и описывает конкретные эндпоинты, она никогда не снабжается осмысленными данные и уж тем более, не показывает логику сложных сценариев использования последовательно сразу нескольких эндпоинтов.


Берегите себя и свои нервы - пишите тесты :)