Сделать сервис автоматического создания пользователей и прикрутить 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 минут.

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

Как вам доработка? Было ли полезно? Есть ли у вас что-то подобное? 


Комментарии (11)


  1. Litovsky83
    17.11.2023 13:13

    Добрый день! Я правильно понимаю, что для тестов вы используете только Postman, без авто ?


    1. ksantd Автор
      17.11.2023 13:13

      Добрый. Авто есть на 3 разных уровнях. В авто тестах так же используем апи для создания пользователей. Собственно кеширование и задумывалось для автотестов.


      1. Litovsky83
        17.11.2023 13:13
        +1

        Я тогда не совсем понял, какую задачу вы решали (

        Раньше на каждый чих вы создавали нового пользователя и это было долго. Поэтому вы переиспользуете старых пользователей, которые "чистые" и их можно брать для тестов ?


        1. ksantd Автор
          17.11.2023 13:13

          Если подытожить, то раньше на создание уходило 15 и более секунд. Сейчас если тест дергает ручку GET 100 миллисекунд на создание. Профит я думаю вполне понятен.


  1. whoisking
    17.11.2023 13:13

    Если данные в кэше хранятся аж 40 дней, то отсюда вытекает, что формат данных пользователей меняется не часто, так почему тогда из на своей стороне не замокать? Не написать генератор пользователей с фейкером?


    1. ksantd Автор
      17.11.2023 13:13

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


  1. iBljad
    17.11.2023 13:13

    Я запутался в цифрах:

    как в разы уменьшить время прохождения автотестов

    создание пользователей занимает часов 8

    уменьшили ... на 40 минут — с 4 часов до 3 часов 20 минут

    Или 8 часов это в сумме и вы запускаете тесты в... 12 параллельных потоков?


  1. dyadyaSerezha
    17.11.2023 13:13

    1) Нвши автотесты, оказывается, были не совсем авто и требовали ручных шагов, и это было долго. Вау, кто бы мог подумать! Прям неожиданно как-то.

    2) Примерно через полсекунды после прочтения истории про создание нового клиента для каждого теста мне пришла мысль про возможное переиспользование. Но оказывается, это тоже было "вау, оказывается!"

    3) Непонятно, зачем нужен кэш, ведь должен быть стандартный механизм типа "найти клиента по id". Хотя кэш, конечно, и тут быстрее, но про стандартный способ автор ничего не написал, и как уже написал автор, кэш не отражает любые изменения клиента.

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

    5) Идут ли какие-то тесты параллельно? Это же самый общий способ ускорить процесс.


    1. iBljad
      17.11.2023 13:13

      Перефразируя известное изречение, все быстрые тесты быстры одинаково, все медленные — медлены по-своему :)

      И, соответственно, многие истории ускорения — зачастую не универсальный совет другим, а отчёт о работе над ошибками, иногда полезным и коллегам по цеху (хотя бывают и исключения: 2 последние статьи про оптимизации прогонов от wrike мне показались интересными)


  1. kentastik
    17.11.2023 13:13
    +1

    а почему не пойти дальше не создавать в ci пользователей на этапе деплоя сервиса. еще можно держать копию бд которая на начало дня содержит 1000 созданных юзеров, которые расходуются на тесты, а ночью накатывается новая база. ну и еще я не верю что для 1000 тестов надо создавать пользователя, почти наверняка хватит меньше десятка на все кейсы.


    1. ksantd Автор
      17.11.2023 13:13

      Одной единой базы которая отвечала бы за все - нет. Просто мое предположении что общее число баз 350+, а скорее всего сильно больше.
      Эм, а про 10 пользователей, только на мою одну команду надо около 8 уникальных. Не считая каких то стандартных.