使用CSV文件读取测试数据

13
我需要使用JMeter测试一个网站的各种链接(无需登录),并使用数百个用户循环执行多次。我想将这些链接放在一个“CSV文件”中,以便从文件中读取要测试的所有链接。 如何完成这项任务?

为什么不先尝试在 jmeter 标签下搜索?这里已经有很多类似的问题了。 - Aliaksandr Belik
相关链接:http://sqa.stackexchange.com/q/5577/11978 - Pacerier
2个回答

22

准备一种包含测试参数列表的csv文件,并使用它来对测试采样器进行参数化,至少使用以下内容:

  1. CSV数据集配置

    请查看以下链接获取详细信息:

    如何让Jmeter使用CSV数据作为GET参数?
    使用Jmeter测试多个网站
    在Jmeter的httprequest路径中使用csv参数
    当使用CSV数据集配置时,强制线程使用相同的输入行

  2. Jmeter函数:

  3. jmeter-plugins从CSV中获取变量采样器。


1. 准备您的测试URL,保存在csv文件中,例如以下格式:

    url1
    url2
    ...
    urlN

确保测试URL不包含http://前缀(根据HTTP请求参数->服务器)。

2. 使用以下脚本架构:

    CSV Data Set Config:
    Filename: [path to your csv-file with test-urls]
    Variable Names: testURL
    Recycle on EOF?: True
    Stop thread on EOF?: False
    Sharing mode: Current thread

    Thread Group:
    Number of Threads: N
    Loop Count: M
            HTTP Request // your http call
            Server Name or IP: ${testURL} // use variable with extracted URL

这将启动N个用户,每个用户将从测试url列表中读取M个条目。如果M>测试url列表中的条目数,则用户在EOF时将循环使用该列表。

谢谢, 但我一直面临的问题是,测试在读取csv文件中的所有请求后就结束了。我无法为多个线程运行它,甚至无法在循环中运行它。你能帮忙吗? - user2003333
好的,请先更新您的回答并更清晰地说明您的问题,提供您的测试脚本模式。 - Aliaksandr Belik
我只是从CSV文件中读取测试链接。我想要做的就是使用多个线程/用户测试CSV文件中的链接(通过在线程组中指定线程数和循环次数)。我已经尝试完成这个测试,但主要问题是CSV数据集配置中"EOF"的设置。如果"Recycle on EOF"设置为False,则测试将停止在单个线程上。而如果"Recycle on EOF"设置为True,则测试将无限运行。所以,请问您如何处理这个问题? - user2003333
我已更新以上回答,提供了可工作的架构,但我真的不喜欢你的“给我代码”的方法。 - Aliaksandr Belik
为了获得我描述的构造(2个线程x 4个循环@列表中的4个URL-> 32个请求),您可以使用此处的模式:http://stackoverflow.com/a/13323433/993246。 即,在While控制器下使用CSV DataSet Config,并设置条件,直到来自CSV的字符串不是EoF时,回收EOF = False,在EOF上停止线程?= True,共享模式=当前线程组 - 这将在每个线程的每个循环中迭代所有的URL列表。像以前一样配置线程组(N线程,M循环)。 - Aliaksandr Belik
显示剩余3条评论

0
在其中一条评论中提到,你不能在每个循环中读取CSV超过一次。你可以创建多个线程,每个线程读取一次CSV文件,但是文件会被关闭,并且不会在下一个循环中读取。此外,如果你将CSV设置为循环使用,则CSV文件将无限期地重复读取。因此问题变成了如何循环读取CSV文件一定次数而不是无限次数?
我在另一篇帖子中发布了我的答案(https://dev59.com/hX3aa4cB1Zd3GeqPjuxa#64086009),但如果该链接在未来无法使用,我将复制并粘贴它。

我找不到一个简单的解决方案。最终我使用 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",

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

  1. 线程组

enter image description here


  1. 用户定义变量

这是可选的,但是文件路径可能会发生变化,我不想因为配置的更改而修改我的脚本。因此,我将CSV文件名存储在“用户定义变量”节点中。

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

如果您将CSV保存在与包含JMeter文件的目录不同的文件夹中,则需要提供绝对路径,然后稍微修改下面的beanshell脚本:您需要注释掉相对加载文件的行,并注释掉从绝对路径加载的行。

enter image description here


  1. 添加一个BeanShell Sampler来解析和存储CSV行

添加一个BeanShell Sampler,它将基本上接受一个路径,并将每一行解析并存储为一个变量。第一行将被存储为一个名为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


Beanshell脚本提取当前CSV行的数据
该脚本将针对每个CSV行运行一次。它会获取当前行并解析出其上的任何数据。您需要修改此脚本以获取所需的数据。在我的示例中,我只有2列,其中列1是“guestId”,列2是“address”。 __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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接