这篇文章接上一篇(即 JMeter 第2篇)
文章里的每一句话都是我斟酌过的,我认为需要有注释或者插图的地方都会有相应的说明,因为水平能力问题依然不能保证每一句话的正确性。更多的是作为参考。
3. 测试计划的要素(Elements of a Test Plan)
本节描述测试计划的不同部分。
最小测试将包括测试计划、线程组和一个或多个采样器(Samplers)。
3.0 测试计划(Test Plan)
测试计划对象有一个名为“函数测试模式(Functional Testing)”的复选框。如果被选中,它将导致JMeter记录每个示例从服务器返回的数据。如果您在测试监听器中选择了一个文件,那么该数据将被写到文件中。如果您正在进行一个小的运行,以确保JMeter的配置正确,并且您的服务器正在返回预期的结果,那么这将非常有用。其结果是文件将迅速增长,JMeter的性能将受到影响。如果你正在做压力测试,这个选项应该是关闭的(默认是关闭的)。
如果您没有将数据记录到文件中,这个选项没有作用。
您还可以使用监听器(listener)上的Configuration按钮来决定保存哪些字段。
3.1 线程组(Thread Group)
线程组元素是任何测试计划的起点。所有的控制器和采样器都必须在一个线程组之下。其他元素,例如监听器,可以直接放在测试计划下,在这种情况下,它们将应用于所有线程组。顾名思义,线程组元素控制JMeter用于执行测试的线程数。线程组的控件允许您:
- 设置线程数
- 设置过渡时期(Ramp-Up Period)
- 设置执行测试的次数。
每个线程将完全独立于其他测试线程执行测试计划。多个线程用于模拟与服务器应用程序的并发连接。
过渡期间告诉JMeter要花多长时间来“过渡”到所选线程的总数。如果使用了10个线程,并且加速周期是100秒,那么JMeter将花费100秒来启动和运行所有10个线程。在前面的线程开始之后,每个线程将启动10(100/10)秒。如果有30个线程,并且加速周期为120秒,那么每个后续线程将被延迟4秒。
在测试开始时,需要足够长的时间来避免过大的工作负载,并且足够短,最后的线程在第一个线程完成之前就开始运行(除非一个线程想要这样做)。
Ramp-up =线程的数量做上下调整。
默认情况下,线程组被配置为在其元素中循环一次。
线程组还提供一个调度器(scheduler)。单击线程组面板底部的复选框,以启用/禁用额外字段,您可以在其中输入测试持续时间、启动延迟、运行的开始和结束时间。您可以配置持续时间(秒)(Duration (seconds))和启动延迟(秒)(Startup Delay (seconds))来控制每个线程组的持续时间以及它开始的秒数。当测试启动时,JMeter将在启动线程组的线程之前等待启动延迟(秒),并运行配置的持续时间(秒)。注意这两个选项覆盖了启动时间和结束时间。
另外(尽管不推荐,因为不太灵活)您可以使用另外两个字段启动时间和结束时间。当测试开始时,JMeter将在必要时等待,直到达到启动时间。在每个周期结束时,JMeter检查是否达到了结束时间,如果达到了,则停止运行,否则测试将继续进行直到循环结束。
3.2 控制器(Controllers)
JMeter有两种类型的控制器:采样器和逻辑控制器。这些驱动了测试的处理。
采样器告诉JMeter向服务器发送请求。例如,如果您想要JMeter发送一个HTTP请求,请添加一个HTTP请求采样器。您还可以通过向采样器添加一个或多个配置元素来定制一个请求。有关更多信息,请参见Samplers。
逻辑控制器允许您定制JMeter用来决定何时发送请求的逻辑。例如,您可以添加一个Interleave逻辑控制器来在两个HTTP请求采样器之间进行切换。有关更多信息,请参见逻辑控制器。
3.2.1 采样器(Samplers)
采样器告诉JMeter向服务器发送请求并等待响应。它们按照出现在树中的顺序进行处理。控制器可用于修改一个采样器的重复次数。
jmeter的样本器包含:
- FTP Request
- HTTP Request (can be used for SOAP or REST Webservice also)
- JDBC Request
- Java object request
- JMS request
- JUnit Test request
- LDAP Request
- Mail request
- OS Process request
- TCP request
每个采样器都有几个属性可以设置。您可以通过在测试计划中添加一个或多个配置元素来进一步定制一个采样器。
如果要向同一服务器发送同一类型的多个请求(例如,HTTP请求),请考虑使用缺省配置元素。每个控制器都有一个或多个默认元素(参见下面)。
请记住在测试计划中添加监听器,以便查看测试结果。
如果您想让JMeter对您的请求的响应执行基本验证,请向采样器添加一个断言(Assertion)。例如,在压力测试web应用程序时,服务器可能返回一个成功的“HTTP响应”代码,但是页面可能有错误,或者可能缺少部分。您可以添加断言来检查某些HTML标记、常见错误字符串等。JMeter允许您使用正则表达式创建这些断言。
内置逻辑控制器的列表(JMeter's built-in samplers)
3.2.2逻辑控制器(Logic Controllers)
逻辑控制器允许您定制JMeter用来决定何时发送请求的逻辑。逻辑控制器可以更改来自其子元素的请求的顺序。他们可以自己修改请求,导致JMeter重复请求,等等。
要理解逻辑控制器对测试计划的影响,请考虑以下测试树:
- Test Plan
* Thread Group
* Once Only Controller
* Login Request (an HTTP Request)
* Load Search Page (HTTP Sampler)
* Interleave Controller
* Search "A" (HTTP Sampler)
* Search "B" (HTTP Sampler)
* HTTP default request (Configuration Element)
* HTTP default request (Configuration Element)
* Cookie Manager (Configuration Element)
该测试树在 JMeter 的显示如下:
关于这个测试的第一件事是登录请求将只在第一次执行。后续的迭代将跳过它。这是由于仅一次控制器的影响。
登录后,下一个取样器将加载搜索页面--Load Search Page(想象一个用户登录的web应用程序,然后进入搜索页面进行搜索)。这只是一个简单的请求,没有经过任何逻辑控制器的过滤。
注意:Load Search Page在这里就是一个 HTTP 请求。
加载搜索页面之后,我们要进行搜索。实际上,我们想做两个不同的搜索。但是,我们希望在每次搜索之间重新加载搜索页面本身。我们可以通过4个简单的HTTP请求元素(加载搜索、搜索“A”、加载搜索、搜索“B”)来实现这一点。相反,我们使用Interleave Controller(交替控制器),它在每次测试中传递一个子请求。它保持排序(也就是说,它不是随机传递一个,而是“记住”它的子元素的位置)。交叉两个子请求可能有点过了头,但是很可能有8个或20个子请求。
注意属于Interleave控制器的HTTP请求默认值。假设“Search A”和“Search B”共享相同的路径信息(HTTP请求规范包括域、端口、方法、协议、路径和参数,以及其他可选项)。这是有意义的——这两个都是搜索请求,攻击相同的后端搜索引擎(比方说servlet或cgi-script)。我们可以将这些信息抽象为单个配置元素,而不是在路径字段中使用相同的信息配置两个HTTP Samplers。当Interleave控制器“传递”来自“Search A”或“Search B”的请求时,它将用HTTP默认请求配置元素的值填充空格。因此,我们为这些请求保留PATH字段为空,并将这些信息放入Configuration元素中。在这种情况下,这充其量只是一个小好处,但它展示了这个特性。
树中的下一个元素是另一个HTTP默认请求(HTTP default request),这次添加到线程组本身。线程组有一个内置的逻辑控制器,因此,它使用的配置元素与上面描述的完全一样。它填入任何经过的请求的空格。在web测试中,在所有HTTP取样器(HTTP Sampler )元素中保留域字段为空是非常有用的,而不是,将这些信息放到一个HTTP默认请求元素中,并添加到线程组中。通过这样做,您可以通过更改测试计划中的一个字段,在不同的服务器上测试应用程序。否则,你必须编辑每一个采样器。
最后一个元素是HTTP Cookie管理器。应该将Cookie管理器添加到所有web测试中——否则JMeter将忽略Cookie。通过在线程组级别添加它,我们确保所有HTTP请求将共享相同的cookie。
可以将逻辑控制器组合起来以实现各种结果。请参阅内置逻辑控制器的列表。
3.2.3 测试片段(Test Fragments)
Test Fragment元素是存在于与Thread Group元素相同级别的测试计划树上的一种特殊类型的控制器。它与线程组的区别在于,它不会执行,除非模块控制器或Include_Controller引用它。
这个元素纯粹用于测试计划中的代码重用
3.3 监听器(Listeners)
监听器提供对JMeter运行时收集的有关测试用例的信息的访问。图结果监听器在图上绘制响应时间。“查看结果树”监听器显示采样请求和响应的细节,并可以显示响应的基本HTML和XML表示。其他监听器提供汇总信息或聚合信息。
此外,监听器可以将数据定向到文件,以便以后使用。JMeter中的每个监听器都提供一个字段,用于指示要存储数据的文件。还有一个配置按钮,可用于选择保存哪些字段,以及使用CSV还是XML格式。
注意,所有监听器都保存相同的数据;唯一的区别在于数据在屏幕上显示的方式。
监听器可以添加到测试中的任何地方,包括直接在测试计划下。他们将只从其同级和子级的元素收集数据。
有几个监听器与JMeter一起出现。
3.4 定时器(Timers)
默认情况下,JMeter线程按顺序执行采样,不会暂停。我们建议您通过向线程组添加一个可用的计时器来指定延迟。如果不添加延迟,JMeter可能会在很短的时间内发出太多请求,从而使服务器不堪重负。
计时器将导致JMeter在其范围(scope)内的每个采样器之前延迟一定的时间。
如果您选择向一个线程组添加多个定时器,JMeter会在执行计时器应用程序的采样器之前,将计时器暂停的时间加起来。计时器可以作为采样器或控制器的子级添加,以限制应用它们的采样器。
要在测试计划中的单个位置提供暂停,可以使用测试动作(Test Action)采样器。
scope: 3.10节
3.5 断言(Assertions)
断言允许您断言从被测试的服务器接收的响应的事实。使用断言,您实际上可以“测试”应用程序正在返回预期的结果。
例如,您可以断言对查询的响应将包含某些特定的文本。您指定的文本可以是一个perl样式的正则表达式,您可以指出响应是包含文本,或者它应该与整个响应相匹配。
您可以向任何采样器(Sampler)添加断言。例如,可以向HTTP请求添加一个断言,该请求检查文本“</HTML>”。然后,JMeter将检查该文本是否存在于HTTP响应中。如果JMeter找不到文本,那么它将把它标记为失败的请求。
注意,断言适用于所有在其范围内(scope)的采样器。若要将断言限制为单个采样器,请将断言添加为采样器的子级。
要查看断言结果,请向线程组添加断监听器。失败的断言也将出现在树视图和表监听器中,并将计数到错误%年龄,例如在聚合和摘要报告中。
3.6 配置元件/素(Configuration Elements)
配置元件与采样器紧密配合。尽管它不发送请求(除了 HTTP(S) Test Script Recorder),但它可以添加或修改请求。
配置元件只能从放置元素的树分支中访问。例如,如果你把一个HTTP Cookie Manager放在一个简单的逻辑控制器,Cookie Manager只会访问HTTP请求控制器将在简单的逻辑控制器(见图1)。Cookie管理器都可以访问HTTP请求“Web Page 1”和“Web Page 2”,而不是“Web Page 3”。
此外,树分支中的配置元素比“父”分支中的相同元素具有更高的优先级。例如,我们定义了两个HTTP请求默认元素“Web Defaults 1”和“Web Defaults 2”。由于我们在循环控制器中放置了“Web Defaults 1”,因此只有“Web Page 2”可以访问它。其他HTTP请求将使用“Web Defaults 2”,因为我们将它放在线程组(所有其他分支的“父”)中。
3.7 前置处理器元素(Pre-Processor Elements)
前置处理器在发出采样请求之前执行一些操作。如果前置处理器附加到采样器元素,那么它将在采样器元素运行之前执行。前置处理器通常用于在示例请求运行之前修改其设置,或者更新未从响应文本中提取的变量。有关何时执行前置处理器的详细信息,请参阅scoping rules(3.10节)。
3.8 后置处理器元素(Post-Processor Elements)
后置处理器在采样请求完成后执行一些操作。如果后置处理程序附加到采样器元素,那么它将在采样器元素运行之后执行。后置处理器通常用于处理响应数据,通常用于从中提取值。有关何时执行后置处理器的详细信息,请参阅scoping rules(3.10节)。
3.9 执行顺序(Execution order)
- 配置元件/素(Configuration elements)
- 前置处理器(Pre-Processors)
- 定时器(Timers)
- 采样器(Sampler)
- 后置处理器(Post-Processors (unless SampleResult is null))
- 断言(Assertions (unless SampleResult is null))
- 监听器(Listeners (unless SampleResult is null))
请注意,定时器、断言、预处理器和后处理器只有在应用它们的采样器时才被处理。逻辑控制器和采样器按照它们出现在树中的顺序进行处理。其他测试元素根据找到它们的范围和测试元素的类型进行处理。[在类型中,元素按照它们出现在树中的顺序进行处理]。
例如,在下面的测试计划中:
- Controller
Post-Processor 1
Sampler 1
Sampler 2
Timer 1
Assertion 1
Pre-Processor 1
Timer 2
Post-Processor 2
执行的顺序是:
Pre-Processor 1
Timer 1
Timer 2
Sampler 1
Post-Processor 1
Post-Processor 2
Assertion 1
Pre-Processor 1
Timer 1
Timer 2
Sampler 2
Post-Processor 1
Post-Processor 2
Assertion 1
3.10 范围规则(Scoping Rules)
JMeter测试树包含分层和有序的元素。测试树中的一些元素是严格的层次结构(侦听器、配置元素、后处理器、前处理器、断言、计时器),而一些元素主要是有序的(控制器、采样器)。当您创建测试计划时,您将创建一个有序的示例请求列表(通过Samplers),它表示要执行的一系列步骤。这些请求通常是在控制器中组织的,这些控制器也是有序的。给定以下测试树:
请求的顺序是,1、2、3、4。
有些控制器影响子元素的顺序,您可以在组件引用中阅读这些特定的控制器。
其他元素层次。例如,断言在测试树中是分层的。如果它的父类是请求,那么它将被应用到该请求。如果它的父类是控制器,那么它将影响该控制器的所有后代请求。在下面的测试树中:
Assertion#1只应用于请求1,Assertion#2应用于请求2和3。
另一个例子,这次使用计时器:
在本例中,请求被命名为反映执行它们的顺序。计时器#1将应用于请求2、3和4(注意,对于分层元素,顺序是不相关的)。断言#1只适用于请求3。计时器#2将影响所有请求。
希望这些示例能够清楚地说明配置(分层)元素是如何应用的。如果您想象每个请求都被传递到树分支上,传递给它的父分支,然后传递给它的父分支,等等,并且每次收集父分支的所有配置元素,那么您将看到它是如何工作的。
配置元素头管理器、Cookie管理器和授权管理器与配置默认元素不同。配置默认元素的设置被合并到采样器可以访问的一组值中。但是,管理器的设置没有合并。如果在采样器的范围内有多个管理器,则只使用一个管理器,但是目前没有办法指定使用哪个管理器。
3.11 属性和变量 (Properties and Variables)
JMeter属性在JMeter.properties中定义(请参阅我的JMeter 第一篇文章第1.5节以了解更多细节)。
属性对于jmeter是全局的,并且主要用于定义一些默认的jmeter使用。例如,属性remote_hosts定义了JMeter远程运行的服务器。属性可以在测试计划中引用——参见Functions——read a property——但是不能用于特定于线程的值。
JMeter变量对每个线程都是本地的。每个线程的值可能相同,也可能不同。
如果一个变量被一个线程更新,那么只有该变量的线程副本被更改。例如,正则表达式提取器后置处理器将根据其线程读取的示例设置其变量,这些变量稍后可以被相同的线程使用。有关如何引用变量和函数的详细信息,请参见函数和变量。
注意,测试计划(Test Plan)和用户定义的变量配置元素定义的值在启动时对整个测试计划可用。如果同一个变量由多个UDV元素定义,那么最后一个变量将生效。一旦一个线程启动,初始的变量集将被复制到每个线程。其他元素如用户参数前置处理器或正则表达式提取器后置处理器可用于重新定义相同的变量(或创建新的变量)。这些重新定义只适用于当前线程。
setProperty函数可用于定义JMeter属性。这些是测试计划的全局变量,因此可以用来在线程之间传递信息——这是需要的。
变量和属性都是区分大小写的。
3.12 使用变量来参数化测试 (Using Variables to parameterise tests)
变量不需要改变——它们可以定义一次,如果不改变,就不会改变值。因此,您可以将它们作为在测试计划中经常出现的表达式的缩写。或者对于在运行过程中是常量的项,但是在运行之间可能会有所不同。例如,主机名或线程组中的线程数。
在决定如何构建测试计划时,请注意哪些项目在运行中是常量,但是在运行之间可能会发生变化。为这些变量确定一些变量名——可能使用命名约定,比如用C_或K_前缀,或者只使用大写字母,以区别于测试期间需要更改的变量。还要考虑哪些项需要在线程中是本地的——例如计数器或使用正则表达式后处理器提取的值。您可能希望对它们使用不同的命名约定。
例如,您可以在测试计划中定义以下内容:
HOST www.example.com
THREADS 10
LOOPS 20
您可以将这些在测试计划中引用为${HOST}${THREADS}等。如果以后想要更改主机,只需更改HOST变量的值。对于少量的测试来说,这样做很好,但是在测试很多不同的组合时就变得单调乏味了。一种解决办法是使用属性来定义变量的值,例如:
HOST ${__P(host,www.example.com)}
THREADS ${__P(threads,10)}
LOOPS ${__P(loops,20)}
然后,您可以更改命令行上的一些或所有值,如下所示:
jmeter … -Jhost=www3.example.org -Jloops=13