探索 JMeter While Controller:循环测试的奇妙世界
嘿,宝子们!今天咱们就来聊聊 JMeter 里超级厉害的 While 控制器,它就像是一把神奇的钥匙,能帮我们打开循环测试的大门,模拟出各种各样复杂又有趣的场景哦!
一、While 控制器初印象
想象一下,你在玩一个冒险游戏,只要你的角色还有 “生命值”(这就好比是 While 控制器里的特定条件),你就可以继续挑战下一个关卡(也就是循环执行操作)。While 控制器在 JMeter 中就是这么一个厉害的角色,它允许我们在满足特定条件的情况下,不停地循环执行它下面的那些 “小跟班” 元件。比如说,我们要测试一个网络应用,它有时候连接不太稳定,需要不断尝试连接直到成功,这时候 While 控制器就能派上大用场啦!又或者你想模拟用户不停地查询某个结果,直到找到自己满意的为止,它也能轻松搞定。
二、把 While 控制器 “请” 进 JMeter
- 首先,打开 JMeter 这个大舞台,创建一个全新的测试计划,这就像是为我们的测试表演搭建了一个场地。
- 接着,在测试计划里添加一个线程组。你可以把线程组想象成一群活力四射的小助手,它们会按照我们设定的规则去干活。怎么添加呢?很简单,右键点击测试计划,然后选择 “添加”,再找到 “线程组” 就可以啦。
- 最重要的一步来咯!在线程组下面,再次右键点击,选择 “添加”,然后找到 “逻辑控制器”,里面就有我们心心念念的 While 控制器啦!这样,While 控制器就成功加入我们的测试计划大家庭,准备好发挥它的循环魔法了。
三、调教 While 控制器
(一)条件表达式 —— 核心魔法咒语
-
在 While 控制器的配置界面中,有一个 “Condition”(条件)输入框,这可是它的 “魔法咒语” 输入区哦!我们要在这里输入一个条件表达式,这个表达式就像一个聪明的小卫士,会判断是让循环继续还是停止。它必须能得出真或假的结果,这样 While 控制器才能知道该怎么做。
-
条件与 JMeter 变量、函数的奇妙结合
- 变量:循环的小助手:
假设我们有一个叫count
的变量,它就像是一个记录循环次数的小秘书。我们一般会在线程组下通过 “用户定义的变量” 元件给它一个初始值,比如设为 “0”。然后在循环过程中,在 While 控制器的子节点里,找一个像 “BeanShell PostProcessor” 这样的元件来帮count
变量 “升级”,每次循环结束后让它加 1(也就是count++
)。这样,当条件表达式写成${count} < 10
时,While 控制器就会看着count
变量的值来决定要不要继续循环。如果count
还没到 10,那就继续;一旦count
达到或超过 10,循环就停止啦。 - 函数:强大的魔法工具:
__groovy
函数:神奇的脚本魔法:
JMeter 里的__groovy
函数就像是一个拥有神奇魔法的小精灵,能让我们在条件表达式里嵌入 Groovy 脚本代码。比如说,${__groovy(vars.get("response_code") == "200")}
这个表达式,就是在检查名为response_code
的变量是不是等于 “200”。当我们编写 Groovy 脚本时,可得小心语法这个小怪兽哦!要是想判断一个字符串变量是不是包含特定的子字符串,就可以这样写:${__groovy(vars.get("response_body").contains("success"))}
,这里的response_body
就像是一个装着响应体内容的魔法盒子。要是遇到复杂的 Groovy 表达式,我们还可以偷偷加个println
语句来帮忙调试。比如${__groovy(println(vars.get("response_body")); vars.get("response_body").contains("success"))}
,这样在查看 JMeter 的日志(启动 JMeter 时加上-j
参数指定日志文件路径就能找到它)时,就能看到response_body
这个魔法盒子里到底装了什么,方便我们找出问题所在。而且哦,要是变量的类型不对,也会出乱子。比如说num_variable
本来是个字符串类型的数字,要在条件表达式里和数字比较大小,就得先用Integer.parseInt
方法把它变成真正的数字,像这样${__groovy(Integer.parseInt(vars.get("num_variable")) > 5)}
,不然就会得到意想不到的结果哦。- 其他内置函数:各显神通:
除了__groovy
函数,JMeter 还有好多其他的内置函数可以用在条件表达式里。比如__javaScript
函数,就像一个会 JavaScript 魔法的小巫师,能让我们用 JavaScript 代码来判断条件,像${__javaScript("${VAR}"!= "STOP")}
这样,通过 JavaScript 函数结合变量来决定循环与否。用这些内置函数的时候,一定要遵守它们的语法规则,还要注意函数参数可不能传错哦,不然魔法就不灵啦!
- 避开常见的魔法陷阱:
在写条件表达式的时候,运算符就像一个个小陷阱,要特别小心。像比较运算符(<
、==
等)和逻辑运算符(&&
、||
),不但要用对,还要注意它们的运算顺序。要是不确定,就用括号把要先算的部分括起来,像${(count < 10) && (${__groovy(vars.get("response_code") == "200")})}
这样,让运算顺序明明白白。还有哦,千万不要把赋值操作(=
)当成比较操作(==
)写进条件表达式里,这可是个很容易犯的错误,一旦犯了,条件表达式的结果就会乱套,While 控制器也会跟着 “晕头转向”,不知道该怎么循环了。
- 变量:循环的小助手:
-
语法错误检查 —— 揪出捣蛋鬼
- 语法错误示例:调皮的小错误:
假设我们不小心把条件表达式写成了${count < 10
(少了一个右括号),这就像是在魔法咒语里写错了一个关键字符,While 控制器可就看不懂啦! - 调试和解决方法:找到魔法修复术:
首先,我们可以去看看 JMeter 的日志文件,要是启动 JMeter 的时候配置好了日志输出,里面可能会有关于这个语法错误的提示信息,就像一个小侦探留下的线索。然后呢,我们还可以请出 “调试采样器” 这个小助手。在 While 控制器的子节点里加上 “Debug Sampler”,在它的 “JMeter Variables to Log” 字段里输入条件表达式里用到的变量名,比如count
。运行测试后,在 “查看结果树” 里看看 “Debug Sampler” 的结果。通过观察变量的值和可能出现的错误信息,就能像个聪明的侦探一样,找到语法错误藏在哪里啦。比如说,如果发现count
变量的值没有像我们想的那样显示,那就可能是条件表达式在处理这个变量的时候出了问题,也许就能发现少了括号之类的语法错误了。
- 语法错误示例:调皮的小错误:
(二)条件表达式的优化 —— 让魔法更高效
- 在一些复杂的魔法场景下,要是每次循环都重新计算一些结果,可能会让我们的测试变慢,就像马车拉着太重的东西跑不动一样。所以,我们可以想办法优化一下:
- 缓存变量结果:把宝藏存起来:
比如说,条件表达式里要用到一个很复杂的函数来获取系统当前时间戳,然后和一个固定值比较。如果每次循环都去调用这个函数拿时间戳,那就太浪费魔法力量了。这时候,我们可以在循环开始前,用 “BeanShell PreProcessor” 这个小工具把时间戳拿到手,存到一个变量里,就像这样:
- 缓存变量结果:把宝藏存起来:
long timestamp = System.currentTimeMillis();
vars.put("startTimestamp", String.valueOf(timestamp));
然后在条件表达式里就用这个存好的变量,像${__groovy(Long.parseLong(vars.get("startTimestamp")) < someValue)}
,这样就不用每次都重新计算时间戳啦,是不是很聪明呢?
- 预计算变量:提前准备好魔法材料:
有些变量的值我们其实可以提前算好。比如条件表达式里要根据用户的等级和一些固定系数来计算一个权限值,而且用户等级在整个测试过程中都不会变。那我们就可以在线程组下的 “用户定义的变量” 元件里把这个权限值先算出来。假设用户等级是userLevel
,固定系数是factor
,权限值的计算公式是permission = userLevel * factor
,那就在 “用户定义的变量” 里加上这样的代码:
int userLevel = 5; // 假设用户等级为 5
int factor = 2;
int permission = userLevel * factor;
vars.put("calculatedPermission", String.valueOf(permission));
然后在条件表达式里就用这个提前算好的变量${calculatedPermission} > someValue
,这样就能让我们的测试跑得更快啦!
(三)其他常用配置选项 —— 给 While 控制器加点装饰
- 名称和注释:给它贴上个性标签
- 在 While 控制器的配置界面上,有 “名称(Name)” 和 “注释(Comment)” 两个小格子。我们可以给 While 控制器取一个有趣又能说明它用途的名字,比如如果它是用来控制用户登录失败后重新尝试登录的循环操作,那就可以叫 “Login Retry Loop Controller”,这样一看就知道它是干什么的。
- 注释字段就像是一个小笔记本,我们可以在里面详细写下 While 控制器的功能和配置逻辑。比如说,“这个 While 控制器可厉害啦!当用户登录失败的时候,它会根据返回的错误码来决定要不要重新登录,一直尝试直到登录成功或者达到最大尝试次数哦。条件表达式是${loginFailed} && ${retryCount} < 5”,这样以后再来看这个测试计划,就能很快明白它的作用了。
- 执行顺序相关选项(如果有的话):排好队伍,有序执行
- 有些版本的 JMeter 或者一些扩展可能会有和执行顺序有关的配置选项。这就像是在一场表演中,要安排好演员的出场顺序一样。比如说,我们可以设置 While 控制器在某个特定前置控制器完成它的操作后再开始循环,这样就能保证循环里的条件判断所需要的数据是准确无误的。要是有这样的选项,我们一定要合理设置,让整个测试流程像一场精彩的演出一样,有条不紊地进行下去。
四、给 While 控制器找 “小伙伴”(添加子节点)
- 在 While 控制器下面,我们可以添加各种各样的元件,这些就是它的 “小伙伴” 啦,它们会在循环中一起完成任务。这些小伙伴可以是 HTTP 请求、Sampler、其他逻辑控制器等等。
- 比如说,我们右键点击 While 控制器,选择 “添加”,再找到 “Sampler”,然后选择 “HTTP 请求”,这样就给 While 控制器添加了一个 HTTP 请求作为小伙伴。接着,我们就可以像打扮一个小玩偶一样,配置 HTTP 请求的 URL、方法、参数等信息,让它去模拟在循环中要不断执行的特定操作。想象一下,我们在测试一个搜索引擎,就可以在 While 控制器下添加一个 HTTP 请求,让它不停地发送搜索关键词的请求,然后根据搜索结果页面的一些特点,比如是不是找到了相关结果,或者结果数量够不够,来决定要不要继续循环搜索。是不是很有趣呢?
五、设置变量值 —— 给循环加点 “变数”
- 变量作用域:分清魔法的边界
- 全局变量:大家都能用的魔法棒:
全局变量就像是一根大家都可以用的魔法棒,在线程组下定义后,整个测试计划里的元件都可以访问和修改它(除非有特殊的限制)。比如说前面提到的count
变量,如果我们希望它在整个测试过程中都能被各个元件使用和操作,就可以在线程组下通过 “用户定义的变量” 元件来定义它。这样,无论是哪个逻辑控制器还是 Sampler,都可以对count
变量进行操作,让它的值发生变化,从而影响循环的过程。 - 局部变量:只属于自己的小魔法:
局部变量就像是一个小魔法师自己的秘密武器,通常在特定的元件内部定义,比如 “BeanShell Sampler” 或者 “JSR223 Sampler”,它的作用域就只在这个元件里面。比如说,我们在一个 “BeanShell Sampler” 里定义了一个局部变量local_count
,并且在里面做了一些操作,那这个变量在 “BeanShell Sampler” 外面是看不到的,就像一个小秘密一样。当我们在条件表达式里使用变量的时候,要根据实际情况来选择是用全局变量还是局部变量。如果一个变量只是在某个特定的操作中使用,比如在一个特定的 Sampler 里做一些临时的计算,那把它定义为局部变量就可以避免和其他变量混淆,让测试计划更加清晰整洁。但如果这个变量需要在多个元件之间传递和使用,比如记录整个测试过程中的循环次数,那就得把它定义为全局变量,这样大家才能都找到它并且使用它。 - 变量操作与管理:让变量乖乖听话:
对于那些在循环过程中需要不断变化的变量,比如count
变量,我们得找对方法来操作它。如果一开始是通过 “用户定义的变量” 元件定义了count
,那在循环过程中(比如在 While 控制器的子节点中的 “BeanShell PostProcessor” 里),我们就可以用count++
这样的操作来让它的值增加。而对于一些从响应数据中提取出来的值,比如从网页响应中提取用户的权限级别,然后存到user_permission
变量里,我们可以用 “正则表达式提取器” 这个小工具来实现。总之,我们要根据变量的特点和在测试中的用途,选择合适的方法来操作和管理它们,这样才能让它们在循环中发挥出最大的作用。
- 全局变量:大家都能用的魔法棒:
- 在循环过程中,我们还可以用其他方法来改变变量的值,从而影响循环的条件:
- 用 “正则表达式提取器” 提取宝藏:
比如说,我们在测试一个网页应用的时候,从登录后的页面响应中提取用户的权限级别,然后把它存到一个叫user_permission
的变量里。这样,在 While 控制器的条件表达式中,我们就可以用这个变量来判断用户是不是有特定的操作权限,比如${user_permission} == "admin"
,如果是,那就可以决定是否继续循环执行某些管理操作相关的请求。这就像是从一个装满宝藏的箱子里找出我们需要的那颗宝石,然后用它来开启下一个关卡的大门。 - 用 “BeanShell PostProcessor” 施展编程魔法:
再比如,在一个循环中,每次发送一个 HTTP 请求后,我们可以用 “BeanShell PostProcessor” 这个小魔法师来检查响应状态码。如果是 “401 Unauthorized”,那就说明可能出现了权限问题,我们就可以把一个用来记录错误次数的变量error_count
加 1,然后根据error_count
的值来决定是不是还要继续循环尝试登录,比如${error_count} < 5
。这样,我们就可以通过编程的方式来灵活地控制循环的条件,让测试更加智能和高效。
- 用 “正则表达式提取器” 提取宝藏:
六、让测试跑起来(运行测试)
- 一切准备就绪,我们就可以点击 JMeter 界面上那个绿色的三角形按钮(也就是 “启动” 按钮),让我们的测试计划像一辆发动的汽车一样跑起来。这时候,While 控制器就会根据我们设置的条件表达式结果,来决定是不是要让它的小伙伴们(子节点)循环执行任务。
- 在测试运行的过程中,我们可以通过 JMeter 的各种 “小眼睛”(监听器)来观察测试的执行情况。比如说 “查看结果树” 就像是一个神奇的望远镜,能让我们看到每个请求的详细信息,包括 While 控制器的子节点在每次循环中的请求和响应数据。还有 “聚合报告” 就像是一个智能的分析师,能告诉我们整个测试过程中 While 控制器及其子节点的性能指标,比如平均响应时间、吞吐量、错误率等等。通过这些监听器,我们就可以清楚地知道测试是不是按照我们的预期在进行,如果条件满足,子节点就会欢快地循环执行;如果条件不满足,循环就会停止,测试就会继续执行后面的其他元件或者操作,就像一场精彩的演出,每个环节都有条不紊地进行着。
七、查看结果 —— 验收我们的 “魔法成果”
- 调试与日志输出:找出隐藏的小秘密
- JMeter 自带的调试工具:神奇的放大镜:
JMeter 给我们准备了 “Debug Sampler” 和 “View Results Tree” 这两个厉害的调试工具,就像是两个神奇的放大镜。我们在 While 控制器的子节点里加上 “Debug Sampler”,然后在它的 “JMeter Variables to Log” 字段里输入我们想要查看的变量名,比如count
、response_code
等。运行测试后,在 “查看结果树” 里查看 “Debug Sampler” 的结果,就能像用放大镜看东西一样,清晰地看到这些变量在每次循环中的值是怎么变化的。这对于我们排查问题可太有用了!如果发现变量的值没有按照我们预想的那样变化,那就说明可能在某个地方出现了问题,我们就可以顺着这个线索去找到问题的根源,然后把它解决掉。 - 日志输出与级别选择:控制魔法日志的信息量:
当我们用__log
函数输出调试信息的时候,就像是在写一本魔法日记,要注意选择合适的日志级别。JMeter 提供了不同的日志级别,比如 DEBUG、INFO、WARN、ERROR 等。我们可以在 JMeter 的配置文件(jmeter.properties
)里设置日志级别,或者在启动 JMeter 的时候通过-L
参数来指定。比如说,如果我们只想输出调试信息,那就可以把日志级别设置为 DEBUG,然后在__log
函数里用合适的日志级别参数,像${__log(DEBUG, "当前循环次数:" + count)}
这样。这样就能避免输出太多不必要的信息,同时又能保证我们能拿到关键的调试信息,就像从魔法日记里找到我们最需要的那几页重要内容一样。
- JMeter 自带的调试工具:神奇的放大镜:
- 同时,我们还可以用 “聚合报告” 这个智能的分析师来查看整个测试过程中 While 控制器及其子节点的性能指标,比如平均响应时间、吞吐量、错误率等等。通过这些数据,我们可以评估我们的测试是不是达到了预期的效果,有没有出现性能瓶颈或者其他问题。
- 性能评估的具体示例与数据解读:解读魔法数据的奥秘:
- 性能瓶颈识别案例:解开性能之谜:
假设我们在测试一个需要不断查询数据库的应用程序,用 While 控制器来模拟多次查询操作。通过 “聚合报告” 监听器,我们发现随着循环次数的增加,平均响应时间越来越长,吞吐量越来越低,而且错误率也开始上升。这就像是我们的魔法马车在行驶过程中越来越慢,还老是出故障,这可能就意味着数据库查询操作在高并发循环查询的情况下出现了性能瓶颈。- 分析与解决:修复性能问题的魔法咒语:
首先,我们要查看数据库的执行计划,看看查询语句是不是可以优化。比如说,是不是存在全表扫描这种比较低效的情况,或者是不是可以添加合适的索引来提高查询速度。然后,我们还要检查服务器的资源使用情况,比如 CPU、内存、磁盘 I/O 等。如果 CPU 使用率太高,可能就表示数据库服务器的处理能力已经快到极限了,这时候我们可能就需要考虑升级硬件或者优化数据库的配置参数,比如调整缓存大小、优化数据库连接池的设置等等。同时,我们也要检查 JMeter 测试计划中的数据库连接配置,看看连接池大小是不是合适。如果连接池太小,就可能会导致大量的查询请求在等待连接,这样就会增加响应时间和错误率。我们可以尝试调整连接池参数,增加连接数,然后再观察性能是不是有所改善。就像给我们的魔法马车换一匹更强壮的马,或者给它的轮子加点润滑油,让它能跑得更快更稳。
- 分析与解决:修复性能问题的魔法咒语:
- 性能瓶颈识别案例:解开性能之谜:
- 性能评估的具体示例与数据解读:解读魔法数据的奥秘:
八、调试 While 控制器以确保循环逻辑的正确性
- 使用调试采样器:点亮魔法追踪灯
- 在 While 控制器的子节点中添加 “Debug Sampler” 就像是在黑暗的魔法森林里点亮了一盏追踪灯。比如说,如果条件表达式是
${count} < 10 && ${__groovy(vars.get("response_code") == "200")}
,那我们就在 “Debug Sampler” 的 “JMeter Variables to Log” 字段里输入 “count” 和 “response_code”。运行测试后,在 “查看结果树” 中查看 “Debug Sampler” 的结果,就能清楚地看到这些变量在每次循环中的实际值。这样我们就可以检查变量值是不是按照我们预期的那样变化,以及条件表达式是不是能正确地判断循环的继续或停止。如果发现变量值不对,或者条件表达式的结果不符合预期,那就说明我们的循环逻辑可能存在问题,需要进一步排查。
- 在 While 控制器的子节点中添加 “Debug Sampler” 就像是在黑暗的魔法森林里点亮了一盏追踪灯。比如说,如果条件表达式是
- 查看日志输出:翻阅魔法记录簿
- 就像前面说的,通过在
__log
函数中选择合适的日志级别输出关键变量的值,这就像是在翻阅一本详细的魔法记录簿。比如在条件表达式相关的元件(如 “BeanShell PostProcessor”)中添加${__log(DEBUG, "当前count值:" + count)}
,并且在启动 JMeter 时设置好日志级别为 DEBUG。这样在查看 JMeter 日志时,我们就能追踪变量的变化情况,确保循环逻辑的正确性。如果发现变量值没有按照预期更新,那就可能意味着循环逻辑存在问题,比如说变量更新的代码没有正确执行,或者条件表达式中的变量引用有误。这时候我们就需要仔细检查相关的代码和表达式,找出问题所在并修复它。
- 就像前面说的,通过在
- 逐步分析循环过程:拆解魔法步骤
- 第一轮循环:踏上魔法旅程的第一步:
- 在循环开始前,我们要像出发前检查行李一样,确认所有涉及条件表达式的变量初始值是不是正确。比如说,如果有变量
count
和response_code
,我们就要检查它们是不是已经通过 “用户定义的变量” 或其他合适的元件进行了正确的初始化。如果count
应该初始为 0,那就确保它确实是 0;如果response_code
应该有一个初始的预期值,也要检查它是否正确设置。 - 当进入第一轮循环时,我们要像一个细心的探险家一样,观察 While 控制器是不是按照预期执行了子节点。这时候,我们可以结合 “查看结果树” 中的信息,查看子节点的请求和响应情况。同时,查看调试采样器或日志输出中变量的值,验证条件表达式的第一次求值是不是正确。比如说,若条件表达式为
${count} < 10 && ${__groovy(vars.get("response_code") == "200")}
,我们就要检查count
是不是为初始值(如 0),response_code
的值是不是符合预期,以及整个条件表达式是不是得出了正确的布尔值来决定是否执行第一轮循环。如果条件表达式应该为真,但实际上没有执行子节点,或者条件表达式为假但却执行了子节点,那就说明我们的循环逻辑在第一轮就出现了问题,需要赶紧查找原因。
- 在循环开始前,我们要像出发前检查行李一样,确认所有涉及条件表达式的变量初始值是不是正确。比如说,如果有变量
- 中间轮次循环:魔法旅程的持续探索:
- 随着循环的进行,我们要像一个专注的魔法师关注魔法元素的变化一样,重点关注变量值的变化情况。如果在循环中存在对变量进行操作的元件(如 “BeanShell PostProcessor” 对
count
进行自增操作),我们就要确保这些操作正确执行。在每一轮循环结束后,再次检查条件表达式中的变量值和表达式的求值结果。比如说,经过几轮循环后,count
的值应该按照操作逻辑依次递增,如果它没有递增或者递增的数值不对,那就说明变量更新的操作可能有问题。同样,response_code
的值(如果会变化)也应该符合实际业务逻辑,同时条件表达式应该根据这些变量值的变化正确地决定是否继续下一轮循环。如果发现条件表达式在某一轮循环中得出的结果不符合预期,那就要仔细检查这一轮循环中变量的变化以及条件表达式的编写是否正确。
- 随着循环的进行,我们要像一个专注的魔法师关注魔法元素的变化一样,重点关注变量值的变化情况。如果在循环中存在对变量进行操作的元件(如 “BeanShell PostProcessor” 对
- 最后一轮循环(循环结束):完成魔法旅程的关键一步:
- 当循环接近结束时,无论是因为条件不满足而正常结束,还是出现了可能的异常情况导致循环提前或异常结束,我们都要像一个严谨的魔法师结束一场重大仪式一样,仔细检查最后一轮循环中的变量值和条件表达式的求值结果。如果循环是因为达到最大循环次数或其他限制条件而结束,我们要确认这些限制条件是不是按照预期生效。比如说,如果条件表达式为
${count} < 10
,当count
达到 9 并进入最后一轮循环后,我们要确认这一轮循环执行完后count
的值变为 10,导致条件表达式为假,从而使 While 控制器停止循环,这一过程应该与我们预期的循环逻辑完全相符。同时,我们还要检查最后一轮循环的子节点执行结果是不是符合业务逻辑,避免出现因循环结束相关操作导致的错误。如果最后一轮循环的子节点执行出现了异常情况,或者执行结果不符合预期,那就要检查是不是在循环结束的处理过程中出现了问题,比如资源释放不当或者数据保存不正确等。
- 当循环接近结束时,无论是因为条件不满足而正常结束,还是出现了可能的异常情况导致循环提前或异常结束,我们都要像一个严谨的魔法师结束一场重大仪式一样,仔细检查最后一轮循环中的变量值和条件表达式的求值结果。如果循环是因为达到最大循环次数或其他限制条件而结束,我们要确认这些限制条件是不是按照预期生效。比如说,如果条件表达式为
- 第一轮循环:踏上魔法旅程的第一步:
九、While 控制器在不同类型的性能测试场景中的具体应用
(一)网络连接测试
- 场景描述:跨越网络的魔法桥梁:
- 在测试网络应用程序的连接稳定性时,我们就像是要在一条不太稳定的魔法桥梁上反复行走,直到安全到达对岸或者尝试了足够多次。常常需要模拟客户端不断尝试连接服务器,直到连接成功或者达到最大尝试次数。这就像是一个勇敢的骑士不断冲击城堡的大门,直到门打开或者他筋疲力尽。
- While 控制器的应用:开启连接魔法之门:
- 条件表达式可以设置为基于连接状态的变量。比如说,假设存在一个名为
isConnected
的变量,它的初始值为false
,就像城堡的大门一开始是紧闭的。在每次尝试连接操作(通过在 While 控制器下添加的子节点,如 TCP Sampler 进行连接尝试)后,我们要通过合适的后置处理器(如 “BeanShell PostProcessor”)来更新isConnected
变量的值。如果连接成功,就把它设置为true
;如果连接失败,就保持false
。条件表达式可以写成${!isConnected} && ${retryCount} < 10
,这就像是骑士在心里默念的咒语:只要城堡的大门还没打开(!isConnected
)并且我还没有尝试太多次(retryCount < 10
),我就继续冲击大门(循环尝试连接)。这样,While 控制器就能根据这个条件表达式,控制连接尝试的循环过程,直到成功连接或者达到最大尝试次数。
- 条件表达式可以设置为基于连接状态的变量。比如说,假设存在一个名为
(二)数据查询测试
- 场景描述:寻找数据宝藏的魔法探险:
- 对于数据库或其他数据存储系统的数据查询操作,我们就像是在一个神秘的魔法宝库里寻找特定的宝藏,可能需要不断地翻找各个角落,直到找到我们想要的东西。比如说,在测试一个数据仓库的查询接口时,我们要不断查询直到获取到最新更新的数据,这就像是在宝库里寻找一件刚刚被放进去的珍贵魔法物品。
- While 控制器的应用:指引数据查询的魔法罗盘:
- 我们可以基于查询结果的相关变量来设置条件表达式。假设通过查询操作会返回一个包含数据时间戳的变量
dataTimestamp
,我们期望获取到的数据时间戳大于某个特定值(如lastKnownTimestamp
),这就像是我们知道要找的魔法物品上有一个特定的标记(时间戳),只有找到比我们已知标记更新的物品才行。那么条件表达式可以写成${__groovy(vars.get("dataTimestamp") <= vars.get("lastKnownTimestamp"))}
,这样 While 控制器就会像一个精准的魔法罗盘,控制查询操作不断循环执行,直到获取到的dataTimestamp
大于lastKnownTimestamp
,也就是我们找到了那个带有更新标记的魔法物品(最新数据)。
- 我们可以基于查询结果的相关变量来设置条件表达式。假设通过查询操作会返回一个包含数据时间戳的变量
(三)业务流程测试
- 场景描述:电商购物的魔法流程:
- 在模拟复杂的业务流程时,比如在电商系统的下单流程中,我们就像是在一个充满魔法规则的购物世界里穿梭。如果支付失败,这就像是在魔法商店里付款时遇到了魔法屏障,我们需要按照一定规则重新尝试支付,就像寻找破解屏障的魔法咒语一样。
- While 控制器的应用:修复支付魔法的循环咒语:
- 我们根据支付结果相关的变量来设置条件表达式。假设存在一个变量
isPaymentSuccess
,它的初始值为false
,就像一开始魔法屏障还在那里。在每次支付操作(通过在 While 控制器下添加的 HTTP 请求等子节点模拟支付)后,我们通过相应的后置处理器(如根据支付接口返回结果更新isPaymentSuccess
变量)来更新变量值。如果支付成功,就把isPaymentSuccess
设置为true
;如果支付失败,就保持false
。条件表达式可以写成${!isPaymentSuccess} && ${retryPaymentCount} < 3
,这就像是我们在心里不断重复的咒语:只要支付还没成功(!isPaymentSuccess
)并且我重新支付的次数还不到 3 次(retryPaymentCount < 3
),我就继续尝试支付(循环执行支付操作)。这样,While 控制器就能控制支付操作的循环,直到支付成功或者达到最大尝试次数,就像我们最终成功破解魔法屏障完成购物一样。
- 我们根据支付结果相关的变量来设置条件表达式。假设存在一个变量
相关文章:
探索 JMeter While Controller:循环测试的奇妙世界
嘿,宝子们!今天咱们就来聊聊 JMeter 里超级厉害的 While 控制器,它就像是一把神奇的钥匙,能帮我们打开循环测试的大门,模拟出各种各样复杂又有趣的场景哦! 一、While 控制器初印象 想象一下,你…...
Facebook元宇宙项目中的智能合约应用:提升虚拟空间的自治能力
近年来,Facebook在元宇宙领域的探索引起了广泛关注。元宇宙是一个融合虚拟现实(VR)、增强现实(AR)和互联网的沉浸式数字空间。在这个过程中,智能合约技术被认为是提升虚拟空间自治能力的关键工具。通过自动…...
前后端规约
文章目录 引言I 【强制】前后端交互的 API请求内容响应体响应码II 【推荐】MVC响应体III【参考】IV 其他引言 服务器内部重定向必须使用 forward;外部重定向地址必须使用 URL 统一代理模块生成,否则会因线上采用 HTTPS 协议而导致浏览器提示“不安全”,并且还会带来 URL 维护…...
获取 Astro Bot AI 语音来增强您的游戏体验!
有很多用户尝试过Astro Bot,却被Astro Bot可爱的声音所吸引。您是否想知道如何使用 Astro Bot 语音来拨打恶作剧电话或用他的声音说话?如果您有,那么这篇文章适合您。我们将向您展示如何为 Astro Bot 提供逼真的 AI 声音并在在线对话中使用它…...
javaEE-多线程进阶-JUC的常见类
juc:指的是java.util.concurrent包,该包中加载了一些有关的多线程有关的类。 目录 一、Callable接口 FutureTask类 参考代码: 二、ReentrantLock 可重入锁 ReentrantLock和synchronized的区别: 1.ReentantLock还有一个方法:…...
nginx配置 - 资源参数配置(性能优化)
nginx - 资源参数配置 (性能优化) 一、worker_rilimit_nofile配置的含义使用场景如何调整参数系统级文件描述符限制(补充)二、worker_connections三、两者之间的数值关系四、sendfile五、keepalive_timeout本文重点讨论: 最大文件描述符数量 worker_rilimit_nofile和最大连…...
TiDB 升级至高版本提示'mysql.tidb_runaway_watch' doesn't exist 问题处理
作者: asd80703406 原文来源: https://tidb.net/blog/90394c97 背景 近期发现很多人从低版本升级至TiDB v7 或者v8版本,均遇到了tidb-server启动失败,提示报错如下: ["get runaway watch record failed"…...
利用Deeplearning4j进行 图像识别
目录 图像识别简介 神经网络 感知器 前馈神经网络 自动编码器 受限玻尔兹曼机 深度卷积网络 理解图像内容以及图像含义方面,计算机遇到了很大困难。本章先介绍计算机理解图像教育方面 遇到的难题,接着重点讲解一个基于深度学习的解决方法。我们会…...
使用Python构建智能医疗诊断系统
医疗诊断系统在现代医疗领域中扮演着重要角色,尤其在辅助医生进行初步诊断、缩短诊断时间方面更是发挥了显著作用。借助Python强大的数据处理能力和机器学习工具,我们可以构建一个智能医疗诊断系统。本文将详细介绍实现过程,并结合代码示例帮助您理解。 引言 现代医学产生…...
NLP 技术的突破与未来:从词嵌入到 Transformer
在过去的十年中,自然语言处理(NLP)经历了深刻的技术变革。从早期的统计方法到深度学习的应用,再到如今Transformer架构的普及,NLP 的发展不仅提高了模型的性能,还扩展了其在不同领域中的应用边界。 1. 词嵌…...
【2024年-11月-9日-开源社区openEuler实践记录】OpenAMDC:开启智能边缘计算与系统管控的新征程
一、开篇:邂逅 OpenAMDC 大家好,我是 fzr123,在开源项目的浩瀚天地里持续探索,今天要带大家深入了解一项极具前瞻性与创新性的开源成果——OpenAMDC。在边缘计算蓬勃兴起、系统复杂度与日俱增的时代背景下,OpenAMDC 宛…...
ELK日志平台搭建 (最新版)
一、安装 JDK 1. 下载 JDK 21 RPM 包 wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.rpm2. 安装 JDK 21,使用 rpm 命令安装下载的 RPM 包: sudo rpm -ivh jdk-21_linux-x64_bin.rpm3. 配置环境变量 编辑 /etc/profile 文件以配置 JAVA_HO…...
蓝桥杯备赛:C++基础,顺序表和vector(STL)
目录 一.C基础 1.第一个C程序: 2.头文件: 3.cin和cout初识: 4.命名空间: 二.顺序表和vector(STL) 1.顺序表的基本操作: 2.封装静态顺序表: 3.动态顺序表--vector:…...
MySQL数据库——常见慢查询优化方式
本文详细介绍MySQL的慢查询相关概念,分析步骤及其优化方案等。 文章目录 什么是慢查询日志?慢查询日志的相关参数如何启用慢查询日志?方式一:修改配置文件方式二:通过命令动态启用 分析慢查询日志方式一:直…...
【NX入门篇】
NX入门篇 一、UG NX 由来二、软件如何启动(UG NX 12.0)三、使用步骤四、常用命令 一、UG NX 由来 UG NX由来: 1969 年:UG 的开发始于美国麦道航空公司,基于 C 语言开发实现;1976 年:UG问世&am…...
卡码网 ACM答题编程模板
背景: input() 在 ACM 编程中的底层调用原理 1. input() 的核心原理 在 Python 中,input() 的底层实现依赖于标准输入流 sys.stdin。每次调用 input() 时,Python 会从 sys.stdin 中读取一行字符串,直到遇到换行符 \n 或文件结束…...
vue代理问题
vue代理问题 场景:前后端分离项目问题,在前端中请求接口,返回数据这个过程,但是在这个过程中,前端会有两个环境,一个是开发环境,一个是生产环境. 在开发环境中请求接口可能会遇到跨域问题,比如请求的端口是3000,当前端口是8080,这时候就会遇到跨域问题,或者ip不同,也会存在跨…...
软考 高级 架构师 第十 章软件工程3
1.系统测试 系统测试是为了发现错误而执行程序的过程,成功的测试是发现了至今尚未被发现的错误的测试。 测试原则: 1)应尽早并不断的进行测试 2)测试工作应避免由原开发软件的人或小组承担 3)在 设计测试方案时&#…...
GoF23种设计模式 简介
文章目录 面向对象(OO)设计原则(7)单一职责原则开闭原则里氏代换原则依赖倒转原则接口隔离原则合成复用原则迪米特法则 创建型模式 (5)工厂方法模式 (类模式,其余都是对象模式)抽象工厂模式建造…...
【FlutterDart】页面切换 PageView PageController(9 /100)
上效果: 有些不能理解官方例子里的动画为什么没有效果,有可能是我写法不对 后续如果有动画效果修复了,再更新这篇,没有动画效果,总觉得感受的丝滑效果差了很多 上代码: import package:flutter/material.…...
旧服务改造及微服务架构演进
旧服务改造及微服务架构演进 微服务架构演进1.微服务架构2.微服务架构的特点3.单体架构与微服务架构之间的对比4.微服务架构演进历程 旧服务改造1. 微服务拆分的一些通用原则2.微服务拆分策略(1)功能维度拆分策略(2)非功能维度拆分…...
数据结构复习 (顺序查找,对半查找,斐波那契查找,插值查找,分块查找)
查找(检索): 定义:从给定的数据中找到对应的K 1,顺序查找: O(n)的从前向后的遍历 2,对半查找,要求有序 从中间开始查找,每次检查中间的是否正确,不正确就…...
根据docker file 编译镜像
比如给到一个Dockerfile 第一步编译镜像 cd /path/to/Dockerfiledocker build -t <DOCKER_IMAGE_NAME> . build 命令编译镜像 -t 镜像名字 . 指dockerfile 所在目录 如果遇到报错 [] Building 0.3s (3/3) FINISHED …...
C语言:调试的概念和调试器的选择
所谓调试(Dubug),就是跟踪程序的运行过程,从而发现程序的逻辑错误(思路错误),或者隐藏的缺陷(Bug)。 在调试的过程中,我们可以监控程序的每一个细节ÿ…...
Vulnhub靶场(Earth)
项目地址 https://download.vulnhub.com/theplanets/Earth.ova.torrent 搭建靶机 官网下载.ova文件双击vm打开导入 获取靶机IP kail终端输入 arp-scan -l 获取靶机 IP 192.168.131.184 信息收集 端口扫描 sudo nmap -sC -sV -p- 192.168.131.184 可以看到开启22端口&…...
rsync命令常用同步方案
rsync是一个高效的文件同步工具,广泛应用于本地和远程备份、镜像及同步任务。它通过增量同步、压缩传输以及远程协议(如SSH)等技术,显著提高了文件传输的效率。本文将介绍rsync命令的常用参数、工作原理、常见同步方案,…...
【Ubuntu】 Ubuntu22.04搭建NFS服务
安装NFS服务端 sudo apt install nfs-kernel-server 安装NFS客户端 sudo apt install nfs-common 配置/etc/exports sudo vim /etc/exports 第一个字段:/home/lm/code/nfswork共享的目录 第二个字段:指定哪些用户可以访问 * 表示所有用户都可以访…...
Python自学 - 递归函数
1 Python自学 - 递归函数 递归函数是一种在函数体内调用自己的函数,就像“左脚踩着右脚,再右脚踩着左脚… 嗯,你就可以上天了!”。递归函数虽然不能上天,但在处理某些场景时非常好用, 一种典型的场景就是遍…...
后端开发入门超完整速成路线(算法篇)
引言 后端开发是软件开发中不可或缺的一部分,它涉及到服务器、数据库、API等核心组件的构建和维护。对于初学者来说,掌握算法和数据结构是进入后端开发领域的基础。本文将为你提供一个超完整的算法学习路线,帮助你快速入门,并在文…...
51单片机——共阴数码管实验
数码管中有8位数字,从右往左分别为LED1、LED2、...、LED8,如下图所示 如何实现点亮单个数字,用下图中的ABC来实现 P2.2管脚控制A,P2.3管脚控制B,P2.4管脚控制C //定义数码管位选管脚 sbit LSAP2^2; sbit LSBP2^3; s…...
使用Clion在ubuntu上进行交叉编译,并在Linux上远程编译五子棋
目录 1.工具以及概念介绍 (1)Clion软件简介 (2)交叉编译 (3)远程编译 2.操作原理 3.详细操作步骤 (1)配置Clion与虚拟机ubuntu的ssh连接 CLion远程开发Ubuntu,并显…...
高并发写利器-组提交,我的Spring组件实战
高并发写优化理论 对于高并发的读QPS优化手段较多,最经济简单的方式是上缓存。但是对于高并发写TPS该如何提升?业界常用的有分库分表、异步写入等技术手段。但是分库分表对于业务的改造十分巨大,涉及迁移数据的麻烦工作,不会作为…...
Stable Diffusion的简单介绍
Stable Diffusion 是一款免费、开源的 AI 图像生成器,由 Stability AI 公司于 2022 年 8 月推出1。以下是关于它的详细介绍: 目录 工作原理 特点 应用场景 主要版本 工作原理 Stable Diffusion 属于潜在扩散模型,主要由三部分组成&…...
R语言的数据结构
R语言的数据结构 R语言是专门为统计计算和数据分析而设计的一种编程语言,因其强大的数据处理能力而受到广泛欢迎。在R中,数据结构是理解和有效使用R语言的基础。本文将详细介绍R语言中的主要数据结构,包括向量、矩阵、数据框、列表、因子等&…...
go项目zero框架中用gentool解决指定MYSQL表生成结构体被覆盖的解决方案
在使用 GoZero 框架进行项目开发时,gentool 是一个非常方便的工具,它可以根据数据库表结构自动生成 Go 语言结构体和其他相关文件。然而,在使用 gentool 生成结构体时,可能会遇到一个问题:如果多次运行 gentool&#x…...
限时特惠,香港服务器,低至53元/年
家人们谁懂啊!香港服务器这价格简直逆天了,居然比内地的还便宜!就拿阿里云来说,人家最低配置的服务器,价格都很难做到这么亲民。 最低配的就不说了,2 核 4G 的配置,应对日常业务稳稳当当&#x…...
【GUI-pyqt5】QObject类
1. QObject模块详解 1.1 描述 所有Qt对象的父类 1.2 功能和作用 1.2.1 对象名称和属性 1.2.1.1 API API功能备注 setObjectName("唯一名称") 给一个Qt对象设置一个名称 一般这个名称是唯一的,当做对象ID来使用 objectName() 获取一个对象名称 - set…...
第2章:SQL基础
第2章:SQL基础 2.1 SQL语言介绍 2.1.1 SQL发展历史 SQL的起源SQL标准的演变不同数据库的SQL实现 2.1.2 SQL语言分类 数据定义语言 (DDL):用于定义和修改数据库的结构,包括数据库、表、索引、视图等对象的创建、修改和删除。数据操作语言 (DML):用于…...
Azkaban其一,介绍、体系架构和安装
目录 一、简介 二、Azkaban的体系结构 三、Azkaban的安装步骤 1、上传,解压 2、生成mysql的元数据 3、配置web-server 4、配置exec-server 5、修改所有的.sh 的执行权限 一、简介 遇到了什么问题才会使用Azkaban ?比如: 想启动hadoop集群先启动…...
Seata 使用教程:全面解锁分布式事务管理
Seata 使用教程:全面解锁分布式事务管理 在当今分布式系统蓬勃发展的时代,微服务架构被广泛应用,随之而来的是分布式事务管理的难题。Seata 作为一款开源的分布式事务解决方案,为保障分布式系统的数据一致性提供了强有力的支持。本文将详细讲解 Seata 的使用方法,深入剖析…...
《learn_the_architecture_-_aarch64_exception_model》学习笔记
1.当发生异常时,异常级别可以增加或保持不变,永远无法通过异常来转移到较低的权限级别。从异常返回时,异常级别可能会降低或保持不变,永远无法通过从异常返回来移动到更高的权限级别。EL0级不进行异常处理,异常必须在比…...
密码学原理技术-第十一章-Hash Functions
文章目录 总结Why we need hash functionsDigital Signature with a Hash FunctionBasic Protocol for Digital Signatures with a Hash FunctionPrincipal input–output behavior of hash functions Security propertiesThe three security requirements of hash functionsWh…...
Golang 入门基础知识
快速入门 go 语言笔记,参考了各种大佬的 blog 。 一、下载安装 国内站点 :https://golang.google.cn IDE : Goland (2020.12月以后破解有些困难 见 zhile.io, 无法试用的话可以搜一个注册码,失效的也可以&…...
SQL把字符串按逗号分割成记录
在 SQL 中,可以通过以下方法将字符串按逗号分割,并将每个分割的值作为单独的记录插入到结果集中。以下是针对不同数据库系统的实现方法: 1. 使用 STRING_SPLIT(SQL Server 2016) STRING_SPLIT 是 SQL Server 提供的内置…...
HTML——26.像素单位
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>像素</title></head><body><!--像素:1.指设备屏幕上的一个点,单位px,如led屏上的小灯朱2.当屏幕分辨率固定时&…...
TIM的输出比较(PWM)
OC(Output Compare)输出比较 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形 每个高级定时器和通用定时器都拥有4个输出比较通道 初始化 1.开启RCC RCC_…...
李宏毅机器学习笔记-Transformer
目录 1. Seq2seq 2. encoder Transformer 中的 Block 结构 3. Decoder 4.Encoder和Decoder间的信息传递 5.Training 6.Tips 1. Seq2seq Transformer 是一个seq2seq的model。Seq2seq指的是input是一个序列,输出也是一个序列,输出的长度是由机器自己…...
【机器学习:三、常见的代价函数】
代价函数的选择与任务类型(回归、分类等)以及模型的具体目标密切相关。 回归任务中的代价函数 均方误差(Mean Squared Error, MSE) 公式: J ( θ ) 1 m ∑ i 1 m ( y i − y ^ i ) 2 J(\theta)\frac{1}{m}\sum_{i1}^m(y_i-\…...
React 数据是怎样传递的
写在前面 在 React 应用程序中,数据传递是非常重要的。它允许我们在组件之间共享信息和状态,从而构建出复杂的用户界面。本文将深入探讨 React 中的数据传递机制,包括 props、state 和 context API。我们还将通过实际例子来演示如何在项目中…...
Python入门教程 —— 高阶函数和装饰器
1.递归函数 什么是递归函数 如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。 递归函数的作用 举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n 解决办法1:使用循环来完成 def cal(num):result,i = 1,1while i <= num:result *= ii…...