使用CSV数据集配置和EOF条件时出现问题

时间:2016-08-19 10:21:45

标签: jmeter

我有一个CSv数据集配置,我在while循环中使用。我在一个模块中有这个,并且在我的测试中多次使用同一个模块。

我的第一个问题是我已经使用这个条件设置了while循环:

${__javaScript("${data}"!="<EOF>")}

“data”是我的csv文件中的第一列。除了最后一次迭代,其中$ {data}被设置为“EOF”并且在其上执行了所有测试之外,这种方法很好。我希望它在此之前停止,而不是在所有测试都运行一次之后。

我的另一个问题是,当我稍后再次使用此模块时,$ {data}仍设置为“EOF”,并且根本不会运行任何测试。

3 个答案:

答案 0 :(得分:2)

要避免这个<EOF>位,只需将您的逻辑置于If Controller下并使用"${data}" != "<EOF>"作为“条件”

While Controller + IF

有关此问题和其他常见用例的详细说明,请参阅Using the While Controller in JMeter指南。

UPD。重复使用相同的CSV文件:

在1st While Controller之后和第二个While Controller之前添加Beanshell Sampler并在“脚本”区域中使用以下代码:

import org.apache.jmeter.services.FileServer;
FileServer.getFileServer().closeFile("yourfile.csv");
vars.put("data", "");

上述脚本将“关闭”原始CSV文件,以便稍后可以在脚本中重复使用,并“清除”${data}变量,因为它包含<EOF>值。

有关在JMeter测试中使用Beanshell脚本的详细信息,请参阅How to Use BeanShell: JMeter's Favorite Built-in Component指南。

答案 1 :(得分:0)

如果您使用循环控制器,CSV行的数量是迭代次数,您可以避免这种情况。只需将此代码放入Beanshell Sampler:

import org.apache.commons.io.FileUtils;

int lines = FileUtils.readLines(new File("/home/username/csv.file")).size();
vars.put("linesCount", String.valueOf(lines));

之后,您可以在循环控制器中使用lineCount

如果您的data变量需要恢复到原始状态,您可以将默认值存储在其他变量中,并在Loop结束时使用Beanshell pre / post proccesor将数据恢复为它。

编辑:

或者您可以在While Controller中插入If Controller并仅在数据不等于 EOF 时处理所有子元素:

${__javaScript("${data}"!="<EOF>")}

答案 2 :(得分:0)

以前的建议都没有对我重新使用csv文件。我最终做了一些不同的事情。它比我喜欢的复杂得多,但是可以。

我在另一篇文章(https://stackoverflow.com/a/64086009/4832515)中发布了我的答案,但是我会复制并粘贴它,以防将来链接失效。


我找不到一个简单的解决方案。我最终使用了beanshell脚本,该脚本使您可以使用与Java非常相似的代码来进行一些自定义操作。我以JMeter项目为例,演示了如何做到这一点(是的,这很复杂,考虑到我要做的就是重复读取CSV):


  1. 文件:

我的文件结构:

JMeterExample
|
⊢--JMeterTests.jmx             // the JMeter file
⊢--example.csv                 // the CSV file

我的CSV内容:

guest-id-1,"123 fake street",
guest-id-2,"456 fake street",
guest-id-3,"789 fake street",

所以在这个线程组中,我将只有1个用户,并且我将循环2次。我打算每CSV行发送1个请求。因此,总共应该发送6个请求。

  1. 线程组

enter image description here


  1. 用户定义的变量

这是可选的,但文件路径可能会更改,我不喜欢仅出于配置更改而更改脚本。因此,我将CSV文件名存储在“用户定义的变量”节点中。

如果将CSV文件存储在与JMeter测试相同的目录中,则只能指定文件名。

如果将CSV保存在除包含JMeter文件的目录之外的其他文件夹中,则需要提供一个绝对路径,然后对下面的beanshell脚本进行一些修改:您需要注释掉加载的行相对文件,并在从绝对路径加载的行中注释。

enter image description here


  1. 用于解析和存储CSV行的BeanShell Sampler

添加一个Beanshell采样器,该采样器将基本上采用一条路径,并将每一行解析并存储为变量。第一行将存储为名为csv_line_0的变量,第二行将存储为csv_line_1,依此类推。我知道这不是一个干净的解决方案,但是...我找不到执行此干净简单任务的任何干净简单方法。我在下面复制并粘贴了代码。

enter image description here

import org.apache.jmeter.services.FileServer;
import java.text.*;
import java.io.*;
import java.util.*;

String temp = null;

ArrayList lines = new ArrayList();

BufferedReader bufRdr;

ArrayList strList = new ArrayList();     

// get the file
try {
    // you can use this line below if your csvFilePath is an absolute path
    // File file = new File(${csvFilePath});

    // you can use this line below if your csvFilepath is a relative path, relative to where you saved this JMeter file
    File file = new File(org.apache.jmeter.services.FileServer.getFileServer().getBaseDir() + "/" + ${csvFilePath});

    if (!file.exists()) {
        throw new Exception ("ERROR: file " + filename + " not found");
    }

    bufRdr = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
} catch(Exception e){
    log.error("failed to load file");
    log.error(e.getMessage());
    return;
}

// For each CSV line, save it to a variable
int counter = 0;
while(true){
    try{
        temp = bufRdr.readLine();
        if(temp == null || temp.equals("<EOF>")){
            break;
         }
         lines.add(temp);
         vars.put("csv_line_" + String.valueOf(counter), temp);
        counter++;

        

    } catch(Exception e){
        log.error("failed to get next line");
        log.error(e.getMessage());
        break;
    }
}

// store the number of CSV lines there are for the loop counter
vars.put("linesCount", String.valueOf(lines.size()));

  1. 循环控制器

添加一个循环控制器,该循环控制器为每个CSV行循环一次。 ${linesCount}是CSV行数的计数,是根据上述beanShell脚本计算得出的。

enter image description here


  1. Beanshell脚本可从当前CSV行提取数据

此脚本将在每个CSV行中运行一次。它将抓取当前行,并解析出其中的任何数据。您必须修改此脚本才能获取所需的数据。在我的示例中,我只有2列,其中第1列是“ guestId”,而第2列是“地址”。

__jm__loopController__idx是JMeter为您定义的变量,并且是循环控制器的索引。变量名称为__jm__{loop controller name}__idx

enter image description here

String index = vars.get("__jm__loopController__idx");
String line = vars.get("csv_line_" + index);
String [] tokens = line.split(",");
vars.put("guestId", tokens[0]);
vars.put("address", tokens[1]);

  1. Http请求采样器

这是使用提取的数据的HTTP请求。

enter image description here


  1. 结果

运行此代码时,根据需要,我最终向我定义的端点发送了6个http请求。

enter image description here