当前位置: 首页 > 知识库问答 >
问题:

Gatling exec块和会话变量

宰父君昊
2023-03-14

我有多个Gatling模拟,我正试图以一种重用低级调用(即HTTP调用)的方式构建它们,同时构建不同的场景。因此,我有以下结构(为了解释当前状态,使用了echo函数):

// 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 }
    ...
}

在上面提供的测试模拟中,我们从文件中提供数据并选择我们作为Map存储到会话中的属性子集。如果在文件中找到此类属性,我们会在提交回显请求时将它们添加为表单参数。否则我们不会。在这两种情况下,我们都存储了响应正文并将其打印出来。这很好。

当我试图将映射作为参数传递给echo()时,问题就开始了。假设我有以下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 }

请求没有触发,我得到了以下关于字符串丢失的错误

[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接受一个表达式[Map[String,Any]],并使用一个普通的exec块(即,不使用注入会话的块)。在这种情况下,我无法从会议中获得实际的地图!

bodyString似乎只在使用exec()而不是exec{session时可用=

我觉得我错过了一些非常基本的东西。任何帮助都将不胜感激。

更新#1

根据到目前为止收到的评论,据我所知,使用exec(sessionFunction:Expression[Session])函数在运行时创建ActionBuilder,因此它们不会被使用(它们只是被创建和丢弃)。

为了在场景中保留所有检查,同时在不同的函数上保留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?

一般来说,是否有一种首选模式/方法将参数传递给从场景中返回HttpRequestBuilders的函数?例如,如果我有另一个函数,该函数将Int作为参数,并使用要发送的请求中的数字创建一个HTTP请求,我将如何执行此操作?

共有1个答案

颜云瀚
2023-03-14

在您的示例中,echo正在返回一个HttpRequest estBuilder。gatling的工作方式是,构建器都应该在启动时构建,然后用于发出请求,因此当您将其包含在会话函数中时,构建器会在执行期间创建,但永远不会实际执行,并返回未更改的会话。

为了实现这一点,您必须将echo移出会话功能。正如您所意识到的,您可能需要更改方法签名以接受某种表达式

 类似资料:
  • 问题内容: 如果我在flask中具有全局变量,并且有多个用户一次访问该站点,那么一个人会话可以覆盖另一个人会话的全局变量,还是在用户每次请求烧瓶时,flask都会创建我的站点和程序代码的唯一实例浏览器? 问题答案: 一般来说,全局变量在请求之间共享。 某些WSGI服务器可以为每个请求使用新的单独流程,但这不是扩展请求的有效方法。大多数将使用踩踏或几个子进程来分散负载,但是即使在单独的子进程的情况下

  • 问题内容: 我刚刚完成了在PHP中创建整个登录和注册systsem的操作,但是我的问题是我还没有使用任何会话。我是PHP的新手,以前从未使用过会话。我想做的是,在用户注册并填写登录表单后,他们仍将停留在同一页面上。因此,其中一部分将是会话已登录,另一部分将是其他(用户未登录,请显示登录表单)。谁能告诉我如何开始? 问题答案: 希望这可以帮助 :) 开始会话,您需要在页面顶部或在调用会话代码之前说出

  • 问题内容: 我在Sun的“ Core Servlets and JavaServer Pages vol 2”中看到了带有会话计数器的示例。 计数器仅仅是建立在和递增/递减会话数与/ : 侦听器在上下文中注册自身,因此可以访问它并获取计数器值。 没有同步块。 安全,不是吗? 可以缓存在CPU寄存器中,并且对于使用? 问题答案: Servlet 3.0的规范规定(第11.5节): 侦听器实例和线程

  • 问题内容: 我需要通过过滤器访问会话变量。我什至不知道是否可能。实际上,问题在于实现的方法类型是,而HttpServlet继承了类,而doPost方法的参数是HttpServletRequest。 我可以在ServletRequest的过滤器中访问会话吗? 我应该那样做吗? 你能推荐我什么? 谢谢! 问题答案: 只需将获得的内容转换为即可。

  • 问题内容: 我正在使用快速框架。我想从socket.io访问会话数据。我尝试使用client.listener.server.dynamicViewHelpers数据来表达dynamicHelpers,但无法获取会话数据。有没有简单的方法可以做到这一点?请看代码 问题答案: 这不适用于通过flashsocket传输的套接字(它不会向服务器发送所需的cookie),但可以可靠地用于其他所有事务。我只

  • 问题内容: 是否可以在PHP中使数组成为会话变量? 情况是,我有一个表(第1页),其中有些单元格具有指向特定页面的链接。下一页将列出名称(第2页,我想保留在会话数组中)及其相应的复选框。提交此表单后,它将进入一个交易页面(第3页,其中已发布复选框的值保存在数据库中以用于对应名称)。现在,如果我返回首页并单击另一个单元格,则会话数组将包含新名称列表还是旧名称列表? 问题答案: 是的,PHP支持将数组