徐州市网站建设_网站建设公司_HTTPS_seo优化
2025/12/22 11:28:56 网站建设 项目流程

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

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

二、 Session API

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

操作API:

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

.exec { session => val updatedSession = session.set("userId", 12345).set("requestId", UUID.randomUUID().toString) updatedSession // 必须返回这个新的Session }

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

.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路径和查询参数:

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

请求体(JSON/XML):

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

请求头:

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

特性:

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

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

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

文章来源:卓码软件测评

精彩推荐:点击蓝字即可
软件负载测试API自动化测试软件测试第三方软件测试软件性能测试软件测试机构

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

1. 随机函数库Random

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

基础随机:

.exec(http("随机用户") .get("/user/${randomInt(1, 100)}") // 生成1到100之间的整数 .header("X-Random", "${randomUuid}") // 生成随机UUID )

随机字符串:

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

加权随机选择:

"${uniformSample(List("mobile", "desktop", "tablet"))}" // 均匀选择 "${circularSample(List("A", "B", "C"))}" // 循环选择

2. Feeder结构化数据源

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

CSV文件驱动:

// 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):

val customFeeder = Iterator.continually( Map("dynamicId" -> (System.currentTimeMillis() + Random.nextInt(1000))) )

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

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

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保证存在。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询