無論是性能測試還是自動化測試,有一個很重要的點就是變量(參數化),因為真實環境是很少同時產生並發很高而且所有參數都一模一樣的請求的,就算有這樣的接口,開發肯定用緩存來擋了,這種一般不會是瓶頸,真正瓶頸並發同一個接口不同參數的情況,這種情況是無法緩存的,只能打在數據庫或者程序上,往往就是瓶頸所在。所以進行性能測試時,用對參數進行變量賦值很重要,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