Инфраструктура для end-2-end тестирования

Влад Мухаматнуров

О себе

План

Функциональное тестирование приложения:

      1. Тестирование REST-приложения

      2. Стабы для тестирования

      3. Архитектура сложного сервиса

Сквозное тестирование приложения:

      4. Определение сквозного тестирования

      5. Способы создания сквозных тестов

      6. Примеры тест-кейсов

Инфраструктура сквозного тестирования

      7. Подходы к тестированию сборки

      8. Тестирование на основе контейнеров

      9. Использование docker-compose

Подведение итогов

Функциональное тестирование

1. Тестирование REST-приложения

Приложение

Архитектура REST

Архитектура

Сервис 1

Сервис 2

Сервис 3

Сервис

2.1

Сервис

2.2

Сервис

2.3

Цель

Функциональное тестирование на основе бизнес-сценариев

Вопрос

Каков объект тестирования?

ЧТО мы хотим протестировать?

Объект тестирования

Сервис 1

Сервис 2

Сервис 3

Сервис

2.1

Сервис

2.2

Сервис

2.3

Следующий вопрос

Подход к тестированию

КАК мы хотим протестировать?

Схема тестирования

Входное воздействие

Сервис

Другой

сервис

Сервис

2.1

Сервис

2.2

Сервис

2.3

Результат воздействия

Проблемы

связанные с соседними сервисами:

  • они могут быть не доступны;
  • они могут быть другой версии.

Как протестировать

только конкретный сервис?

Схема тестирования

Входное воздействие

Сервис

Другой

сервис

Сервис

2.1

Сервис

2.2

Сервис

2.3

Результат воздействия

Вопрос

Почему бы не сделать стабы вместо сервисов?

Функциональное тестирование

2. Стабы для тестирования

Схема тестирования

Входное воздействие

Сервис

Стаб

Стаб

Результат воздействия

Стаб

Стаб

Обратная сторона

Не тестируется взаимодействие с важными компонентами системы

Мнение

Компромисс между:

  • тем, что можно зафиксировать - 1 тип;
  • тем, что нельзя зафиксировать - 2 тип.

Сервис 1-го типа:

  • не определяет поведение системы;
  • не реализуют бизнес-логику;
  • имеет простую структуру API.

Сервис 2-го типа:

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

Схема тестирования

Входное воздействие

Сервис

Другой

сервис

Сервис

2.1

Сервис

2.2

Сервис

2.3

Результат воздействия

Функциональное тестирование

3. Архитектура сложного сервиса

Сложный сервис

Набор из разных сервисов с единой API

Архитектура проекта

как набора сервисов

API

Сервис

А

Сервис

B

Внешние компоненты

Очередь

БД

API

Сервис A

Сервис B

Масштабирование

API 1

API 2

API N

...

СA 1

СA 2

...

CA M

СB 1

СB 2

...

CB Z

API:
N нод

Сервис А:

M нод

Сервис B:

Z нод

Масштабирование

Очередь

БД

API 1

API 2

API N

...

СA 1

СA 2

...

CA M

СB 1

СB 2

...

CB Z

Взаимодействие

Очередь

API 1

Балансирощвик

API 2

API N

...

СA 1

СA 2

...

CA M

СB 1

СB 2

...

CB Z

БД

Тестирование

Схема тестирования

Входное воздействие

Другой

сервис

Стаб

Стаб

Сервис

2.3

Результат воздействия

Сервис

Сервис в кластере

Сервис

=

Протестировать приложение

  • подобно реальной эксплуатации

  • только с необходимым количеством нод

Сквозное тестирование

4. Определение

End-2-End тестирование

Сквозное тестирование

  • Проверка функциональности приложения
  • На минимальном количестве сервисов
  • Для осуществления бизнес-сценариев
  • И получения результатов их выполнения

Схема сквозного тестирования

Входное воздействие

Другой

сервис

Стаб

Стаб

Сервис

2.3

Результат воздействия

Важно!

Сквозное тестирование

  • Не отменяет потребности в
    остальных видах тестирования;
  • Имеет смысл только при прочном
    фундаменте из предваряющих этапов;
  • Это "верхушка" пирамиды тестирования.

Сквозное тестирование

Сквозное тестирование характеризуется

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

Для реализации сквозного тестирования требуется

  • Продуманная инфраструктура для тестирования
    из подготовленных к процессу сервисов
    (версионирование, состояние, доступность)
     
  • Инструмент для тестирования и анализа
    (формат данных, оценка результатов, мониторинг)

Бонус сквозного тестирования

Сквозные тест-кейсы

единетичны для тестирования на кластере

Какими бывают эти...

сквозные тест-кейсы?

Сквозное тестирование

5. Способы создания сквозных тестов

Тест-кейсы могут быть созданы

  1. При помощи кода
  2. При помощи DSL

Сквозные тест-кейсы, написанные в коде

  • Быстро создать
  • Сложно поддерживать
  • Непонятны никому, кроме вас
  • Подходят для маленьких проектов

Если у вас серьезный проект

Сквозные тест-кейсы

должны описываться просто и понятно, в т.ч. для бизнеса

Сквозные тест кейсы

должны описываться на специально подготовленном языке - DSL

Digital Subscriber Line

Domain-Specific Language

язык, специфический для предметной области

Примеры

  • TeX / LaTeX
  • SQL
  • HTML
  • YAML
  • ...
  • Tcl/Tk

Сквозное тестирование

6. Примеры тест-кейсов

Существуют фреймворки

для создания и эксплуатации сквозных тестов

Как может выглядеть

тест-кейс

Пример

Фреймворк Tavern, на основе pytest

test_name: Тест API

marks:
  - end2end
  usefixtures:
    - x_trace_id
    - host

stages:
  - name: Входное воздействие #1

    request:
      headers:
        X-TRACE-ID: '{x_trace_id}'
      json:
        param1: value1
        param2: value2
      method: POST
      url: '{host}/my_handler1'

    response:
      status_code: 200
      body:
        result: 'Success'

Пример

Много этапов

test_name: Многоэтапный тест

stages:
  - name: Входное воздействие #1
    request:
    	...
    response:
    	...
  - name: Входное воздействие #2
    request:
    	...
    response:
    	...
  ...
  - name: Входное воздействие #N
    request:
    	...
    response:
    	...

Пример

SetUp / TearDown

from my_utils import (
  generate_x_trace_id,
  prepare_state,
  clear_state,
)
from my_settings import APISettings


@pytest.fixture(scope="session")
def host() -> str:
    return APISettings.url
  
  
@pytest.fixture(scope="function")
def magic_fixture(host) -> None:
  prepare_state(host)
  yield
  clear_state(host)
test_name: Тест

marks:
  - end2end
  usefixtures:
    - host
    - magic_fixture

stages:
  - name: Входное воздействие
	...
  - name: Проверка результата
    ...

Возможно,

функциональности фреймворков недостаточно

Решение

собственный DSL

(фреймворк для имплементации шаблонов)

Пример тест-кейса

Фреймворк pytest_bdd, на основе pytest

Сценарий: Перевод денег по номеру телефона на Тинькофф

  Когда я пишу "переведи деньги Саше"
  То бот отвечает текстом "Сколько переводим?"
  И бот показывает подсказки $HINTS(100₽; 200₽; 300₽; 500₽; 1000₽; 2000₽; 5000₽)$

  Когда я выбираю подсказку 1
  То бот показывает виджет $WIDGET(buttons=Отменить;Перевести)$
  И бот показывает подсказки $HINTS(Другая сумма; Другому человеку; На Сбербанк)$

  Когда я нажимаю кнопку виджета "Перевести"
  То бот отвечает текстом "Деньги отправлены"

Проблемы

  • Решение нужно разработать
  • Решение нужно поддерживать
  • Решением необходимо
    научить пользоваться
  • Решение необходимо
    встроить в инфраструктуру
  • Решение должно предоставлять
    удобные для анализа отчеты

С другой стороны

это позволяет вам гибко работать с вашим приложением и получать расширенную аналитику

Инфраструктура сквозного тестирования

7. Подходы к тестированию сборки

Хочется

тестировать каждую версию приложения

Версия приложения

соответствует какой-то конкретной сборке

Тестирование сборки

  • проверка приложения
  • фиксированной версии
  • на соответствие критериям качества
  • согласно определенным
    этапам тестирования

Тестирование сборки

API

Сервис A

Сервис B

Очередь

БД

ver 1.23

ver 1.23

ver 1.23

Как протестировать сборку сквозными тестами?

2 подхода

  1. Доставка очередной версии приложения

    на тестовый контур

  2. Развертывание очередной версии приложения при помощи агента и контейнеров

1. Доставка

очередной версии приложения

на тестовый контур

(автоматическая)

Плюсы

  • Приближенно к проду
  • Не используются стабы
  • Единоразово (условно) настроены:
    • системы отладки и мониторинга
    • интеграция с другими системами

Минусы

  • Нужно возвращать в
    начальное состояние

    (нужно определить понятие
    начального состояния)
  • Проблемы с сетью
  • Контур может быть занят

Вам подходит

 доставка на тестовый контур, если...

Если

  • у вас большое количество
    не пересекающихся контуров
  • вам легко производить
    SetUp и TearDown 

Как правило

  • ресурсы разработки ограничены,
  • приложение является звеном в цепи
    большого количества сервисов
  • и необходимо гарантировать его
    доступность для других (препрод),
  • а тестовый контур является
    площадкой для тестирования
    отдельно взятых фич и фиксов

Поэтому, круто

определенным образом гарантировать

до раскатки кода на тестовый контур,

что оно корректно выполняет свои основные бизнес-функции

Кажется, что...

приложение необходимо развернуть  в отдельной сети на основе контейнеров

2. Развертывание приложения

на основе контейнеров

Преимущества

  • Можно развернуть в любой момент
  • Приложение фиксированной версии
  • Настроить необходимое окружение
  • Выполнить тестирование сборки
  • Не изменяя инфраструктуру контуров
  • Легко интегрировать в CI / CD

Минусы

  • Используются стабы
  • Относительно сложно производить
    отладку и мониторинг
  • Используются ресурсы общего
    пула агентов CI / CD

Сквозное тестирование

сборок на подготовленной инфраструктуре:

  • ускоряет выявление проблем
    в основных бизнес-сценариях
  • экономит человеческие и
    временные ресурсы
  • является частью общего
    регресса приложения и
  • позволяет гарантировать
    работоспособность сервисов

Отлично!

Подготовим инфраструктуру

Инфраструктура сквозного тестирования

8. Тестирование на основе контейнеров

Тестирование

при помощи docker

Сборка приложения

для тестирования

Контейнер с приложением

Сборка приложения

  • Базовый образ приложения
  • Образ приложения с кодом

Можно тестировать!

А как запускать тесты?

Решение

запуск shell-скриптом в CI

Проблемы

  • Неконсистентность скрипта
  • Разрозненность данных

Решение

подготовка контейнера с инструментом для тестирования

Сборка приложения

  • Базовый образ приложения
  • Образ приложения с кодом
  • Базовый образ инструмента тестирования
  • Образ инструмента тестирования с тестами

Плюсы реализации

  • Консистентность сборок
  • Унифицированный шаблон
  • Возможность развертывания и
    тестирования с использованием
    docker-compose
  • Минимизация сетевых проблем
  • Обработка и отправка данных
    в системы мониторинга

Инфраструктура сквозного тестирования

9. Использование docker-compose

Инфраструктура для тестирования

с docker-compose

Развертывание приложения

  • Сборка базового образа приложения
  • Сборка образа приложения с кодом
  • Разрешение необходимых зависимостей
    (включение соответствующих сервисов)
  • Подготовка рабочего окружения
  • Запуск всех частей приложения

Базовый образ

services:
  base:
    image: "app/app-base:${CONTENT_HASH}"
    build:
      context: .
      dockerfile: docker/base.dockerfile
      network: host

Образ приложения

services:
  ...
  base:
    image: "app/app-code:${BUILD_NUMBER}"
    build:
      context: .
      dockerfile: docker/code.dockerfile
      network: host
      args:
        BUILD_NUMBER: "${BUILD_NUMBER}"

Сервис API

services:
  ...
  api:
    image: "app/app-code:${BUILD_NUMBER}"
    command: "/bin/api"
    volumes:
      - ./volume:/code/folder
    environment:
      - VAR1=${VAR1:-unset}
      - VAR2=${VAR2:-unset}
      - VAR3=${VAR3:-unset}
    env_file:
      - docker/environments/${ENV:-unset}.env
    ports:
      - 8765:8765
    depends_on:
      - db
      - redis
      - kafka

Сервисы A, B.., N

services:
  ...
  service_N:
    image: "app/app-code:${BUILD_NUMBER}"
    command: "/bin/service_N"
    volumes:
      - ./volume_N:/code/folder_N
    environment:
      - VAR_N1=${VAR_N1:-unset}
      - VAR_N2=${VAR_N2:-unset}
      - VAR_N3=${VAR_N3:-unset}
    env_file:
      - docker/environments/${ENV:-unset}.env
    ports:
      - 8760:8760
    depends_on:
      - api

docker-compose up

Развернутое приложение

API

Сервис A

Сервис B

Очередь

БД

ver 1.23

ver 1.23

ver 1.23

Стабы

  • развернутые в сети сервисы
  • развернутые через docker-compose
    собранные контейнеры

Стабы, развернутые для сборки

  • Обеспечивают консистентность
  • Доступны только для
    текущего оркестра контейнеров

Стабы

services:
  ...
  stub_N:
    image: "app/app-stubs:${BUILD_NUMBER}"
    command: "/bin/stub_N"
    environment:
      - VAR_N1=${VAR_N1:-unset}
      - VAR_N2=${VAR_N2:-unset}
      - VAR_N3=${VAR_N3:-unset}
    env_file:
      - docker/environments/${ENV:-unset}.env
    ports:
      - 5005:5005
    depends_on:
      - api
      - service_A
      - service_B

Актуализировать окружение

указать URL стабов для сервисов приложения

Оркестрация контейнеров

API

Сервис A

Сервис B

Очередь

БД

ver 1.23

ver 1.23

ver 1.23

Стабы

Контейнер

инструмента тестирования

Базовый образ

services:
  test-base:
    image: "app/test-base:${CONTENT_HASH}"
    build:
      context: .
      dockerfile: docker/test-base.dockerfile
      network: host

Образ инструмента тестирования

services:
  ...
  test-tool:
    image: "app/test-tool:${BUILD_NUMBER}"
    build:
      context: .
      dockerfile: docker/test-tool.dockerfile
      network: host
      args:
        BUILD_NUMBER: "${BUILD_NUMBER}"
    volumes:
      - .${ALLUREDIR:-/allure-results}:${ALLUREDIR:-/allure-results}
    env_file:
      - docker/environments/${ENV:-unset}.env
    depends_on:
      - test-base
      - stubs

Оркестрация контейнеров

Очередь

БД

ver 1.23

ver 1.23

ver 1.23

Стабы

Сервис A

Сервис B

API

Test

tool

ver 1.23

Пример инфраструктуры для тестирования

Другой

сервис

Сервис

2.3

Итоги

  • Подготовлены сквозные тесты
  • Подготовлена инфраструктура
    для тестирования сборок

Это позволяет

  • в рамках процесса CI / CD
  • реализовать последовательные:
    • сборку;
    • тестирование;
  • локализовать критические проблемы
  • при выполнении бизнес-сценариев
  • и предоставить отчет по результатам,
  • чтобы быть готовым к очередному

релизу

Презентация

End-2-end testing infrastructure

By Vladislav Mukhamatnurov

End-2-end testing infrastructure

  • 280