无论是性能测试还是自动化测试,有一个很重要的点就是变量(参数化),因为真实环境是很少同时产生并发很高而且所有参数都一模一样的请求的,就算有这样的接口,开发肯定用缓存来挡了,这种一般不会是瓶颈,真正瓶颈并发同一个接口不同参数的情况,这种情况是无法缓存的,只能打在数据库或者程序上,往往就是瓶颈所在。所以进行性能测试时,用对参数进行变量赋值很重要,Gatling本身基于Scala写的,支持JAVA库,所以它的用例既可以支持scala语法,又能使用java的海量函数,简直强大到不行,只可惜我对scala和java都不懂,所以只能简单说一说Gatling中变量的用法了。
要使用变量就要搞清楚“从哪里来,到哪里去”的问题。
从哪里来
Gatling的变量的值至少有如下几种来源:
1、using Feeders——文件、数据库
2、extracting data from responses and saving them, e.g. with HTTP Check’s saveAs——从请求的返回值中提取和保存内容
3、manually with the Session API——用各种java提供的函数生成,缺点是可能影响一点性能
前面两种,大家用的时候参考官网说明就可以了,我这里只说说第三种。
到哪里去
以http请求为例,变量可以用的地方一般是被请求的URL,请求体,但是其他协议的请求肯定不止这两种。
代码
本例是实现对某个http请求进行测试,要求body、url都包含随机数。注释很多,都是因为我对scala和java不熟导致的,将就着看吧。。。
package computerdatabase import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
import java.util.concurrent.ThreadLocalRandom //引用java的库,用于生成随机数 class BasicSimulation extends Simulation {
def getRand(i: Int) : String = ThreadLocalRandom.current.nextInt(i).toString//定义一个生成随机数的函数
var randnum = getRand(100000000)//定义一个常规意义的“变量”,后来发现没什么卵用
val httpConf = http
.baseURL("http://192.168.0.11") // Here is the root for all relative URLs
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.doNotTrackHeader("1")
.acceptLanguageHeader("en-US,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") val headers_1 = Map("Content-Type" -> "application/x-www-form-urlencoded") val scn = scenario("Hello Gatling") // A scenario is a chain of requests and pauses //.exec( session => session.set("RAND", getRand(100000000) ) )// 这才是定义“变量”,在Gatling中用变量就好像把它们作为属性或者元素一样,注意,不能用randnum代替getRand(100000000),否则这个就只会计算一次。
.exec(_.set("RAND", getRand(100000000) ) )//这样写也可以,可怕的scala语法
.exec(_.set("r", "\r" ) )//"""...."""中的换行符是\n,如果要加\r,则也得这么用“变量”的方式做,"""里不能反转义。。。
.exec(
http("post's example") // Here's an example of a POST request
.post("/api/getconf.json?mid=${RAND}&ver=1.0")//在URL中用变量,如果${RAND}在一次请求中被调用多次,每次的结果也是一样的,而jmeter的函数则会每次都变化
//.post("/api/getconf.json?mid="+getRand(100000000)+"&ver=1.0")//如果这样写,字符串+函数返回值,这样的话getRand(100000000)就只会计算一次了
.headers(headers_1)
.body(StringBody("""{
"audit_control_list" : [],
"sd" : [ "sd_settings",${RAND}]
}""")).asJSON
//在body中使用变量,因为用了"""..."""来包含字符串,所以它里面用其他比如getRand(100000000)之类的结果都是直接输出这个字符串而已
//.body(StringBody(_=>getRand(100000000)+"dsds"))//如果要在body中做字符串拼接,这样就可以,也可以用.concat,scala的语法。_ =>这个符号表示scala的模式匹配表达式,是为了让每次循环时都计算新的随机数,它的用法实在搞不定。。。
//.body(StringBody("dsds"+_=>getRand(100000000)))//反过来这样写就不行
//.body(StringBody("dsds${RAND}"))//用变量也可以 //.queryParam("name" ,_=>getRand(100000000))//或者单独作为参数写也可以,如果写成getRand(100000000),那么测试时只会生成一次随机数
.queryParam("name" ,"${RAND}")//用变量当然可以,本文出自360肥狐测试,转载时请注明出处
)
setUp(
scn.inject(
atOnceUsers(10)
).protocols(httpConf)
)
}
在使用Gatling的过程中我发现老外早就把它研究透了,而国内连它的中文帮助都没有,实在可惜,希望有能者把它的官网帮助翻译成中文,造福人民啊,呵呵。
Gatling官网帮助:http://gatling.io/#/docs
Gatling的谷歌论坛:https://groups.google.com/forum/#!topic/gatling/8KVMX8k1eD8