当前位置: 首页 > 测试知识 > Gatling动态参数处理:Session API、EL表达式、随机函数
Gatling动态参数处理:Session API、EL表达式、随机函数
2025-12-22 作者cwb 浏览次数76

Gatling的Session API、EL表达式和随机函数是构建动态、真实负载测试,模拟出每个虚拟用户(Virtual User)的独特行为。


Session :一个不可变键值存储,存储着该用户的所有个性化状态。随机函数和Feeder负责生成数据并写入Session;而EL表达式则是在需要时从Session中读取数据的简洁语法。


二、 Session API

Session是Gatling状态管理的主要对象,是不可变(Immutable) 的。任何修改操作都会返回一个新的Session实例。


操作API:

存储数据:使用 .set(key, value)


scala

.exec { session =>

  val updatedSession = session.set("userId", 12345).set("requestId", UUID.randomUUID().toString)

  updatedSession // 必须返回这个新的Session

}


读取数据:使用 .get(key),返回 Option[Any]


scala

.exec { session =>

  val maybeUserId = session("userId").asOption[Int] // 安全读取,类型转换

  val userId = session("userId").as[Int] // 直接读取,类型不匹配或不存在会抛异常

  session

}


移除数据.remove(key)

避免使用Session API进行复杂的业务逻辑计算。它主要用于状态传递,复杂逻辑应放在exec的函数体外或使用Gatling的内置处理器。


三、 EL表达式:简洁的动态参数注入

EL表达式(表达式语言)是Gatling DSL中在字符串模板内动态引用Session属性的简洁语法,格式为 ${attributeName}。


应用示例:

URL路径和查询参数:

scala

.get("/api/users/${userId}/orders?type=${orderType}")


请求体(JSON/XML):

scala

.body(StringBody("""{"userId": ${userId}, "items": [${itemId}]}""")).asJson


请求头:

scala

.header("X-Trace-Id", "${traceId}")


特性:

自动类型转换:如果Session中存储的是数字,在JSON体中会被正确渲染为数字(无引号)。

空值安全:如果Session中不存在该属性,Gatling会将该虚拟用户的请求标记为失败。

局限:无法在EL表达式中进行运算或方法调用(如${userId + 1}是无效的)。


四、 随机函数和Feeder数据生成引擎


1. 随机函数库Random

Gatling在io.gatling.core.Predef和io.gatling.core.session.el包中提供了丰富的随机函数,可直接在EL表达式或Session API中使用。


基础随机:


scala

.exec(http("随机用户")

  .get("/user/${randomInt(1, 100)}") // 生成1到100之间的整数

  .header("X-Random", "${randomUuid}") // 生成随机UUID

)


随机字符串:


scala

"${randomAlphanumeric(10)}" // 10位字母数字


加权随机选择:


scala

"${uniformSample(List("mobile", "desktop", "tablet"))}" // 均匀选择

"${circularSample(List("A", "B", "C"))}" // 循环选择


2. Feeder结构化数据源

Feeder用于从外部文件(CSV、JSON)或内部迭代器中读取数据,并注入Session。


CSV文件驱动:


scala

// users.csv 文件内容

// userId,username

// 1,userA

// 2,userB

val userFeeder = csv("users.csv").random

val scn = scenario("场景")

  .feed(userFeeder) // 为每个虚拟用户注入一行数据

  .exec(http("获取用户")

    .get("/api/${userId}")

    .check(jsonPath("$.name").is("${username}"))

  )


自定义迭代器(Iterator.continually):

scala

val customFeeder = Iterator.continually(

  Map("dynamicId" -> (System.currentTimeMillis() + Random.nextInt(1000)))

)


五、 模拟真实用户下单流程

模拟一个包含用户登录、浏览商品、随机下单的完整业务流程:


scala

import scala.concurrent.duration._

import io.gatling.core.Predef._

import io.gatling.http.Predef._


class AdvancedSimulation extends Simulation {


  val httpProtocol = http.baseUrl("https://api.zmtests.com")


  // 1. 使用Feeder加载测试账户和商品数据

  val userAccounts = csv("data/users.csv").circular

  val productPool = csv("data/products.csv").random


  val scn = scenario("完整购物流程")

    // 2. 为虚拟用户注入初始身份

    .feed(userAccounts)

    .exec(

      http("用户登录")

        .post("/login")

        .body(StringBody("""{"username":"${username}","password":"${password}"}"""))

        .check(jsonPath("$.token").saveAs("authToken")) // 3. 提取Token存入Session

    )

    .pause(2)

    // 4. 循环浏览商品

    .repeat(5, "visitCount") {

      feed(productPool)

      .exec(

        http("浏览商品 - ${productId}")

          .get("/products/${productId}")

          .header("Authorization", "Bearer ${authToken}") // 使用Session中的Token

          .check(status.is(200))

      )

      .pause(1)

    }

    // 5. 随机决定是否下单(50%概率)

    .doIf(session => Random.nextBoolean()) {

      exec(

        http("创建订单")

          .post("/orders")

          .header("Authorization", "Bearer ${authToken}")

          .body(ElFileBody("templates/order.json")) // 6. 使用模板文件,其中可包含EL表达式

          .check(jsonPath("$.orderId").saveAs("createdOrderId"))

      )

      .exec { session =>

        // 7. 使用Session API进行后置处理

        println(s"用户 ${session("username").as[String]} 创建了订单:${session("createdOrderId").as[String]}")

        session

      }

    }


  setUp(

    scn.inject(rampUsers(100).during(30.seconds))

  ).protocols(httpProtocol)

}


六、实践

性能:避免在Session中存储过大的对象(如整个文件内容),会增加内存开销和序列化。

线程安全:Gatling的随机函数和Feeder在设计上都是线程安全的,无需额外同步。

可重复:调试时可以为随机数生成器设置固定种子(通过Session的seed属性),保证每次运行脚本时生成相同的“随机”序列。

错误处理:对于主要的Session属性,在使用EL表达式前,可先用.get进行安全检查,或使用doIf保证存在。


文章标签: 软件测试 测试工具
咨询软件测试