测试工具:JMeter 2.3.151Testing软件测试网+wr-P
T/W/]'n
数据库:Oracle 10G
:A;YL \be$d"y
c"u0 其他环境:JDK 1.6.0_05(也可以使用JDK1.4及以上版本)51Testing软件测试网M
iUr{;i]X5i3u
1.创建好的JMeter测试计划树形结构图如下:51Testing软件测试网X"n/kF7K2C&ky
2.在刚打开JMeter的时候,默认会存在两个节点,一个是“Test Plan”,点击这个节点,在右边的属性页面中,命名为“我们的数据库测试计划”51Testing软件测试网Yc e
\KR
在属性页的最下面,我们看到设置jar包所在路径的选项,默认存在一个选项"E:\software\develop\testunit\jMeter \jakarta-jmeter-2.3.1\lib",这个是我的机器中JMeter的lib目录,在这个例子中,Oracle的jdbc驱动也已经拷 贝到该目录下。
2vQ+W:}%y7@0内容导航 3.新增一个“Thread Group”,重命名为“使用变化的SQL来做数据库压力测试”。其 中,“Number of Threads”表示的是JMeter会同时创建多少个线程来进行压力测试,对于一个网站而言,也就是模拟一次存在多少个用户来访问该网站;而 “Ramp-Up Period(in seconds)”表示JMeter每个多少秒发动并发;“Loop Count”则是指配置好的并发情形发生多少次。
0U:f&T3y!v x1@m~z0 4.在“Thead Group”下创建一个“User Defined Variables”,即用户自定义变量,重命名为“我们定义的动态语句部分”,这里我们使用它来生成动态SQL语句,让用户每次访问数据库的SQL语句都不一样,这样减少Oracle数据库对相同SQL语句的缓存对测试结果所带来的影响。
h"]'\#_Ni!W.xn}0 变量定义的完整内容如下:
7E h,o E"s0 注:${__split(...)} 是JMeter中自带的拆分字符串为数组的函数,可以通过JMeter工具栏"Options"->"Function Helper Dialog"来打开函数代码辅助工具生成我们所需的函数调用。
]~o d'oB#gZ2Tj0 另外有个需要注意的问题是:在${__split(...)} 中,如果拆分字符串中的内容包含有符号",",一定得用符号"\"进行转义,否则可能被JMeter误认为是参数分隔符,会导致无法正确生成字符串数组。
1R2t%@ F"l@0内容导航 5.接下来是配置JDBC连接设置51Testing软件测试网5tI&D@
Q` X
6.创建一个具体的JDBC请求
SPk}#z0L GA] Y6ac
?0 "Query Type"中选择的是预编译语句;
2d#W+l)s5K!^"@0 SQL语句当中,动态内容的代码行是"and contains(p.p_name,?) > 0",这里的"?"就是预编译语句中的动态参数,在属性页下面的"Parameter Values"和"Parameter types"来指定,由于预编译语句在Java教程已有很多讲解,这里不再赘述。51Testing软件测试网u,v
s$[x z
注:这里有一个JMeter的函数"__V..."没有提到,将在后面说明另外一个JDBC调用测试的时候进行补充。51Testing软件测试网\ _)g$LC${
内容导航 7.创建三个监听器,可以从三个不同的层面来观察响应结果
n|R[_~1Z]]0 51Testing软件测试网6AW6zh fB
Hs
执行一下测试计划,我们来看看三个监听器所返回的结果是怎样的。
M,f'[?lJ!vvAK yj0
+? P-c s(}3Bnpg0 以上是表格方式查看响应结果的情况,可以看到通过表格可以查看某个范围内的响应时间和响应状态是否正常;
\x#|7F*\'J0 51Testing软件测试网-Tsg \_+bb6Q$g(W
kj)M+Io7h*nV0oN0 51Testing软件测试网 ay
ZF,}%ZBj e
以上三幅截图则是来自树形监听器,树形监听器在几种监听器中应该是最细致的,可以查看响应状态、时间、以及执行的SQL语句,乃至返回的结果均能进行验证。51Testing软件测试网"S(e o5db
y[ul;hY0 至于上面的图形监听器,可以宏观的观察SQL语句在压力测试下响应的平滑度,并且有一定的统计信息,能够观察平均响应时间等。
AfYYs8[2`$L2h%C0 现在我们来看另外一种方式编写我们的JDBC调用。就是使用JMeter提供的函数动态生成我们所需要不断变化的SQL语句部分。之所以需要这么做是为了方便我们观察执行的SQL语句内容。
|6J*d!qy/y0 在前面使用预编译的方式,传递动态参数的SQL语句执行的结果,大家已经看到过,在树形监听器中,我们观察到到执行过的SQL语句是:
^g(b0m-Qo0
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
SELECT *
FROM (SELECT tmp.*, ROWNUM rn
FROM (
select p.p_id, p.p_name, c.cmp_name
from test_product p, test_company c
where p.cmp_id = c.cmp_id
and contains(p.p_name, ?) > 0
--and (p.p_name like '%D%' or p.p_name like '%AIX%')
ORDER BY p.p_id desc
) tmp
WHERE 1 = 1 AND ROWNUM <= 100)
WHERE 1 = 1 AND rn >= 1 这样导致我们无法看出参数"?"当中表示的具体值是什么,这对我们在某些情况下确定SQL语句的性能是相当不利的。所以我们这里需要使用JMeter的动态函数特性。51Testing软件测试网OW1j2b*WR/^Kw4RX
我们创建第二个"JDBC Request"节点,而后禁用"产品名 全文关键字 JDBC Request",将新创建的"JDBC Request"重命名为"产品名 like JDBC Request",将其中的SQL语句改写为:51Testing软件测试网oe?C
C*X-k&s)P1@G V|
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
SELECT *
FROM (SELECT tmp.*, ROWNUM rn
FROM (
select p.p_id, p.p_name, c.cmp_name
from test_product p, test_company c
where p.cmp_id = c.cmp_id
AND ( ${__V(smt_${__Random(1,4,rnd)})} )
ORDER BY p.p_id desc
) tmp
WHERE 1 = 1 AND ROWNUM <= 100)
WHERE 1 = 1 AND rn >= 1 这里核心的部分就是代码行"AND ${__V(smt_${__Random(1,4,rnd)})} "。"${__Random(1,4,rnd)}"用来生成随机数,取值范围在1到4之间,而"__V(...)"函数帮助我们转 义"smt_${__Random(1,4,rnd)}"生成的内容,很类似于JavaScript中的"eval"函数。
I?0b;M%Dl
b:X!kjg0 例如"${__Random(1,4,rnd)}"生成随机数为1,则"smt_${__Random(1,4,rnd)}"对应的内容为"smt_1","__V"将获取数组变量"smt"中的第一个元素,于是生成的SQL语句如下:51Testing软件测试网&E kLX ANk
这里我们可以清楚的看到所执行的SQL语句。51Testing软件测试网
t-V5r h
R
后记
nH:u7oK2@j^6b0 本例中我们使用了JMeter附带的函数"__split"和"__V","__Random"等等,文章对于这些函数的描述可能不够完整,亦可能不够准确,更多详尽的解释,大家可以参考JMeter官方文档。51Testing软件测试网9[6?/_h gDa7\+e;d