【问题标题】:JMeter environment specific configurationJMeter 环境特定配置
【发布时间】:2014-04-25 22:35:57
【问题描述】:

我有几个 JMeter 测试计划应该在不同的环境中执行,比如 Dev、Test、UAT、Live。在每个测试计划中,我都希望有一种简单的方法来指定要使用的环境。每个环境都有很多配置如hostname、port、ssl-cert、用户名、密码、账号等测试数据。

我想要实现的一件事是在使用 JMeter GUI 或从构建脚本运行场景时轻松切换环境。

我的一个想法是使用“包含控制器”来包含另一个 jmx 文件,该文件具有用户定义变量和其他配置元素的列表。但是,JMeter 不支持包含文件名中的变量,因此我无法通过环境名称对场景进行参数化。 Include Controller 支持 JMeter 参数“includecontroller.prefix”,但不是很灵活,例如我无法从 JMeter GUI 更改它,我应该更改 JMeter 配置文件并重新启动它。

我尝试使用 Switch Controller,但没有成功,它不切换配置元素,仅切换采样器。

从测试场景中外部化特定于环境的配置并在多个场景之间共享的最佳实践是什么?

【问题讨论】:

    标签: java jmeter


    【解决方案1】:

    我建议用 JMeter 属性替换所有特定于环境的变量或值。请参阅以下功能以供参考:

    例如,您可以在 jmeter.properties 文件或 JMeter 命令行参数中定义一个名为 hostname 的属性,如下所示

    jmeter -Jhostname=169.140.130.120 -n -t yourscript.jmx -l yourscriptresults.jtl
    

    并在您的脚本中引用为:

    • ${__P(hostname,)}
    • ${__property(hostname,,)}

    有关详细信息,请参阅Apache JMeter Properties Customization Guide

    【讨论】:

    • 使用GUI时如何切换属性?
    • @kan,你使用 ${__P(hostname, "default_value")} 例如${__P(hostname,"localhost")},当你使用GUI时,改变参数默认值,当从批处理运行时你可以定义属性。
    • 对我来说太难了,在切换环境时我有大约 10 个参数需要更改 - 主机名、端口、协议、ssl 密钥、用户名、密码和其他一些特定于域的东西。
    • 请注意,您可以通过--propfile 参数指定包含属性的属性文件,而不是在命令行中指定每个属性。然后只需为每个环境保留一个单独的属性文件。
    • @Yeroc 这也不是很容易使用。每次需要切换到不同的环境,都需要重启,自定义命令行。
    【解决方案2】:

    就像提到的Manish Sapariya 一样,Parametrized Controller 对于为多个环境准备配置非常有用。我在以前工作的地方使用过它,现在在新的地方开始配置。刚开始有点工作,但后期维护起来很容易。上面提供的链接中有一些教程,但它不会考虑您一次只想运行一个环境。我将在下面描述一下,也许它会有用。 于是,一步一步慢慢来:

    1. 首先 - 您需要 两个线程组 - 一个用于环境配置文件(第一个屏幕截图中没有 1 个 - Env Profiler)和 一个用于测试案例,包括测试计划等(没有 2 - API 请求)。 后者必须被禁用,因为它是不应直接从此处执行的容器(右键单击 -> 禁用或 Ctrl+T)
    2. 那么您需要 用户定义的变量 元素(第 3 个) - 我正在使用其中的三个:
      • 首先用于定义将执行哪个环境(environmentType var)以及登录名/密码、令牌等。
      • 第二个带有测试所需项目的 ID
      • 第三个是 IP、端口、路径前缀等。

    这里最重要的是,此时我用变量名中的前缀将它们分开,所以在一个 UDV 元素中,我有诸如 dev.serverIP、dev.serverPort、preprod.serverIP 之类的变量依此类推(第二个屏幕截图)填充了与该环境相关的值。 此外,在其中一个 UDV 中,我有 environmentType 变量(前面提到过),默认值为“dev”(您可以在此处手动更改或在通过命令行/CI 或其他方式启动时提供不同的值)

    1. 现在在 Env Profiler 中我有 If Controllers(第一个屏幕截图上没有 4)。对于开发环境,我有(第一个屏幕上没有 5):

      "${environmentType}" == "dev"

    对于每个环境(如果是控制器),您必须像上面一样提供适当的条件。

    1. 每个 IfController 都包含前面提到的“jp@gc - 参数化控制器”(顺便说一下,您可以将其作为 Extras Set here 的一部分下载)。在每个参数控制器中,您分配给您在测试计划中使用的变量,特定于该环境的变量,例如名称:serverIP,值:${dev.serverIP} 用于开发环境(第三个屏幕截图)

    1. 现在是最后一件事 - 您要执行的测试和计划。
      • 在该禁用的线程组(API 请求)中,添加包含您的测试的 简单控制器,或从其他文件导入一些测试的 包含控制器
      • 当您进行这些测试时,对于您希望在该特定环境中运行的每个测试,您都必须添加 Module 控制器在参数化控制器中以及该测试的路径(下面的屏幕截图)

    差不多就是这样。现在维护:

    • 要添加新变量,您必须在 UDV 中添加前缀(dev.newVar、preprod.newVar)并填写相关值,然后在参数化控制器中添加适当的条目(那些 newVar = ${dev.newVar})和就是这样
    • 从其他测试计划添加新测试 - 添加包含该文件路径的包含控制器,并在每个参数化控制器中添加模块控制器,将它们定向到该包含控制器
    • 要添加新环境,只需复制您已有的环境,更改其 If contr.、参数化控制器并在 UDV 中填充值 这里的好处是,如果你想要,比如说,带有所有测试的 dev env,而另一个只有一些 somke 测试,你可以准备一个副本,更改 If 控制器以获取 env 变量的其他值(比如所有测试的 dev, devsmoke 用于烟雾测试)并在该新配置文件中添加或删除一些模块控制器。 当然,您可以稍微构建它,并且可以为系统的不同部分使用不同的线程以便于维护,只是不要忘记禁用这些作为容器工作的线程。

    我知道刚开始时要做的事情很多,但以后只要添加一些东西就不会那么糟糕了——无论如何这可能是最简单的方法。

    【讨论】:

    • 这几乎是我们开始使用的,但维护起来相当困难。首先,我们最终得到了一个超级测试计划,它将所有测试集中在一个地方,它不可扩展——难以在团队中协作。然后,有很多样板代码,例如newVar = ${dev.newVar}。然后,很难有一些默认值,例如表示“https”只在prod和uat中使用,其他环境都使用“http”。然后我们根据我的回答得到了 JS 代码,在我们的例子中:新 var - 文件中的一行,新的 env - 目录的副本,新的测试计划 - 将采样器添加到其中。
    • 很高兴知道。虽然在我的情况下它工作得很好,但是就像你说的,你需要一个测试来统治它们;),所以如果你有很多测试计划,那么维护起来可能会有点困难。我发现并且可能有用的另一件事是从 csv 文件加载变量 - 可能会帮助您解决问题 - jmeter-plugins.org/wiki/VariablesFromCSV
    • CSV 看起来更好,我不记得我们为什么不这样做。原因之一 - 我们的一些变量是多行文件(例如私有 rsa 密钥),在 CSV 中维护并不容易。但是很容易自定义 javascript 代码以从每个环境目录的文件中加载值。
    • 在 JMeter 4 中,我无法使用此选项。它破坏了我的脚本如此糟糕,以至于下次我什至无法打开它。我现在使用 JSR223 采样器脚本来完成它。 (见其他答案)
    【解决方案3】:

    作为当前的解决方案,我使用带有自定义 JavaScript 代码的 JSR223 采样器来设置来自外部属性文件的变量。类似的东西:

    var file = new java.io.File(args[0]);
    var props = new java.util.Properties();
    var is = new java.io.FileInputStream(file);
    props.load(is);
    is.close();
    for(var it = props.entrySet().iterator(); it.hasNext();)
    {
        var entry = it.next();
        vars.put(entry.getKey(), entry.getValue());
    }
    

    现在我只需将此代码添加为测试计划中的第一个采样器,并将特定于环境的文件路径作为采样器参数传递args[0],它将从文件中加载变量并将它们作为 JMeter 变量。

    【讨论】:

    • 唯一的缺点是这种负载发生在每个循环中。即使您设置了“已加载”标志,它仍然会在每个线程中执行加载,因为变量的范围是线程内的。因此,如果您有 200 个线程,那么您至少要加载 200 个文件。
    • @KeithTyler 文件通常由操作系统缓存。您是否实际测量过性能影响?我预测只有不到 1% 的测试套件有 200 个线程。
    【解决方案4】:

    如果您希望在 仅 GUI 中轻松生活,一种简单的方法是为每个环境复制您的 用户定义变量,并禁用除执行测试的环境,如下所示:

    【讨论】:

      【解决方案5】:

      我自己没用过,不过thisjmeter-pluing 可能对你有帮助。这是文档中的 sn-p

      Parameterized Controller since 0.1.0
      
      When your JMeter test plan tree becomes like a sequoia or a banyan, 
      you start feeling yourself like a monkey in a jungle, jumping from 
      branch to branch, trying to support this important test consistent. 
      You really need some way to have parameterized subroutines, to reuse 
      parts of test plan like regular programming language functions and 
      procedures.
      
      JMeter have out-of-box Module controller, but it has no parameters 
      to pass to, so if you need to call repeating sequence of the same 
      action with different parameters, your reflection in a mirror starts 
      morphing into monkey. Parameterized Controller helps you stay human 
      and sane.
      

      【讨论】:

      • 我看不出它有什么帮助。控制器是同一测试计划的一部分,而我需要在多个计划之间共享配置。例如。如果 UAT 环境更改其主机名,我不想更改新主机名的数百个测试计划。或者如果部署了一个新环境,我不想将它添加到数百个地方。此外,如果我理解正确的话,控制器不控制配置元素,只控制采样器。
      【解决方案6】:

      我也有同样的问题。我目前的方法是拥有几个用户定义的变量 (UDV) 元素,例如 DevVariables、TestVariables 等。每个都定义了相同的变量(主机名、端口等)。然后我手动禁用那些不使用的 UDV 元素。

      编辑:

      JMeter User Manual 状态 - “用户定义的变量元素允许您定义一组初始变量,就像在测试计划中一样。请注意,测试计划中的所有 UDV 元素 - 无论它们在哪里 - 在开始时都会被处理。”我不确定什么事件构成了“开始”,但这听起来好像您不能有条件地包含 UDV,至少不能通过控制器。

      您可以为每个测试计划设置一个 UDV,您可以在其中设置各种变量(主机等)。也许您可以使用一个丑陋的 JavaScript 函数来设置每个变量的值,该函数以传入的属性值为键。

      您可以尝试在Apache JMeter User mailing list 上提问。一定有办法做你想做的。

      【讨论】:

      • 也不太好。 UDV 是测试计划的一部分。我有几个测试计划应该共享相同的主机名、端口等。
      【解决方案7】:

      我使用带有 Groovy 的 JSR223 采样器来注册新参数。确保将 JSR223 采样器放在 Only Once Controller 中,因此它只运行一次(每个线程)。

      我在测试计划中为所有环境注册了所有变量,如下所示:

      TEST.user = 123
      TEST.url = test.mysite.com
      LOAD.user = 435
      LOAD.url = load.mysite.com
      

      然后我在启动时使用命令行参数指定要选择的环境,例如:-Denvironment=TEST

      我的 JSR223 脚本将在没有 TEST 的情况下将新变量添加到测试中。字首。在我的脚本中,我只引用了${user}

      这是要使用的脚本:

      JMeterVariables jmv = new JMeterVariables();
      
      for (Map.Entry item : vars.entrySet()) {
          if (item.getKey().startsWith(env)) {
              String keyname = item.getKey().substring(env.length()+1);
              String origval = vars.get(keyname);
              if (origval==null || (origval.equals("") && !item.getValue().equals(""))) {
                  jmv.put(keyname, item.getValue());
              }
          }
      }
      if (!jmv.entrySet().isEmpty()) {
          vars.putAll(jmv);
      }
      

      【讨论】:

        【解决方案8】:

        我意识到这个问题很老,但是如果您使用 GUI 并手动运行测试,一种非常简单的方法是为每个环境设置一个用户定义变量元素,并在运行测试时启用其中一个。但是我还是不明白为什么jmeter不支持有条件地设置UDV:s。

        【讨论】:

        • 正如我所提到的,这不允许在多个测试计划之间重用相同的变量。是的,它仅限于手动运行。启用/禁用对用户来说不是很友好。对我来说,通过脚本从外部 .properties 文件加载变量效果很好。
        猜你喜欢
        • 2013-08-16
        • 1970-01-01
        • 1970-01-01
        • 2017-12-08
        • 2020-04-16
        • 2014-09-07
        • 2014-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多