Gatling腳本編寫技巧篇(一)

1、公共類抽取

熟悉Gatling的同窗都知道Gatling腳本的同窗都知道,Gatling的腳本包含三大部分:
  1. http head配置
  2. Scenario 執行細節
  3. setUp 組裝
那麼針對三部分咱們須要在一套全流程測試當中把公共的部分提取出來寫成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")
}
定義一個home的接口:

 

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

 

  

 

定義login 接口:

 

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

2、經常使用接口

 

併發量控制:

   

函數 解釋
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)
    }
  }
相關文章
相關標籤/搜索