【问题标题】:How to pass value between two scenarios in gatling?如何在加特林的两个场景之间传递价值?
【发布时间】:2017-03-27 15:07:23
【问题描述】:

我的脚本中有两个场景。我想将“CreateId”的值传递给第二个场景。我在第一个场景中保存了“CreateId”。

错误提示:

未定义名为“CreateId”的属性

jsonPath($.id).find(0).exists,一无所获

场景 - 1

val create = scenario("Create")
        .exec(http("post_request_create")
        .post("/api/asdf")
        .headers(headers_10)
        .body(StringBody(session =>s"""{"name": "${randomName()}"}""")).asJSON
        .check(jsonPath("$.id")
        .saveAs("CreateId"))
        )

场景 - 2

val addTerm = scenario("Add Term")
        .repeat (repeatCount){
        exec(http("Add")

        // NOT WORKING
            //.post("""/api/asdfg/${CreateId}/terms""")

        // NOT WORKING
            .post(session => "/api/asdfg/" + session.get("CreateId").asOption[String] + "/terms")

            .headers(headers_10)
            .body(StringBody(session =>s"""{...somedata...}"""))
            )
        }
val scn = List(create.inject(atOnceUsers(1)),addTerm.inject(nothingFor(10 seconds), atOnceUsers(userCount)))
setUp(scn).protocols(httpProtocol)      

【问题讨论】:

    标签: scala gatling


    【解决方案1】:

    用下面的代码试过了,效果很好。希望对其他人有所帮助。

    var CreateId = ""
    
    Scenario - 1
    
    val create = scenario("Create")
            .exec(http("post_request_create")
            .post("/api/asdf")
            .headers(headers_10)
            .body(StringBody(session =>s"""{"name": "${randomName()}"}""")).asJSON
            .check(jsonPath("$.id")
            .saveAs("CreateId"))
            )
    
            .exec(session => {
                CreateId = session("CreateId").as[String].trim
                println("%%%%%%%%%%% ID =====>>>>>>>>>> " + CreateId)     
                session}       
            )
    
    
    Scenario - 2
    
    val addTerm = scenario("Add Term")
        .exec(_.set("CreateId", CreateId)) // Set it here
           .repeat (repeatCount){
            exec(http("Add")
           .post("""/api/asdfg/${CreateId}/terms""")
           .headers(headers_10)
           .body(StringBody(session =>s"""{...somedata...}"""))
                )
            }
    val scn = List(create.inject(atOnceUsers(1)),addTerm.inject(nothingFor(10 seconds), atOnceUsers(userCount)))
    setUp(scn).protocols(httpProtocol)    
    

    【讨论】:

    • 您好@Peter,当您同时运行许多用户并且创建时间超过 10 秒时,这种方法如何工作?我有类似的情况,但由于第一个场景对我来说可能需要很长时间,所以有时在第二个场景开始时变量没有设置。
    • 嗨,Gery,对我来说,在上面的代码中,第二个场景很重要,我必须检查第二个调用的响应,所以我持有那个场景,直到我得到第一个场景的响应。您可以根据响应时间的计算增加时间限制,即(nothingFor(300 秒))。
    • 谢谢,这很有帮助。我对两个场景的要求不一样,但我想设置一个值并在一个场景中对同一用户的多个请求使用它。但是由于会话是不可变的,所以在发出下一个请求后我的值就消失了——因为新会话是根据最新的请求/响应编写的。需要将会话之外的值存储在一个变量中,以便在整个场景中使用它。
    【解决方案2】:

    我也遇到了同样的令牌问题,我需要从身份验证服务生成一个令牌并需要传递给其他 API。我按照以下步骤操作。希望这能解决您的问题。

    val create = scenario("Create")
            .exec(http("post_request_create")
            .post("/api/asdf")
            .headers(headers_10)
            .body(StringBody(session =>s"""{"name": "${randomName()}"}""")).asJSON
            .check(jsonPath("$.id")
            .saveAs("CreateId"))
            )
    

    然后我创建了

    val createId = exec(session => session.set("createdId", createdId));
    

    假设create 在不同的测试对象中。所以在调用类中创建了对象。

    val test = new Test()
    
    val addTerm = test.createId
        .exec(_.set("CreateId", CreateId)) // Set it here
           .repeat (repeatCount){
            exec(http("Add")
           .post("""/api/asdfg/${CreateId}/terms""")
           .headers(headers_10)
           .body(StringBody(session =>s"""{...somedata...}"""))
                )
            }
    
    val addTermScn = scenario("Add Term ").exec(addTerm)
    val testScn = scenario("create").excec(test.create)
    
    setUp(
    
        testScn.inject(atOnceUsers(1)),
        addTermScn.inject(nothingFor(5),rampUsers(vUsers) during (rampUp seconds)),
        //orderLookup.inject(nothingFor(5),rampUsers(vUsers) during (rampUp seconds))
      ).throttle(
        reachRps(tps) in (rampUp second),
        holdFor(duration minutes)
      ).protocols(httpProtocol)
    

    【讨论】:

      【解决方案3】:

      我有一个易于使用的通用解决方案。有几个步骤如何做到这一点。

      创建从一个场景获取所有会话变量的方法和设置此变量的另一种方法:

      import scala.collection.mutable.{Map => MutableMap}
      
      def passAnotherSession(currentSession: Session)(implicit transferVariable: MutableMap[String, Any]) = {
          currentSession.setAll(transferVariable)
        }
      
        def saveSessionToVariable(currentSession: Session)(implicit transferVariable: MutableMap[String, Any]) = {
          val systemKeys = List("gatling.http.ssl.sslContexts", "gatling.http.cache.contentCache", "gatling.http.cache.dns")
          transferVariable ++= currentSession.removeAll(systemKeys: _*).attributes
          currentSession
        }
      

      我在我的抽象基类中定义了上述方法,该基类在所有模拟/场景类中都被继承。


      然后在我的模拟/场景类中,我为存储会话变量定义了可变映射(通过隐式):

      import scala.collection.mutable.{Map => MutableMap}
      
      implicit val setUpSession: MutableMap[String, Any] = MutableMap()
      

      现在让我们开始使用这些方法。 以下是获取所需变量的场景示例:

      val setUpScenario = scenario(...)
      .exec(...) // some action with save desired variable 
      .exec(saveSessionToVariable(_)) // this save all session variables to above defined implicit map
      

      而这已经是一个需要变量的场景了:

      val mainScenario = scenario(...)
      .exec(passAnotherSession(_))    // get variable from setUpScenario
      .exec(...)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多