Scenario generator / HTTP

Scenario generator / HTTP

Конфигурация

Вам необходимо использовать генератор и провайдер типа http/scenario

pools:
  - id: Pool name
    gun:
      type: http/scenario
      target: localhost:80
    ammo:
      type: http/scenario
      file: payload.hcl

Генератор

Минимальная конфигурация генератора выглядит так

gun:
  type: http/scenario
  target: localhost:80

Так же есть type: http2/scenario генератор

gun:
  type: http2/scenario
  target: localhost:80

Для сценарного генератора поддерживаются все настройки обычного HTTP генератора

Провайдер

Провайдер принимает всего один параметр - путь до файла с описанием сценария

ammo:
  type: http/scenario
  file: payload.hcl

Поддерживает файлы расширений

  • hcl
  • yaml
  • json

Описание формата сценариев

Поддерживает форматы

  • hcl
  • yaml
  • json

Общий принцип

В одном файле можно описывать несколько сценариев. У сценария есть имя по которому один сценарий отличается от другого.

Сценарий - это последовательность запросов. То есть вам потребуется описать в сценарии какие запросы в каком порядке должны выполняться.

Запрос - HTTP запрос. Имеет стандартные поля HTTP запроса плюс дополнительные. См Requests.

HCL пример

locals {
  common_headers = {
    Content-Type  = "application/json"
    Useragent     = "Yandex"
  }
  next = "next"
}
locals {
  auth_headers = merge(local.common_headers, {
    Authorization = "Bearer {{.request.auth_req.postprocessor.token}}"
  })
  next = "next"
}
variable_source "source_name" "file/csv" {
  file              = "file.csv"
  fields            = ["id", "name"]
  ignore_first_line = true
  delimiter         = ","
}

request "request_name" {
  method  = "POST"
  uri     = "/uri"
  headers = merge(local.common_headers, {
    Authorization = "Bearer {{.request.auth_req.postprocessor.token}}"
  })
  tag       = "tag"
  body      = <<EOF
<body/>
EOF

  templater {
    type = "text"
  }

  preprocessor {
    mapping = {
      new_var = "source.var_name[next].0"
    }
  }
  postprocessor "var/jsonpath" {
    mapping = {
      new_var = "$.auth_key"
    }
  }
}


scenario "scenario_name" {
  weight           = 1
  min_waiting_time = 1000
  requests         = [
    "request_name",
  ]
}

Так же пример можно посмотреть в тестах https://github.com/yandex/pandora/blob/dev/tests/grpc_scenario/testdata/grpc_payload.hcl

YAML пример

locals:
  my-headers: &global-headers
    Content-Type: application/json
    Useragent: Yandex
variable_sources:
  - type: "file/csv"
    name: "source_name"
    ignore_first_line: true
    delimiter: ","
    file: "file.csv"
    fields: [ "id", "name" ]

requests:
  - name: "request_name"
    uri: '/uri'
    method: POST
    headers:
      <<: *global-headers
    tag: tag
    body: '<body/>'
    preprocessor:
      mapping:
        new_var: source.var_name[next].0
    templater:
      type: text
    postprocessors:
      - type: var/jsonpath
        mapping:
          token: "$.auth_key"

scenarios:
  - name: scenario_name
    weight: 1
    min_waiting_time: 1000
    requests: [
      request_name
    ]

Locals

Про блок locals смотрите в отдельной статье Locals

Возможности

Запросы

Поля

  • method
  • uri
  • headers
  • body
  • name
  • tag
  • templater
  • preprocessors
  • postprocessors

Шаблонизатор

Поля uri, headers, body шаблонризируются.

Используется стандартный go template.

Имена переменных в шаблонах

Имена переменных имеют полный путь их определения.

Например

Переменная users из источника user_file - {% raw %}{{.source.user_file.users}}{% endraw %}

Переменная item из препроцессора запроса list_req - {% raw %}{{.request.list_req.preprocessor.item}}{% endraw %}

Переменная token из постпроцессора запроса list_req - {% raw %}{{.request.list_req.postprocessor.token}}{% endraw %}

Функции в шаблонах

Так как используется стандартные шаблонизатор Го в нем можно использовать встроенные функции https://pkg.go.dev/text/template#hdr-Functions

А так же некоторые функции

  • randInt
  • randString
  • uuid

Подробнее про функции рандомизации см в документации

Preprocessors

Препроцессор - действия выполняются перед шаблонизацией

Используется для нового маппинга переменных

У препроцессора есть возможность работать с массивами с помощью модификаторов

  • next
  • last
  • rand
yaml
requests:
  - name: req_name
    ...
    preprocessor:
      mapping:
        user_id: source.users[next].id
hcl
request "req_name" {
  preprocessor {
    mapping = {
      user_id = "source.users[next].id"
    }
  }
}

Так же в препроцессоре есть возможность создавать переменные с использованием функций рандомизации

  • randInt()
  • randString()
  • uuid()

Подробнее про функции рандомизации см в документации

Postprocessors

var/jsonpath

Пример hcl

request "your_request_name" {
  postprocessor "var/jsonpath" {
    mapping = {
      token = "$.auth_key"
    }
  }
}
var/xpath
request "your_request_name" {
  postprocessor "var/xpath" {
    mapping = {
      data = "//div[@class='data']"
    }
  }
}
var/header

Создает новую переменную из заголовков ответа.

Есть возможность через pipe указывать простейшие строковые манипуляции.

Модификаторы:

  • lower
  • upper
  • substr(from, length) - где length - опционально
  • replace(search, replace)

Модификаторы можно выстраивать в цепочку.

Пример:

Если вам приходит ответ с заголовками

X-Trace-ID: we1fswe284awsfewf
Authorization: Basic Ym9zY236Ym9zY28= 

И вам требуется сохранить для дальнейшего использования traceID=we1fswe284awsfewf & auth=ym9zy236ym9zy28 вы можете использовать постпроцессор с модификаторами

request "your_request_name" {
  postprocessor "var/header" {
    mapping = {
      traceID = "X-Trace-ID"
      auth    = "Authorization|lower|replace(=,)|substr(6)"
    }
  }
}

В шаблонах вы можете использовать результать данного постпроцессора как

`{% raw %}{{.request.your_request_name.postprocessor.auth}}{% endraw %}`
`{% raw %}{{.request.your_request_name.postprocessor.traceID}}{% endraw %}`
assert/response

Проверяет значения заголовков и тела

Если матчинг не срабатывает, прекращает дальнейшее выполнение сценария

request "your_request_name" {
  postprocessor "assert/response" {
    headers = {
      "Content-Type" = "application/json"
    }
    body        = ["token"]
    status_code = 200

    size {
      val = 10000
      op  = ">"
    }
  }
}

Scenarios

Минимальные поля для сценария - имя и перечень запросов

scenario "scenario_name" {
  requests = [
    "list_req",
    "order_req",
    "order_req",
    "order_req"
  ]
}

Можно указать мултипликатор повторения запросов

scenario "scenario_name" {
  requests = [
    "list_req",
    "order_req(3)"
  ]
}

Можно указать задержку sleep(). Параметр в миллисекундах

scenario "scenario_name" {
  requests = [
    "list_req",
    "sleep(100)",
    "order_req(3)"
  ]
}

Вторым аргументом в запросы указывается sleep для запросов с мултипликаторами

scenario "scenario_name" {
  requests = [
    "list_req",
    "sleep(100)",
    "order_req(3, 100)"
  ]
}

Параметр min_waiting_time описывает минимальное время выполнения сценария. То есть будет добавлен sleep в конце всего сценария, если сценарий выполнится быстрее этого параметра.

scenario "scenario_name" {
  min_waiting_time = 1000
  requests         = [
    "list_req",
    "sleep(100)",
    "order_req(3, 100)"
  ]
}

В одном файле можно описывать множество сценариев

Параметр weight - вес распределения каждого сценария. Чем больше вес, тем чаще будет выполняться сценарий.

scenario "scenario_first" {
  weight   = 1
  requests = [
    "auth_req(1, 100)",
    "list_req(1, 100)",
    "order_req(3, 100)"
  ]
}

scenario "scenario_second" {
  weight   = 50
  requests = [
    "mainpage",
  ]
}

Sources

См документ - Источники переменных

Смотри так же