JMeter:如何在多个线程组循环中重用/重新打开CSV? [英] JMeter: How to reuse/reopen a CSV in several Thread-Group-Loops?

查看:97
本文介绍了JMeter:如何在多个线程组循环中重用/重新打开CSV?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在JMeter中,我有一个CSV用户列表,每个用户都应该上传一定数量的文件.文件在第二个CSV文件中列出.每个用户都必须上传所有文件.由于服务器无法一次处理所有线程,因此我将线程"组设置为使用X个用户并循环Y次,因此最终所有用户都将上载所有文件.

In JMeter I have a CSV list of users, and each of these users is supposed to upload an amount of files. The files are listed in a second CSV. Each user must upload all files. Since the server can't handle all threads at once I set the Thread group to use X users and loop Y times, so that in the end all users upload all files.

 Test plan
 - CSV Data Set Config (contains users) --> Recycle = false, Stop thread on EOF = false
 - Thread Group (X users, Y loops)
 - - While Controller ( ${__javaScript("${uploadFile}"!="<EOF>")} )
 - - - CSV Data Set Config (contains files) --> Recycle = false, Stop thread on EOF = false
 - - - HTTP Request (upload file)

对于第一个循环,一切正常:X线程已启动.在每个线程中,都打开了文件CSV,每个用户都上载了所有文件.然后第二个线程组循环开始,下一个用户从用户CSV中获取,但是当那些线程进入包含文件CSV的while循环时,他们什么也没有上传.似乎他们从第一个循环中重新使用了文件CSV,并认为CSV是EOF或类似的东西.

For the first loop this all works OK: X threads are started. In each of the threads the files-CSV is opened and each users uploads all files. Then the second Thread-Group-loop starts, the next users are taken from the users-CSV, but when those threads come to the while-loop containing the files-CSV, they don't upload anything. It seems like they re-use the files-CSV from the first loop, and consider the CSV to be EOF or something like that.

例如,具有3个线程/用户和2个循环的结果如下:

As an example, the results with 3 threads/users and 2 loops looks like this:

**first loop**
user 1
  upload file 1
  upload file 2
  upload file 3
user 2
  upload file 1
  upload file 2
  upload file 3
user 3
  upload file 1
  upload file 2
  upload file 3
**second loop**
user 4
user 5
user 6

第二个循环中的用户也应浏览CSV文件并上传文件.知道我在做什么错吗? 在此先感谢!

The users from the second loop should also go through the files-CSV and upload the files. Any idea what I am doing wrong? Thanks in advance!!

推荐答案

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

I couldn't find a simple solution to this. I ended up using beanshell scripts, which let you use code very similar to java to do some custom stuff. I made an example JMeter project to demonstrate how to do this (yes it's ridiculously complicated, considering all I want to do is repeat the CSV read):

  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个请求.


so in this thread group, I'm going to just have 1 user, and I'll loop 2 times. I intend to send 1 request per CSV line. So there should be 6 requests sent total.

  1. 线程组

  1. 用户定义的变量

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

This is kind of optional, but the filepath is subject to change, and I don't like changing my scripts just for a change in configuration. So I store the CSV filename in a "User Defined Variables" node.

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

If you are storing the CSV file in the same directory as your JMeter test, you can just specify the filename only.

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

If you are saving the CSV in a folder other than the directory containing your JMeter file, you will need to supply an absolute path, and then slightly modify the beanshell script below: you'll need to comment out the line that loads the file relatively, and comment in the line that loads from an absolute path.

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

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

Add a Beanshell Sampler which will basically take in a path, and parse & store each line as a variable. The first line will be stored as a variable called csv_line_0, the 2nd line will be csv_line_1 and so on. I know it's not a clean solution but... I can't find any clean simple way of doing this clean simple task. I copied and pasted my code below.

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脚本计算得出.

Add a Loop Controller that loops once for each CSV line. ${linesCount} is a count of the number of CSV lines and is calculated from the above beanShell script.

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

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

This script will run once per CSV line. It will go and grab the current line, and parse out whatever data is on it. You'll have to modify this script to get the data you want. In my example, I only had 2 columns, where column 1 is a "guestId", and column 2 is an "address".

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

__jm__loopController__idx is a variable JMeter defines for you, and is the index of the loop controller. The variable name is __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]);


  1. Http请求采样器

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

Here's the HTTP request that's using the data extracted.

  1. 结果

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

When running this, as desired, I end up sending 6 http requests over to the endpoint I defined.

这篇关于JMeter:如何在多个线程组循环中重用/重新打开CSV?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆