Как использовать один токен OAuth2.0 для нескольких виртуальных пользователей в нагрузочном тесте Гатлинга - PullRequest
1 голос
/ 04 апреля 2019

Мне нужно загрузить тестирование API, который требует токен OAuth2.0 через Gatling (я новичок в этом деле!), Но хотел бы, чтобы каждый виртуальный пользователь использовал один и тот же токен. Я извлекаю токен нормально (я думаю) и помещаю его в переменную с именем «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)) 

Идея заключалась в том, что извлечение токена завершится до запуска нагрузочного теста, и тогда переменная 'access' будет использоваться сценарием нагрузочного теста, но это дает следующий результат:

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

Я достиг конца своей привязи с ним. Я предполагаю, что это может быть связано с областями видимости, и, возможно, переменная не переносится в сценарий нагрузочного тестирования, но в других местах я видел примеры, которые, кажется, рекомендуют именно эту настройку, поэтому я не знаю являются ли эти другие примеры частично полными или что.

Ответы [ 3 ]

1 голос
/ 05 апреля 2019

Сеансы для каждого пользователя, и никакие данные сеанса не передаются между пользователями.Таким образом, хотя у вас есть 1 пользователь, выполняющий сценарий 'auth' и сохраняющий токен, это два разных пользователя, которые запускают 'scn', и у них нет доступа к значениям сеанса пользователя auth.

Этоне рекомендуется, но вы можете решить эту проблему, вставив токен аутентификации в обычный scala-переменную и установив его в сценарии аутентификации и прочитав его в основном сценарии - вам просто нужно быть уверенным, что аутентификация всегда завершается, прежде чем вводить другиеusers.

var token: String = ""

затем в сценарии auth в конце есть шаг, такой как

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

, затем в начале сценария scn есть шаг для установки переменной сеанса

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

Я использовал этот шаблон в прошлом, и он работает, но я уверен, что есть более хорошие способы сделать это

0 голосов
/ 12 июня 2019

@ Тарун,

Когда я это сделал, в моем сценарии было «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' больше не был частью API сеанса.

Мое полное решение было следующим: обратите внимание, что есть ряд вещей, на которые стоит обратить внимание, которые могут не относиться к вашему решению.Я использовал объект, так как он просто прояснил мои мысли о том, что я пытался сделать!Кроме того, некоторые операции импорта, вероятно, являются избыточными, поскольку я включил их как часть подхода scattergun к поиску чего-то, что сработало!

Наконец, я в основном перечисляю содержимое каталога и перебираю файлы, перечисленные в нем., используя каждый в качестве фидера.Вы выглядите так, как будто вы используете буквальный шаблон 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
 }

Я имею в виду, я, вероятно, сделал опечатку где-то вдоль линии, когда я удалил из нее чувствительные вещи, но, надеюсь, это сделает то, что вам нужно.

0 голосов
/ 09 июня 2019

Я также пробую этот сценарий, но получаю сообщение об ошибке при попытке добавить .exec {session => {token = session ("access"). As [String] session}} в начале сценария scn .

       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)) 

но ни один из них не работал. Подскажите, пожалуйста, куда мне на самом деле поместить этот код?

...