我需要通过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
我已经到了我的系绳的尽头。我猜它可能与范围有关,也许变量不会延续到负载测试场景,但我看到其他地方的例子似乎建议完全设置,所以我不知道这些其他例子是否部分完整或是什么。
会话是按用户进行的,用户之间不会共享会话数据。因此,当您有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))
我过去曾使用过这种模式,但它确实有用,但我确信有更好的方法可以做到
我也在尝试这种情况,但是当我尝试在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))
但他们都没有工作。你能告诉我我应该把这段代码放到哪里。
@ 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
}
我的意思是,当我从中移除敏感的东西时,我可能在某处发生了一个错字,但希望这会做你需要的。