Как в разы уменьшить время прохождения автотестов?
Сделать сервис автоматического создания пользователей и прикрутить Redis, конечно же.
Привет, меня зовут Евгений Шайкин, я ведущий специалист по тестированию в команде Цифрового Рубля, майнтейнер одного из проектов автотестов, состою в команде развития автотестов в Альфа-Мобайл, где, собственно, и веду свою активную бурную деятельность. Я расскажу, как две небольшие «доработки» помогли сэкономить время и повысить эффективность автотестов.
Статью условно можно разделить на две части: сначала я расскажу про оптимизацию автотестов или как мы создаём тестовые данные, а потом — о кэшировании.
Автотесты и 5 минут на «Клиента»
Наш банк обладает сложной и многоуровневой архитектурой, которая влечет за собой определенные трудности в процессе тестирования. Если кратко:
Само приложение(фронт) — Альфа-Мобайл, Альфа-Онлайн и ещё несколько приложений.
Далее слой API, которые «торчат» наружу для работы приложений. Слышал, что сейчас их больше 350, но это не точно.
И дальше у нас ещё 3-4 различных слоя, в зависимости от операций и действий пользователя, участвующих в процессе работы. Например, платеж юрлица и покупка акций задействуют разные слои.
Одна из ключевых проблем специалиста по тестированию — создание нового пользователя под нужды определенного теста.
Основная сущность в банке — это «Клиент», в простонародье — «пользователь» или «пользак». У клиента есть куча различных параметров, от ФИО до счетов, кредитов и карт. Всё крутится вокруг Клиента.
За каждый отдельный логический модуль отвечает большое количество команд. Они имеют условные архитектурные различия (Java, C#, Python и т.д.) и находятся на различных серверах, неймспейсах — если привязаться к терминологии популярного К8S.
Каждый из этих «модулей», которые вкупе составляют «Банк», имеют ряд своих ограничений на взаимодействий между собой. Ну и время взаимодействия от различных «модулей» также может сильно отличаться. Далеко ходить не надо, можно просто представить, с технической точки зрения, как много информации по сети бегает туда-сюда. А если во всю эту картину вписать различные базы данных, кеши, брокеры сообщений, балансировщики, мы получаем достаточно длительное время отклика.
У нас архитектурно было задумано так, что для каждого прогона автотестов создаётся новый пользователь. И чтобы нам создать самого стандартного «Клиента», допустим с ФИО, паспортными данными, картой и счетом, ну и каким-то количеством денег на счету, в ручном режиме необходимо обойти изрядное количество сервисов.
Это прямо совсем грустно. Специалисты по тестированию тратили бы уйму времени на создание тестовых данных. На создание тестового пользователя руками уходит минут 5. Но так как автотестов у нас 1000+, общее время работы, только на пользователей, составляет 80 часов!
Но прогресс не стоит на месте, все течет, все меняется и для таких целей, как создание пользователя, был разработан специальный микросервис. Он делает 95% работы за нас, а именно — бегает по сервисам и создает нам нашего «клиента». Оставшиеся 5% это прям совсем что-то новое, либо какие-то корнер кейсы, которые не стоят времени на доработку автоматизацией.
Как устроен микросервис по созданию тестовых пользователей
Если совсем совсем верхнеуровнево, то как на картинке ниже:
Немного технических подробностей:
В качестве оркестратора у нас Кубер.
Сам сервис написан на Java. На текущий момент используем 17 версию.
Spring Boot второй версии.
Сборщиком выступает Gradle.
Сам микросервис под капотом использует как REST-вызовы до других сервисов, так и SOAP (да-да, все мы любим SOAP).
Конфиг сервер используем для хранения настроек микросервиса.
Основной пойнт —это микросервис от тестировщиков для тестировщиков. Когда-то давно скелет был написан программистами. Но поддержка и добавления нового функционала сейчас полностью на нас — тестировщиках ^_^. Основная поддержка на ментейнере проекта (Гриша, если читаешь Привет=)), а когда хватает времени занимается развитием:
Когда недостаточно какого-то функционала, коллеги берут технические цели на квартал и делают что им не хватает, если хватает компетенции в разработке.
Если же компетенций не хватает, то приходят в чатик/Конфлюенс/ментейнер и расписывают что надо. Аналитика остается за человеком с хотелками — полностью расписывают как это сделать ручками.
А когда не хватает каких-то компетенций в плане кода, то наши разработчики всегда рады помочь.
Процесс разработки новых фич в микросервисе полностью похож на разработку любых других микросервисов: написание самого функционала, Unit-тестов, интеграционных, а также выкатка snapshot версии для теста. Ну и, конечно же, куда без pull request с ревью кода.
Так как сервис используют, в основном, тестировщики, то и используем один из основных инструментов тестировщика, а именно Postman. Есть уже заготовленная коллекция с часто используемыми параметрами + есть описание всех параметров в Конфлюенсе.
Приведу примеры запроса и ответа. Они выглядят иначе, конечно, я убрал критическую информацию, но для понимания достаточно.
Запрос в curl виде:
curl --location '<https://alfabank.ru/blabla/createuser>' \\
--header 'TokenForCreatingAMUser: tratata' \\
--header 'Content-Type: application/json' \\
--header 'Authorization: tratata' \\
--data '{
"createTemplates": false,
"activateCards": false,
"connectChannels": true,
"addUserToOcrmSpineTable": true,
"tariffPlan": "TRDYF",
"cards":{
"debit":true,
"credit":false
},
"bioInfo": {
"birthDate": "10-12-1994"
},
"identityDocument": {
"issueDate": "13-02-2015"
}
}'
Ответ:
{
"phoneNumber": "79051054844",
"birthDate": "1995-10-24",
"fullName": "Мухин Динар Евдокимович",
"shortName": "Мухин Д Е",
"lastName": "Мухин",
"name": "Динар",
"patronymic": "Евдокимович",
"transliteratedName": "DINAR MUKHIN",
"embossedName": "Dinar Mukhin",
"tariffPlan": "TRDYF",
"accounts": [
{
"accountNumberFull": "40817810610210109398",
"currency": "RUR",
"shortAccountNumber": "··9398",
"maskedAccountNumber": "40817…398"
}
],
"cards": [],
"templates": null,
"autoPayments": null,
"secSalesOffers": null,
"secondaryCardOfferId": null,
"identityDocumentInfo": {
"number": "26 61 298404",
"issuer": "ТП УФМС РОССИИ",
"issuerCode": "520-015",
"issueDate": "13-02-2015"
},
"massEmployeeDraftNumber": null,
}
Вот таким нехитрым образом мы создали пользователя, под которым на тесте мы можем зайти в мобильное приложение или Альфа-Онлайн. И приступить к тестированию.
Также сервис переиспользуется в дебаг меню приложений.
«Кешируем» пользователей
С сервисом на создание пользователя, в среднем, уходит где-то 15-30 секунд. Время зависит от загруженности тестовой среды. Но и с ним время только на создание пользователей занимает часов 8!
А ведь это время можно потратить эффективнее, например, на дополнительный прогон или разбор отчетов по прогону.
Данная ситуация не нравилась никому. И как мы из нее вышли?
Мы решили провести мозговой штурм, чтобы обдумать все наши варианты того, как бы мы могли на это повлиять. В ходе споров поняли, что достичь единого варианта невозможно. Тогда подключили аналитику и процесс пошел.
В результате выяснили, что примерно половина наших тестов — это GET-запросы, которые «не портят» пользователя, а значит — его можно переиспользовать и делать нового не требуется. А «переиспользовать» значит, что нам нужен кэш.
Примечание. «Не портят» — значит, что данные пользователя не меняются после повторной отправки запроса, например, «денег» на счету не становится меньше или больше, ведь GET запросы только извлекают информацию, но не меняют ее.
А как это организовать?
Родилась концепция с двумя решениями:
Первый вариант — встроить использование удаленного кэша в сам тестовый проект. Но из-за достаточно сложного доступа к кэшируемому серверу мы отказались от него.
Второй вариант — встроить использование удаленного кеша в API по созданию клиентов. Здесь мы, по сути, обратили внимание в сторону DB Redis. А так как в Альфе Redis достаточно популярное решение, то выбор был предрешен.
Redis, упрощенно, это просто база данных с key-value и представляет собой инструмент для работы с данными оперативной памяти, что как раз таки для нас очень удобно.
Итак, мы решили использовать Redis для кеширования пользователя. Здесь все относительно просто:
Храним ключ, например, такой — v1-user::ed09b13963c8e2c585f6ad5db316d891.
Значение по сути будет повторять ответ выше.
При запуске каждого автотеста, мы проверяем есть ли такой пользователь в кэше и его используем. Тело запроса, которое попадает в микросервис при создании пользователя, кешируется в Redis, потом сравнивается — если в Redis такой хэш есть, Redis его отдаёт.
Если же пользователя нет, то мы просто его создаем по старым рельсам и кладем в Redis и при следующем запуске он у нас будет.
Мы очищаем кэш и работаем дальше, если что-то ломается, например, для пользователя создали три карты, а потом другой тестировщик заказал этому же пользователю дополнительную и всё путается. В целом, данные пользователей мы храним 40 дней, потом кэш также очищается.
Если по какой-то причине пользователя «кто то ломает», например, для пользователя создали три карты, а потом другой тестировщик заказал этому же пользователю дополнительную и всё путается, то мы очищаем кэш и работаем дальше. А с данным нехорошим человеком проводим разъяснительную беседу что так делать не стоит. В целом, данные пользователей мы храним 40 дней, потом кэш также очищается.
Красота.
С Redis время с 15-30 секунд сократилось до 300 мс. В результате мы уменьшили время прохождения автотестов примерно на 40 минут — с 4 часов до 3 часов 20 минут.
Вот так парой небольших доработок мы уменьшили время на проведение автотестов в разы . В дальнейшем планируем переписать все наши автотесты, где это возможно, с кэшем, и сократим время часов до двух.
Как вам доработка? Было ли полезно? Есть ли у вас что-то подобное?