Gatling-HTTP 脚本模板

import io.gatling.commons.validation._
import io.gatling.core.check.Validator
import io.gatling.core.Predef._
import io.gatling.http.Predef.{http, _}

import scala.concurrent.duration._

class DemoSimulation extends Simulation {

  // 支持多种格式的csv
  val csvFeeder = csv("foo.csv") // use a comma separator
  val tsvFeeder = tsv("foo.tsv") // use a tabulation separator
  val ssvFeeder = ssv("foo.ssv") // use a semicolon separator
  val customSeparatorFeeder = separatedValues("foo.txt", '#') // use your own separator

  // 一次加载所有数据
  val csvFeeder1 = csv("foo.csv").eager.random

  // 批量加载数据,默认2000
  val csvFeeder2 = csv("foo.csv").batch.random
  // 修改默认buffer
  val csvFeeder3 = csv("foo.csv").batch(200).random

  val feeder = csv("search.csv").random

  // 可进行全局配置
  val httpProtocol = http
    // .enableHttp2 // 支持http2
    .warmUp("http://www.baidu.com") // 热机,启动客户端的http(默认访问的是https://gatling.io,但是这个地址往往不通)
    .baseUrl("http://www.baidu.com", "http://www.baidu.com", "http://www.baidu.com") // 支持多个地址,绕过负载均衡,直接向服务器施加压力
    .header("key", "value")
    .connectionHeader("close")
    .disableCaching

  // 创建场景
  val scn_1 = scenario("scn_1").during(1 minutes) {
    exec(
      feed(feeder).exec(
        http("http_1")
          .get("/")
          .queryParam("key", "value")

          /** http协议常用的检查点设置 **/
          .check(

          /** Targets the HTTP response status code. **/
          status.is(200),
          status.in(200, 304),
          status.not(404),

          // 以下所有关于正则的查找,都支持:find、find(occurrence)、findAll、findRandom、findRandom(num: Int)、findRandom(num: Int, failIfLess = true)、count

          /** Targets the current page absolute URL. Useful when following redirects in order to check if the landing page is indeed the expected one. **/
          currentLocation.validate(new StringValidator[String](CheckType.equals, "http://www.baidu.com/")), // 可以检查有没有出现重定向。
          currentLocationRegex("www").validate(new StringValidator[String](CheckType.equals, "www")), // 支持正则匹配,取出关键字。
          // currentLocationRegex("http://(www).(baidu).(com)").ofType[(String, String, String)].validate(todo),  // 支持多个匹配,这个时候Option[T]是Option[(String, String, String)],StringValidator需要重新适配。

          /** Targets the HTTP response header of the given name.  **/
          header("connection").validate(new StringValidator[String](CheckType.equals, "close")),
          headerRegex("Set-Cookie", "delPer=(.+?);").validate(new StringValidator[String](CheckType.equals, "0")),
          // headerRegex("FOO", "foo(.*)bar(.*)baz").ofType[(String, String)].validate(todo),  // 同样支持多个匹配

          /** Returns the response time of this request in milliseconds = the time between starting to send the request and finishing to receive the response. **/
          responseTimeInMillis.lte(1000),

          /** Return the full response body String. Note that this can be matched against content from the the filesystem using RawFileBody or ElFileBody. **/
          bodyString.validate(new StringValidator[String](CheckType.contains, "百度")),

          /** bodyBytes 和 bodyStream 应该用不到吧 **/

          /** Scans for the indices of a given substring inside the body string. **/
          substring("baidu"), // same as substring("baidu").find.exists
          substring("baidu").findAll.saveAs("indices"), // 可以保存到session中(保存为一个Seq序列)
          substring("baidu").count.gte(10), // 可以检查某正则条件出现的次数

          // 官网描述,substring 似乎比 regex 更节省CPU资源,推荐使用 substring

          /** 正则匹配 **/
          regex("""<link rel="dns-prefetch" href="//(.+?)"/>""").find.validate(new StringValidator[String](CheckType.contains, "com")), // 默认查询第一个
          regex("""<link rel="dns-prefetch" href="//(.+?)"/>""").find(0).validate(new StringValidator[String](CheckType.contains, "com")), // 可以指定查询第几个
          regex("""<link rel="dns-prefetch" href="//(.+?)"/>""").findRandom.validate(new StringValidator[String](CheckType.contains, "com")), // 随机匹配一个
          // regex("""<link rel="dns-prefetch" href="//(.+?)"/>""").findAll.validate(new StringValidator[String](CheckType.contains, "www")), // 这个返回是一个Seq[String],需要单独写Validator
          regex("""<link rel="dns-prefetch" href="//(.+?)"/>""").count.gte(5),

          /** XPath匹配 **/
          // xpath("//input[@id='text1']/@value"),

          /** JSON匹配 **/
          // jsonPath("$..foo.bar[2].baz").ofType[Int]  // 支持 ofType[Int] 进行类型转换
        )
      ))
  }

  val scn_2 = scenario("scn_2").forever() {
    exec(
      /** form **/
      http("http_1")
        .post("/")
        .formParam("myKey", "myValue")
        .formParamSeq(Seq(("myKey", "myValue"), ("anotherKey", "anotherValue"))) // 批量
        .formParamMap(Map("myKey" -> "myValue", "anotherKey" -> "anotherValue")) // 这样也可以
        .multivaluedFormParam("multi1", "${foo}") // 一个key对应多个value。where foo is the name of a Seq Session attribute
        .multivaluedFormParam("multi2", session => List("foo", "bar")), // 这样也可以

      /** from 上传文件 **/
      http("http_upload")
        .post("my.form-action.uri")
        .formParam("myKey", "myValue")
        .formUpload("myKey2", "myAttachment.txt"),

      /** row格式 **/
      http("http_row")
        .body(RawFileBody("myFileBody.json")).asJson // { "myContent": "myHardCodedValue" }
        .body(ElFileBody("myFileBody.json")).asJson // { "myContent": "${myDynamicValue}" },将会解析myDynamicValue的具体值
        .body(StringBody("""{ "myContent": "${myDynamicValue}" }""")).asJson // 将会解析myDynamicValue的具体值
        .body(StringBody(session => """{ "myContent": """" + someGenerator(session) + """" }""")).asJson // TODO
        // .body(ByteArrayBody(bytes: Expression[Array[Byte]]))
        // .body(InputStreamBody(stream: Expression[InputStream]))
        .body(PebbleStringBody("""{ "myContent": "{% if myCondition %}{{myDynamicValue}}{% endif %}" }""")).asJson // 支持一些复杂的逻辑
        .body(PebbleFileBody("myFileBody.json")).asJson, // 可以使用文件中的内容

      /** 支持模拟浏览器的并行获取资源 **/
      http("http_resources")
        .get("https://www.github.com/gatling/gatling/issues")
        .resources(
          http("api.js").get("https://collector-cdn.github.com/assets/api.js"),
          http("ga.js").get("https://ssl.google-analytics.com/ga.js")
        )
    )
  }

  // 开始执行
  setUp(
    scn_1.inject(atOnceUsers(1)),
    scn_2.inject(atOnceUsers(1))
  ).protocols(httpProtocol)
}

/**
  * 自定义的字符串检查方法
  *
  * @param checkType
  * @param param
  * @tparam A
  */
class StringValidator[A](checkType: String, param: String) extends Validator[A] {

  val name = "StringValidator"

  def apply(actual: Option[A], displayActualValue: Boolean): Validation[Option[A]] = {
    actual match {
      case Some(value) => {
        checkType match {
          case CheckType.contains => {
            if (s"${value}".contains(param)) {
              actual.success
            } else {
              s"${value}中未发现${param}".failure
            }
          }
          case CheckType.equals => {
            if (s"${value}".equals(param)) {
              actual.success
            } else {
              s"${value}与${param}不相等".failure
            }
          }
          case CheckType.startswith => {
            if (s"${value}".startsWith(param)) {
              actual.success
            } else {
              s"${value}不是以${param}开始".failure
            }
          }
          case CheckType.endswith => {
            if (s"${value}".endsWith(param)) {
              actual.success
            } else {
              s"${value}不是以${param}结尾".failure
            }
          }
          case _ => {
            "CheckType Error!".failure
          }
        }
      }
      case None => {
        "found nothing!".failure
      }
    }
  }
}

object CheckType {
  val contains: String = "contains"
  val equals: String = "equal"
  val startswith: String = "startwith"
  val endswith: String = "endwith"
}
原文地址:https://www.cnblogs.com/CSunShine/p/11911537.html