我有一个CSv数据集配置,我在while循环中使用。我在一个模块中有这个,并且在我的测试中多次使用同一个模块。
我的第一个问题是我已经使用这个条件设置了while循环:
${__javaScript("${data}"!="<EOF>")}
“data”是我的csv文件中的第一列。除了最后一次迭代,其中$ {data}被设置为“EOF”并且在其上执行了所有测试之外,这种方法很好。我希望它在此之前停止,而不是在所有测试都运行一次之后。
我的另一个问题是,当我稍后再次使用此模块时,$ {data}仍设置为“EOF”,并且根本不会运行任何测试。
答案 0 :(得分:2)
要避免这个<EOF>
位,只需将您的逻辑置于If Controller下并使用"${data}" != "<EOF>"
作为“条件”
有关此问题和其他常见用例的详细说明,请参阅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):
我的文件结构:
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个请求。
这是可选的,但文件路径可能会更改,我不喜欢仅出于配置更改而更改脚本。因此,我将CSV文件名存储在“用户定义的变量”节点中。
如果将CSV文件存储在与JMeter测试相同的目录中,则只能指定文件名。
如果将CSV保存在除包含JMeter文件的目录之外的其他文件夹中,则需要提供一个绝对路径,然后对下面的beanshell脚本进行一些修改:您需要注释掉加载的行相对文件,并在从绝对路径加载的行中注释。
添加一个Beanshell采样器,该采样器将基本上采用一条路径,并将每一行解析并存储为变量。第一行将存储为名为csv_line_0
的变量,第二行将存储为csv_line_1
,依此类推。我知道这不是一个干净的解决方案,但是...我找不到执行此干净简单任务的任何干净简单方法。我在下面复制并粘贴了代码。
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()));
添加一个循环控制器,该循环控制器为每个CSV行循环一次。 ${linesCount}
是CSV行数的计数,是根据上述beanShell脚本计算得出的。
此脚本将在每个CSV行中运行一次。它将抓取当前行,并解析出其中的任何数据。您必须修改此脚本才能获取所需的数据。在我的示例中,我只有2列,其中第1列是“ guestId”,而第2列是“地址”。
__jm__loopController__idx
是JMeter为您定义的变量,并且是循环控制器的索引。变量名称为__jm__{loop controller name}__idx
。
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]);
这是使用提取的数据的HTTP请求。
运行此代码时,根据需要,我最终向我定义的端点发送了6个http请求。