如何在Gatling负载测试中为多个虚拟用户使用单个OAuth2.0令牌

问题描述 投票:1回答:3

我需要通过Gatling加载测试需要OAuth2.0令牌的API(其中我是一个完整的新手!)但是希望每个虚拟用户使用相同的令牌。我正在检索令牌ok(我认为)并将其放入一个名为'access'的变量中,但是当测试本身启动时,我继续得到'没有名为'access'的属性。

我的令牌检索如下所示(以及下面使用的httpConf):

 class MySimulation extends Simulation {

 val httpConf = http        
    .baseUrl("https://MyBaseUrl.Com/")
    .acceptHeader("application/json") 
    .doNotTrackHeader("1")
    .acceptLanguageHeader("en-UK,en;q=0.5")
    .acceptEncodingHeader("gzip, deflate")
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0")
    .shareConnections

 val header = Map("Content-Type" -> """application/x-www-form-urlencoded""")

 al auth = scenario("Retrieve Token")
 .exec(http("POST OAuth Req")
 .post("https://SomeTokenUrl")
 .formParam("resource", "someresource")
 .formParam("grant_type", "somegranttype")
 .formParam("client_secret", "someclientsecret")
 .formParam("client_id", "someclientid")
 .headers(header).check(status.is(200)).check(jsonPath("$.access_token").find.saveAs("access"))) 

然后我尝试将负载测试设置为(注意:我最初放置'Map',而不是可变变体,但是在某处读取默认值是不可变的,并且想知道这是否是标头无法更新的原因):

 val headers_10 = scala.collection.mutable.Map("Content-Type" -> "application/json; charset=ISO-8859-1", "Authorization" -> "Bearer ${access}")

 val scn = scenario("MyService Gatling test run")       
           .exec(http("")               
           .post("Myservice/api")
           .headers(headers_10.toMap)                
           .body(StringBody("""{"SomeProperty": "Some Value"}"""))
           .asJson
           .check(status.is(200)))

 setUp(
    auth.inject(constantUsersPerSec(1) during (2 seconds)),
    scn.inject(nothingFor(2 seconds),
    constantUsersPerSec(10) during (10 seconds) 
    ).protocols(httpConf))
    .assertions(global.responseTime.max.lt(500)) 
    .assertions(forAll.failedRequests.percent.lte(1)) 
    .assertions(global.responseTime.mean.lte(100)) 

我们的想法是,在加载测试开始之前,令牌检索将完成,然后负载测试场景将使用“访问”变量,但它会给出以下结果:

  ERROR : Failed to build request: No attribute named 'access' is defined 

我已经到了我的系绳的尽头。我猜它可能与范围有关,也许变量不会延续到负载测试场景,但我看到其他地方的例子似乎建议完全设置,所以我不知道这些其他例子是否部分完整或是什么。

scala load-testing gatling gatling-jsonpath
3个回答
1
投票

会话是按用户进行的,用户之间不会共享会话数据。因此,当您有1个用户运行“auth”方案并保存令牌时,运行“scn”的是两个不同的用户,并且他们无权访问auth用户的会话值。

这不建议练习,但你可以通过将auth令牌推入常规scala var并在auth场景中设置它并在主场景中读取它来解决这个问题 - 你只需要确保auth总是在你注入之前完成其他用户。

var token: String = ""

然后在auth场景中,最后有一步如

.exec(session => {
    token = session("access").as[String]
    session
})

然后在scn场景的开头有一个设置会话变量的步骤

.exec(session.set("access", token))

我过去曾使用过这种模式,但它确实有用,但我确信有更好的方法可以做到


0
投票

我也在尝试这种情况,但是当我尝试在scn场景开始时添加.exec {session => {token = session(“access”)。作为[String] session}}时,我收到错误。

       val scn = scenario("MyService Gatling test run")
       .exec{session => { token = session("access").as[String] session}}  
      .exec(http("")               
       .post("Myservice/api")
       .headers(headers_10.toMap)                
       .body(StringBody("""{"SomeProperty": "Some Value"}"""))
       .asJson
       .check(status.is(200)))

我还尝试分别在下面的步骤进行更改: -

  setUp(auth.inject(constantUsersPerSec(1) during (2 seconds)),
  .exec{session => { token = session("access").as[String] session}}
  scn.inject(nothingFor(2 seconds),
  constantUsersPerSec(10) during (10 seconds) 
  ).protocols(httpConf))
  .assertions(global.responseTime.max.lt(500)) 
  .assertions(forAll.failedRequests.percent.lte(1)) 
  .assertions(global.responseTime.mean.lte(100)) 

但他们都没有工作。你能告诉我我应该把这段代码放到哪里。


0
投票

@ Young,

当我这样做时,我在我的场景中使用了'exec'而不是设置,并使用了以下语法:

 val dataToUse = feed(testData)
 .exec(session => session.set("access", token))            
 .exec(http("")             
 .post("*the_URL_to_send_to)*")
 .headers(headers_10.toMap)
 .body(RawFileBody("${filePath}")).asJson
 .check(status.is(200))
             )

正如前面讨论中的评论中所提到的,这是因为我使用了更高版本的gatling,而'get'方法不再是session api的一部分。

我的完整解决方案如下 - 请注意,有许多需要注意的事项可能不适用于您的解决方案。我使用了一个物体,因为它让我想到的东西更加清晰!此外,一些导入可能是多余的,因为我将它们作为散射枪方法的一部分,以找到有用的东西!

最后,我基本上列出了目录的内容,并循环浏览其中列出的文件,使用每个目录作为馈送器。你看起来好像在使用json的文字模板,所以可能不需要它,但我认为我会将它包含在内,因为它非常方便 - 如果你改变json的格式,你就不会需要在模拟中更改模板,你只需清除目录并在那里删除新格式的示例,然后就可以了! :

 package myTest

 import io.gatling.core.Predef._
 import io.gatling.http.Predef._
 import scala.concurrent.duration._
 import scala.collection.JavaConversions._
 import java.io.File
 import java.io.FileNotFoundException


 class myTestSimulation extends Simulation {    


 val httpConf = http
    .baseUrl("*your_base_URL*")
.acceptHeader("application/json") // Here are the common headers
.doNotTrackHeader("1")
.acceptLanguageHeader("en-UK,en;q=0.5")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0")
.shareConnections

val header = Map("Content-Type" -> """application/x-www-form-urlencoded""");
private var token = ""

val auth = scenario("Retrieve Token")
    .exec(
        http("POST OAuth Req")
        .post("*URL_for_Token*")
        .formParam("resource", "*your_resource_value*")
        .formParam("grant_type", "*your_grant_type*")
        .formParam("client_secret", "*your_client_secret_value*")
        .formParam("client_id", "*your_client_id_value*")
        .headers(header)
        .check(status.is(200)).check(jsonPath("$.access_token").find.saveAs("access")))  
        .exec{session => { token = session("access").as[String]
                         session}}       

object myTestObject {

    var headers_10 = scala.collection.mutable.Map("Content-Type" -> "application/json; charset=ISO-8859-1", "Authorization" -> "Bearer ${access}")     
    val testData = Iterator.continually(
    new File("*pathway_to_file*") match {
      case d if d.isDirectory => d.listFiles.map(f => Map("filePath" -> f.getPath))
      case _ => throw new FileNotFoundException("Samples path must point to directory")
    }).flatten

    val myTestObjectMethod = feed(testData)
        .exec(session => session.set("access", token))            
        .exec(http("")              
            .post("*the_URL_to_send_to(don't_forget_that_base_URL_above_is_automatically_stuck_to_the_front_of_this!)*")
            .headers(headers_10.toMap)
            .body(RawFileBody("${filePath}")).asJson
            .check(status.is(200))
             )
}   

val scn = scenario("my_actual_load_test")
    .exec(myTestSimulation.myTestObject)
   setUp(
  auth.inject(constantUsersPerSec(1) during (1 seconds)), // fire 1 requests per second for 1 second to retrieve token
scn.inject(nothingFor(2 seconds), // waits 2 seconds as a margin to process token
    constantUsersPerSec(50) during (300 seconds) // fire 50 requests per second for 300 seconds
   ).protocols(httpConf))                             
   .assertions(global.responseTime.max.lt(500)) // set max acceptable response time
   .assertions(forAll.failedRequests.percent.lte(1)) // less than 1% of tests should fail
   .assertions(global.responseTime.mean.lte(100)) // set average response time
 }

我的意思是,当我从中移除敏感的东西时,我可能在某处发生了一个错字,但希望这会做你需要的。

© www.soinside.com 2019 - 2024. All rights reserved.