熟悉Gatling的同窗都知道Gatling腳本的同窗都知道,Gatling的腳本包含三大部分:
那麼針對三部分咱們須要在一套全流程測試當中把公共的部分提取出來寫成Scala腳本公共類,來避免重複的工做和代碼冗餘:
package computerdatabase.JieOuData import io.gatling.core.Predef._ import io.gatling.http.Predef._ import io.gatling.http.config.HttpProtocolBuilder object phHttpProtocol { implicit val noneWhiteList: io.gatling.core.filter.WhiteList = WhiteList () implicit val noneBlackList: io.gatling.core.filter.BlackList = BlackList () implicit val staticBlackList: io.gatling.core.filter.BlackList = BlackList (""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.(t|o)tf""", """.*\.png""") implicit val staticWhiteList: io.gatling.core.filter.WhiteList = WhiteList (""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.(t|o)tf""", """.*\.png""") def apply(host: String)( implicit blackLst: io.gatling.core.filter.BlackList , whiteLst: io.gatling.core.filter.WhiteList ): HttpProtocolBuilder = { http.baseURL (host) .inferHtmlResources (blackLst, whiteLst) .acceptHeader ("application/json, text/javascript, */*; q=0.01") .acceptEncodingHeader ("gzip, deflate") .acceptLanguageHeader ("zh-CN,zh;q=0.9,zh-TW;q=0.8") .doNotTrackHeader ("1") .userAgentHeader ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36") } }
package computerdatabase.JieOuData import io.gatling.http.config.HttpProtocolBuilder object phHeaders { val headers_base = Map ("Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Upgrade-Insecure-Requests" -> "1") }
package com.pharbers.gatling.scenario import io.gatling.core.Predef._ import io.gatling.http.Predef._ import io.gatling.core.structure.ChainBuilder import com.pharbers.gatling.base.phHeaders.headers_base object getHome { val getHome: ChainBuilder = exec (http ("home").get ("/").headers (headers_base)) }
package com.pharbers.gatling.scenario import io.gatling.core.Predef._ import io.gatling.http.Predef._ import io.gatling.core.structure.ChainBuilder import com.pharbers.gatling.base.phHeaders.headers_json object userLogin { val feeder = csv ("loginUser.csv").random println (feeder) val login: ChainBuilder = exec (http ("login") .get ("/api/user/login").headers (headers_json) .body (StringBody ("""{ "condition" : { "email" : "nhwa", "password" : "nhwa" } }""")).asJSON) }
package com.pharbers.gatling.simulation import io.gatling.core.Predef._ import scala.concurrent.duration._ import com.pharbers.gatling.scenario._ import com.pharbers.gatling.base.phHttpProtocol import com.pharbers.gatling.base.phHttpProtocol.{noneBlackList, noneWhiteList} class userLogin extends Simulation { val httpProtocol = phHttpProtocol ("http://192.168.100.141:9000") val scn = scenario ("user_login") .exec (getHome.getHome.pause (5 seconds), userLogin.login.pause (60 seconds)) setUp (scn.inject (rampUsers (1000) over (3 seconds))).protocols (httpProtocol) }
這樣看起來你的腳本是否是清爽不少javascript
函數 | 解釋 |
atOnceUsers(100) | 使用100併發量測試目標服務器 |
rampUsers(100) over (10 seconds) | 按部就班的增大壓力,在10s中內線性增長用戶數達到最大壓力100併發量 |
nothingFor(10 seconds) | 等待10s |
constantUsersPerSec(rate) during(duration) | 在指定duration內,以固定頻率注入用戶,每秒注入rate個用戶,默認固定間隔 |
constantUsersPerSec(rate) during(duration) randomized | 與上面不一樣的是用戶以隨機間隔注入 |
rampUsersPerSec(rate1) to (rate2) during(duration) | 在指定duration內,以遞增頻率注入用戶,每秒注入 rate1 ~ rate2 個用戶 |
函數 | 解釋 |
exec() | 實際的用戶行爲 |
pause(20) | 用戶滯留20s,模擬用戶思考或者瀏覽內容 |
pause(min: Duration, max: Duration) | 用戶隨機滯留,滯留時間在min ~ max 之間 |
函數 | 解釋 |
repeat(time, counterName) | 內置循環器 |
foreach(seq, elem, counterName) | foreach循環器 |
csv("file").random | 建立填充器 |
doIf("", "") | 判斷語句 |
JDBC數據css
jdbcFeeder("databaseUrl", "username", "password", "SELECT * FROM users")
Redis數據html
import com.redis._import io.gatling.redis.Predef._ val redisPool = new RedisClientPool("localhost", 6379) // use a list, so there's one single value per record, which is here named "foo"// same as redisFeeder(redisPool, "foo").LPOPval feeder = redisFeeder(redisPool, "foo") // read data using SPOP command from a set named "foo"val feeder = redisFeeder(redisPool, "foo").SPOP // read data using SRANDMEMBER command from a set named "foo"val feeder = redisFeeder(redisPool, "foo").SRANDMEMBER
文件數據java
import java.io.{ File, PrintWriter }import io.gatling.redis.util.RedisHelper._ def generateOneMillionUrls(): Unit = { val writer = new PrintWriter(new File("/tmp/loadtest.txt")) try { for (i <- 0 to 1000000) { val url = "test?id=" + i // note the list name "URLS" here writer.write(generateRedisProtocol("LPUSH", "URLS", url)) } } finally { writer.close() }}
迭代數據web
import io.gatling.core.feeder._import java.util.concurrent.ThreadLocalRandom // index records by projectval recordsByProject: Map[String, Seq[Record[Any]]] = csv("projectIssue.csv").readRecords.groupBy { record => record("project").toString } // convert the Map values to get only the issues instead of the full recordsval issuesByProject: Map[String, Seq[Any]] = recordsByProject.mapValues { records => records.map { record => record("issue") } } // inject projectfeed(csv("userProject.csv")) .exec { session => // fetch project from session session("project").validate[String].map { project => // fetch project's issues val issues = issuesByProject(project) // randomly select an issue val selectedIssue = issues(ThreadLocalRandom.current.nextInt(issues.length)) // inject the issue in the session session.set("issue", selectedIssue) } }