У меня есть несколько симуляций Gatling, которые я пытаюсь структурировать таким образом, чтобы повторно использовать низкоуровневые вызовы (например, HTTP-вызовы) при построении различных сценариев. По этой причине у меня есть следующая структура (функция эха используется для объяснения текущего состояния):
// File UserAction.scala contains all low-level actions like load a specific page, login, logout etc. All functions return HttpRequestBuilder so that each simulation can perform its own set of checks on the responses.
object UserAction {
...
def echo(): HttpRequestBuilder = {
http("Postman Echo Service Call")
.get("https://postman-echo.com/get")
.headers(headers("headers_0"))
}
...
}
// File TestSimulation.scala
class TestSimulation extends ParameterizedSimulation {
private val accountFeeder = csv("data/accounts.csv")
private val testScenario = scenario("Test Simulation")
.feed(accountFeeder)
.exec { session =>
session.set("attributes", session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
}
.doIfOrElse(session => session("schema_attributes").as[Map[String, String]].isEmpty) {
exec(
echo()
.check(bodyString.saveAs("responseBody"))
)
} {
exec(
echo()
.formParamMap("${schema_attributes}")
.check(bodyString.saveAs("responseBody"))
)
}
.exec { session => println(session("responseBody").as[String]); session }
...
}
В приведенном выше тестовом моделировании мы загружаем данные из файла и выбираем подмножество атрибутов, которые сохраняем в виде карты в сеансе. Если такие атрибуты обнаруживаются в файле, мы добавляем их в качестве параметров формы при отправке эхо-запроса. В противном случае мы этого не сделаем. В обоих случаях мы сохраняем тело ответа и также печатаем его. Это нормально работает.
Когда я пытаюсь передать карту в качестве параметра функции echo (), возникают проблемы. Предположим, у меня есть следующая реализация эха:
def echo(extraParameters: Map[String, Any]): HttpRequestBuilder = {
val request = http("Postman Echo Service Call")
.get("https://postman-echo.com/get")
.headers(headers("headers_0"))
if (extraParameters.nonEmpty) {
request.formParamMap(extraParameters)
}
request
}
и что симуляция делает следующее:
.exec { session =>
session.set("schema_attributes", session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
}
.exec { session =>
echo(session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
.check(bodyString.saveAs("responseBody"))
session
}
.exec { session => println(session("responseBody").as[String]); session }
Запросы не срабатывают, и я получаю следующую ошибку о том, что bodyString отсутствует.
[ERROR] i.g.c.a.b.SessionHookBuilder$$anon$1 - 'hook-1' crashed with 'j.u.NoSuchElementException: No attribute named 'responseBody' is defined', forwarding to the next one
Альтернативой, которую я пробовал, было заставить echo принимать Expression[Map[String, Any]]
и использовать обычный блок exec (т.е. не тот, у которого был введен сеанс). В этом случае я не мог получить фактическую карту из сеанса!
Кажется, что bodyString доступна только при использовании exec (), а не exec {session => ...; session} форма. У меня очень мало знаний о Scala, что только усугубляет мое замешательство.
Я чувствую, что упускаю в этом что-то очень важное. Любая помощь будет принята с благодарностью.
ОБНОВЛЕНИЕ №1
На основании полученных комментариев, насколько я понимаю, использование функции exec(sessionFunction: Expression[Session])
создает ActionBuilders во время выполнения, поэтому они не используются (они просто создаются и удаляются).
В попытке сохранить все проверки внутри сценария, сохраняя определение HTTP-запросов для другой функции, я попробовал следующую альтернативу:
def echo(): HttpRequestBuilder = {
http("Postman Echo Service Call")
.get("https://postman-echo.com/get")
.headers(headers("headers_0"))
.formParamMap("${schema_attributes}")
}
// Used as
.feed(myFeeder)
.exec { session => session.set("schemaAttributes", session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
}
.exec(
echo()
.check(bodyString.saveAs("responseBody"))
)
Таким образом, у меня проблема в том, что если карта пуста (т.е. информация отсутствует в файле) formParamMap
не будет работать. Есть ли способ при желании добавить formParamMap, если карта действительно содержит данные?
В общем, существует ли предпочтительный шаблон / метод для передачи параметров функциям, которые возвращают HttpRequestBuilder
s из сценария? Например, если у меня есть другая функция, которая принимает в качестве параметра Int и создает HTTP-запрос с номером в отправляемом запросе, как я могу это сделать?
ActionBuilder
s. - person George Leung   schedule 13.02.2020exec { session => ...; session }
не из таких. Только функцияexec(actionBuilder: ActionBuilder)
будет выполнять действия, определенные моими строителями. Я правильно понял? :) В очередной раз благодарим за помощь. - person George E. Kallergis   schedule 14.02.2020