# JMeter官方文档：3. 测试计划中的元素




[《JMeter官方文档--翻译计划》](/2017/08/24/jmeter-translation-plans/) [原文地址](http://jmeter.apache.org/usermanual/test_plan.html)

## 3.测试计划中的元素（elements of a test plan）
----

本节描述测试计划不同的部分。

最小测试将包括测试计划、线程组和一个或多个采样器。

### 3.0 测试计划（Test Plan）
----
测试计划对象有一个叫 __“功能测试”__ 的复选框，如果选择了，它将导致JMeter记录从服务器返回的每个示例的数据。如果您在测试监听器中选择了一个文件，那么这些数据将被写入文件。如果您正在执行一个小的运行，以确保JMeter的配置正确，并且您的服务器正在返回预期的结果，那么这将非常有用。其结果是，文件将快速增长，JMeter的性能将受到影响。如果您正在进行压力测试(默认情况下是off)，则该选项应该关闭。

如果您没有将数据记录到文件中，则该选项没有任何区别。

您还可以使用侦听器(listener)的 __配置__ 按钮来决定要保存哪些字段。

### 3.1 线程组（Thread group）
----
线程组元素是任何测试计划的起点。所有控制器和采样器必须在线程组下。其他元素，例如侦听器，可以直接置于测试计划之下，在这种情况下，它们将适用于所有的线程组。顾名思义，线程组元素控制JMeter用来执行测试的线程的数量。线程组的控件允许:

* Set the number of threads： 设置线程数
* Set the ramp-up period：设置过渡时期
* Set the number of times to execute the test：设置执行测试的次数

每个线程将完全独立地执行测试计划，完全独立于其他测试线程。多个线程用于模拟与服务器应用程序的并发连接。

这个过渡时期告诉JMeter要花多长时间才能“加速”到选择的全部线程数。如果使用10个线程，并且过渡时期是100秒，那么JMeter将花费100秒来启动所有10个线程并运行。在前面的线程开始后，每个线程将开始10(100 / 10)秒。如果有30个线程和一个上升周期120秒，则每个连续线程将延迟4秒。

需要足够长的时间来避免在测试开始时工作负载过大，足够短的时间，最后的线程在第一个线程完成之前就开始运行(除非有人希望发生这样的情况)。
从增加的线程数开始，根据需要调整向上或向下。

默认情况下，线程组被配置为通过它的元素循环一次。

线程组还提供了一个 __调度器__ 。单击线程组面板底部的复选框，以启用/禁用额外的字段，在该字段中您可以输入测试持续时间、启动延迟、运行的开始和结束时间。您可以配置 __持续时间（秒）__ 和 __启动延迟（秒）__ 来控制每个线程组的持续时间和启动后的秒数。当开始测试时，JMeter会等待 __启动延迟（秒）__ 之前启动的线程组的线程和运行配置的持续时间（秒）的时间。注意，这两个选项覆盖了 __开始时间__ 和 __结束时间__ 。

或者(尽管不建议不是很灵活)，您可以使用其他两个字段 __开始时间__ 和 __结束时间__。当测试开始时，JMeter将在必要时等待，直到到达开始时间。在每个循环的末尾，JMeter检查是否已经到达了结束时间，如果是，则停止运行，否则测试将继续运行下去，直到达到迭代限制。

### 3.2 控制器（Controllers）
----
JMeter有两种控制器：采样器和逻辑控制器。这些驱动测试的处理。

采样器告诉JMeter发送请求到服务器。例如，如果你想要JMeter发送http请求添加一个HTTP请求取样器。您还可以通过向采样器中添加一个或多个配置元素来定制请求。更多信息，参见：采样器。

逻辑控制器让你自定义JMeter决定要发送请求时用什么样的逻辑。例如，您可以在两个HTTP请求采样器之间添加交错逻辑控制器。有关更多信息，参见：逻辑控制器。

##### 3.2.1 采样器（Samplers）
----

采样员告诉JMeter向服务器发送请求并等待响应。它们按照它们在树中出现的顺序进行处理。控制器可用于修改采样器的重复次数。

JMeter采样器包括：

* FTP请求
* HTTP请求(也可以用于SOAP或REST Webservice)
* JDBC请求
* Java对象请求
* JMS请求
* JUnit测试请求
* LDAP请求
* 邮件请求
* 操作系统进程请求
* TCP请求

每个采样器都有几个可以设置的属性。您可以通过在测试计划中添加一个或多个配置元素来自定义采样器。

如果要将同一类型的多个请求（例如HTTP请求）发送到同一服务器，请考虑使用默认配置元素。每个控制器都有一个或多个Defaults元素（见下文）。

请记住在测试计划中添加一个侦听器，以查看和/或将请求的结果存储到磁盘。

如果您有兴趣让JMeter对您的请求的响应进行基本验证，那么向sampler添加一个 __断言__ 。例如，在压力测试web应用程序时，服务器可能返回一个成功的“HTTP响应”代码，但是页面可能有错误，或者可能缺少部分。您可以添加断言来检查某些HTML标记、常见的错误字符串等。JMeter允许使用正则表达式创建这些断言。

[JMeter的内置采样](http://jmeter.apache.org/usermanual/component_reference.html#samplers)

#### 3.2.2 逻辑控制器（Logic Controllers）
----
逻辑控制器让您自定义JMeter决定要发送请求时的逻辑。逻辑控制器可以改变来自子元素的请求顺序。他们可以自己修改请求，导致JMeter重复请求，等等。

要了解逻辑控制器对测试计划的影响，请考虑以下测试树:

* 测试计划
  * 线程组
    * 仅一次控制器
      * 登录请求(一个[HTTP请求](http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request))
    * 加载搜索页面(HTTP采样器)
    * 交替控制器
      * 搜索“A”(HTTP取样器)
      * 搜索“B”(HTTP取样器)
      * HTTP请求默认值(配置元件)
    * HTTP默认请求(配置元件)
    * Cookie管理器(配置元件)

这个测试的第一件事是，登录请求将仅在第一次执行。随后的迭代将跳过它。这是由于[Once Only Controller](http://jmeter.apache.org/usermanual/component_reference.html#Once_Only_Controller)（只有一次控制器）的影响。

登录后，下一个采样器加载搜索页面(想象一个用户登录的web应用程序，然后进入搜索页面进行搜索)。这只是一个简单的请求，没有经过任何逻辑控制器的过滤。

加载搜索页面后，我们要进行搜索。实际上，我们想做两种不同的搜索。但是，我们希望在每次搜索之间重新加载搜索页面本身。我们可以通过4个简单的HTTP请求元素(加载搜索、搜索“A”、加载搜索、搜索“B”)来实现这一点。相反，我们使用[Interleave Controller](http://jmeter.apache.org/usermanual/component_reference.html#Interleave_Controller)控制器每次通过测试传递一个子请求。它保持了排序(即它不会随机地传递一个，而是“记住”它的子元素的位置)。插入两个子请求可能会被过度使用，但是可能会有8个或20个子请求。

注意，HTTP Request Defaults属于Interleave Controller。假设“Search A”和“Search B”共享相同的路径信息(HTTP请求规范包括域、端口、方法、协议、路径和参数，以及其他可选项)。这是有意义的——两者都是搜索请求，命中相同的后端搜索引擎(比如servlet或cgil - script)。我们可以将这些信息抽象为单个配置元素，而不是在路径字段中使用相同的信息配置两个HTTP Samplers。当Interleave控制器“传递”来自“Search A”或“Search B”的请求时，它将从HTTP默认请求配置元素的值中填充空白。因此，我们将这些请求的路径字段留空，并将这些信息放入配置元素中。在这种情况下，这充其量只是一个小的好处，但它展示了这个特性。

树中的下一个元素是另一个[HTTP默认请求](http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request_Defaults)，这个时间添加到线程组本身。线程组有一个内置的逻辑控制器，因此，它使用这个配置元素，就像上面描述的那样。它填入经过的任何请求的空格。在web测试中，将所有HTTP Sampler元素中的域字段保留为空是非常有用的，相反，将这些信息放入HTTP默认请求元素中，添加到线程组中。通过这样做，您可以通过改变测试计划中的一个字段来测试您在不同服务器上的应用程序。否则，你必须编辑每一个采样器。

最后一个元素是[HTTP Cookie管理器](http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Cookie_Manager)。所有web测试都应该添加一个Cookie管理器——否则JMeter将忽略Cookie。通过在线程组级别添加它，我们确保所有HTTP请求将共享相同的cookie。

逻辑控制器可组合实现各种结果。请参阅内置逻辑控制器列表（ [built-in Logic Controllers](http://jmeter.apache.org/usermanual/component_reference.html#logic_controllers).）。

#### 3.2.3 测试片段（Test Fragments）
----
测试片段元素是一种特殊类型的控制器，它存在于与线程组元素相同级别的测试计划树中。它与线程组不同，因为它没有被执行，除非由 [模块控制器](http://jmeter.apache.org/usermanual/component_reference.html#Module_Controller) 或 [包含控制器](http://jmeter.apache.org/usermanual/component_reference.html#Include_Controller) 引用。

此元素纯粹用于测试计划中的代码重用。

### 3.3 侦听器（Listeners）
----
当JMeter运行时，侦听器提供对测试用例的信息JMeter的访问。图的结果是监听器将响应时间绘制在图上。“视图结果树”侦听器显示了sampler请求和响应的详细信息，可以显示响应的基本HTML和XML表示。其他侦听器提供汇总信息或聚合信息。

此外，侦听器可以将数据直接引导到文件中以供以后使用。JMeter中的每个监听器都提供一个字段来指示要存储数据的文件。还有一个配置按钮，可以用来选择保存哪些字段，以及是否使用CSV或XML格式。

```
注意，所有侦听器都保存相同的数据;唯一的区别在于数据在屏幕上呈现的方式。
```

可以在测试的任何地方添加监听器，包括直接在测试计划下。他们只从他们的水平或低于他们水平的元素收集数据。

JMeter这里有些[监听器](http://jmeter.apache.org/usermanual/component_reference.html#listeners)。

### 3.4 定时器（Timers）
----
默认情况下，JMeter线程在不暂停的情况下依次执行samplers。我们建议您通过向线程组添加一个可用的计时器来指定延迟。如果您不添加延迟，JMeter会在很短的时间内发出太多的请求，从而使服务器不堪重负。

定时器将导致JMeter在每个采样器在其[范围](http://jmeter.apache.org/usermanual/test_plan.html#scoping_rules)内延迟一定的时间。

如果您选择将多个计时器添加到线程组，JMeter将使用计时器的总和，并在执行计时器所应用的samplers之前暂停此时间。计时器可以添加为samplers或控制器的子元素，以限制应用程序的采样器。

为了在测试计划中提供一个单独的位置，可以使用[Test Action](http://jmeter.apache.org/usermanual/component_reference.html#Test_Action)采样器。

### 3.5 断言（Assertions）
----
断言允许你断言你正在测试的服务器返回的结果。通过使用断言，你基本上可以断定你的程序返回的结果是否是你期望的值。

例如，你可以断言一个查询的返回结果将包含一些特定的文本，特定的文本可以是perl语言的正则表达式，也可以是返回结果中的一部分，或者整个返回值。

你可以为任何Sampler(取样器)添加断言，例如，您可以向“HTTP请求”中添加一个断言，用来检查文本 __“< / HTML >”__ 。然后，JMeter将检查文本‘< / HTML >’是否存在于HTTP响应中。如果JMeter不能找到文本，那么它将标记为请求失败。

```
注意：断言适用于所有的取样器，但是要将断言限制到具体的某一个取样器上，要将断言作为取样器的子元素添加。
```

要查看断言结果，请向线程组添加一个“断言结果”，断言失败的也会现在树视图和表侦听器中，并将统计到汇总、汇总报告的误差率里面。

### 3.6 配置元件（Configuration Elements）
---
一个配置元件与采样器紧密合作。虽然它不发送请求([HTTP(S)测试脚本记录器](http://jmeter.apache.org/usermanual/component_reference.html#HTTP(S)_Test_Script_Recorder) __除外__)，但它可以添加或修改请求。

一个配置元件只能从放置元素的树分支中访问，例如，如果你把一个“HTTP Cookie管理器”放在一个简单控制器中，只有在简单控制器内，Cookie管理器才可以访问HTTP请求控制器(参见图1)。Cookie管理器可以访问HTTP请求“页面1”和“页面2”，而不是“页面3”。

此外，树分支中的配置元件的优先级高于“父”分支中的相同元素，例如，我们定义二个“HTTP请求默认值”元件："HTTP请求默认值 1"和"HTTP请求默认值 2",由于我们将"HTTP请求默认值 2"放在一个循环控制器中的，故只有"页面2"可以访问它。其他HTTP请求将使用“HTTP请求默认值 2”，因为我们将它放入了线程组(所有其他分支的“父”)。

![](http://img.testclass.net/http-config-example.png)

图1 测试计划显示了配置元件的可访问性

注意：配置元件中的"用户定义的变量"与其它元件是有区别的。它是在测试开始时进行处理的，而不管我们将它放在哪里。为了简单起见，建议将它放在线程组的开始处。

### 3.7 前置处理器（Pre-Processor Elements）
----
预处理器在执行Sampler(采样器)请求之前执行一些操作。如果一个预处理器被附加到一个采样器元件上，那么它就会在这个采样器元件运行之前执行。预处理程序通常用于在运行前修改采样品请求的设置，或者更新不是从响应文本中提取的变量。有关何时执行预处理器的详细信息，请参阅3.10小节。

### 3.8 后置处理器（Post-Processor Elements）
----
在采样器请求完成后，后处理器执行一些操作。如果一个后处理器被附加到一个采样器元件上，那么它将在Sampler元件运行后执行。后处理器通常用于处理响应数据，通常是从它提取值。有关何时执行后处理程序的详细信息，请参阅3.10小节。

### 3.9 执行顺序（Execution order）
----
0.配置元件
1.前置处理器
2.定时器
3.采样器
4.后置处理器(假设采样器结果不为空)
5.断言(假设采样器结果不为空)
6.监听器(假设采样器结果不为空)

```
请注意，定时器、断言、预处理器和后处理器只在有一个他们应用的采样器的情况下进行处理。逻辑控制器和采样器
按它们出现在树中的顺序进行处理。其他测试元件根据被发现的范围和测试元件的类型进行处理。[在一种类型中，
元素按其出现在树中的顺序进行处理]。
```

例如：在下面的测试计划中：

* 控制器
  * 后置处理器 1
  * 采样器 1
  * 采样器 2
  * 定时器 1
  * 断言 1
  * 前置处理器 1
  * 定时器2
  * 后置处理器 2

执行顺序是：

```
  前置处理器 1
  定时器 1
  定时器2
  采样器1
  后置处理器1
  后置处理器2
  断言1

  前置处理器1
  定时器1
  定时器2
  采样器2
  后置处理器1
  后置处理器2
  断言1
```

### 3.10 范围规则（Scoping Rules）
----

JMeter测试树包含分层和有序的元素。测试树中的有些元件是严格分层的(监听器、配置元件、后置处理器、前置处理器、断言、定时器),而有些元素是有序的(控制器、采样器)。当您创建测试计划时，您将创建一个有序的采样请求列表(通过采样器)，它表示将要执行的一系列步骤。这些请求通常都是在控制器中进行组织的，它们也是有序的。例如，给定以下测试树:

![](http://img.testclass.net/scoping1.png)
图：测试树示例

请求顺序将是：网页1，网页2，网页3，网页4

一些控制器影响其子元素的顺序，您可以在[组件](http://jmeter.apache.org/usermanual/component_reference.html)参考文献中了解这些特定的控制器。

其他元素是分层的。例如，断言在测试树中是分层的。如果它的父元素是一个请求，那么它将被应用到该请求。如果它的父节点是一个控制器，那么它将影响到该控制器的后代的所有请求。在以下测试树中:

![](http://img.testclass.net/scoping2.png)
图：分层的示例

断言1只应用于网页1，而断言2应用于网页2和3。

另一个例子，这次使用计时器:
![](http://img.testclass.net/scoping3.png)
图：复杂的例子

在这个例子中，请求的命名可以反映它们将被执行的顺序。定时器1将应用于网页2、3和4(注意顺序如何与分层元素无关)。断言1只适用于网页3。定时器 2将影响所有网页。

希望这些示例能清楚地说明如何配置应用到的(分层)元素。如果你想象成每个请求都被传递到了树分支、再到其父节点、最后到父节点的父节点等等，并且每次都收集父节点的所有配置元件，你将明白它是如何工作的。

```
配置元件中的头管理器、Cookie管理器和授权管理器的处理方式与配置默认元件不同。配置默认元件的设置
被合并到一组采样器可以访问的值中。但是，管理器的设置并没有被合并。在一个采样器的范围内，如果不止
一个管理器，但是只使用到了一个管理器，目前没有办法确定使用了哪个管理器。
```

### 3.11 属性和变量（Properties and Variables）
----
JMeter属性在JMeter.属性中定义(查阅 [开始-配置JMeter](http://jmeter.apache.org/usermanual/get-started.html#configuring_jmeter)获得更多细节)。

属性是jmeter的全局属性，主要用于定义一些jmeter使用的默认值。例如，属性 __remote_hosts__ 定义了JMeter将试图远程运行的服务器。属性可以在测试计划中引用（参见[函数—读取属性](http://jmeter.apache.org/usermanual/functions.html#__property)），但不能用于线程特定的值。

JMeter变量仅仅局限于每个线程。每个线程的值可能相同，也可能不同。如果一个变量被一个线程更新，那么只有变量的这个线程副本被更改。例如，[正则表达式提取器](http://jmeter.apache.org/usermanual/component_reference.html#Regular_Expression_Extractor)后置处理器将根据线程读取的采样器来设置变量，这些变量后面可以被相同的线程使用。有关如何引用变量和函数的详细信息，请参见[函数和变量](http://jmeter.apache.org/usermanual/functions.html)。

注意，[测试计划](http://jmeter.apache.org/usermanual/component_reference.html#Test_Plan)定义的值和[用户定义变量](http://jmeter.apache.org/usermanual/component_reference.html#User_Defined_Variables)的配置元件在启动时可用于整个测试计划。如果同一个变量被多个UDV元素定义，那么变量等于最后一次设置的值。一旦线程启动，变量初始集将被复制到每个线程。其他元素，如[用户参数](http://jmeter.apache.org/usermanual/component_reference.html#User_Parameters)预处理器或[正则表达式](http://jmeter.apache.org/usermanual/component_reference.html#Regular_Expression_Extractor)提取器后置处理器可能被用来重新定义相同的变量(或创建一个新变量)。这些重新定义只适用于当前线程。

可以使用[setProperty](http://jmeter.apache.org/usermanual/functions.html#__setProperty)函数来定义JMeter属性。这些在测试计划中是全局的，因此可以用于在线程之间传递信息——应该是需要的。

```
变量和属性都是大小写敏感的。
```

### 3.12 使用变量来参数化测试（Using Variables to parameterise tests）
----

变量不是一定要改变值，它们可以定义一次，如果单独使用，则不会改变值。因此，您可以使用它们作为在测试计划中频繁出现的表达式的短手，或者是在运行期间的一个常量，但在运行期间可能会有所改变。例如，主机名，或线程组中的线程数。

在决定如何构建一个测试计划时，要注意运行时哪些项是常量，哪些项在运行期间可能会发生变化。为这些常量取一些变量名称（可以使用命名约定），比如：用C_或K_来作为前缀或者全使用大写字母，来与在运行期间会发生变化的变量进行区分。还要考虑哪些项目需要本地的线程——例如使用正则表达式后处理器提取的计数器或值。您可能希望使用不同的命名约定。

除此之外，你需要考虑哪些项目仅仅局限于一个线程，例如使用”正则表达式“后置处理器提取的计数器或值。您可能希望使用不同的命名约定。

例如，您可以在测试计划中定义以下内容:

```
HOST             www.example.com
THREADS          10
LOOPS            20
```

您可以在测试计划中用类似$ { HOST} 、 $ { THREADS }来引用这些变量，如果您后面想要更改主机，只需更改主机变量的值。对于少量的测试，这样做很好，但是在测试许多不同的组合时就变得单调乏味了。因此，可以使用属性来定义变量的值，例如:

```
HOST             ${__P(host,www.example.com)}
THREADS          ${__P(threads,10)}
LOOPS            ${__P(loops,20)}
```

然后你可以在命令行，用如下命令来更改部分或全部值，如下:
```
jmeter … -Jhost=www3.example.org -Jloops=13
```




原始封面

![课程图片](https://images.unsplash.com/photo-1482406611936-43ea538e39d4?w=300)


