CLI 性能测试





5.00/5 (2投票s)
使用 Java 进行命令行接口 (CLI) 性能测试
引言
我在多个地方查找关于使用 Java 进行命令行界面 (CLI) 性能测试的知识,但问题是我找不到任何有建设性的分步过程。这让我想记录下这些过程,以便将来能帮助到他人。
我之前已经使用 CURL(您可以使用任何 CLI)实现了这一点,并在 LoadRunner 中进行了执行,以测试其可扩展性、可靠性和各种其他性能。
先决条件
- 预期您对 Java 开发有所了解。您可能不是一个出色的开发者,但应该比“Hello World!”程序了解得多一点。
- 您应该了解性能测试工具,例如 LoadRunner。
- 您应该拥有任何 Java 开发 IDE,例如 NetBeans。
要求
- 在此示例中,我使用了 CURL,但您可以使用任何 CLI 应用程序进行性能测试。要了解更多关于 CURL 的信息,请访问 cURL and libcurl
- 在使用任何 CLI 应用程序之前,请仔细阅读其文档以及它为完成任务所需的各种参数。
- 您需要性能测试工具,在本例中我们将使用 LoadRunner。这不限于 LoadRunner,也可以用于其他性能测试工具。
- 您需要 Java 开发 IDE,在本例中我们将使用 NetBeans。这不是必需的,但它将帮助我们编写无错误的代码,并稍后复制粘贴到性能测试工具中。当您在 NetBeans 中编写 Java 代码时,与在 LoadRunner 中编写代码相比,您会获得一些优势。
- 轻松将 API 添加到 NetBeans 项目中。
- NetBeans 会自动导入所需的包。
- 以无忧的方式调试代码。
- 毫无麻烦地使代码无错误。
注意:在开始编写 Java 代码之前,请确保您在 NetBeans 中编写的所有内容都可以被复制,并且 LoadRunner 能够理解。
性能场景
假设您有一个 CLI 应用程序(例如 CURL.exe),该应用程序由您项目的开发团队提供,您负责提供该 CLI 在 100 个用户并发运行 2 小时,并且有 10 秒思考时间下的性能指标。
事务详情
- 使用 CURL 登录远程服务器
- 使用 CURL 从您的计算机上传文件到远程服务器
- 使用 CURL 从远程服务器下载文件到您的计算机
开始在 NetBeans 中编写代码
- 在 NetBeans 中,点击 文件 -> 新建项目。
- 选择 Java -> Java Application,然后点击 下一步。
- 输入项目名称为“Sumit_Cli_Example”,选择项目位置,选中“创建主类”复选框,然后点击 完成。
- 将创建新项目。
注意
CLI(在本例中为CURL.exe)或下面的代码将与您的性能测试脚本不匹配。本博文仅帮助您了解如何使用 Java 对 CLI 执行性能测试。您将有不同的 CLI,它们会有不同的参数和属性,您需要使用这些参数和属性编写 Java 代码在 LoadRunner 中执行。
理解您的 CLI 的最佳方法是查阅其文档,该文档应由开发团队在交付 CLI 时提供。
package sumit_cli_example;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Sumit_Cli_Example
{
static Runtime objRuntime = null;
static Process objProcess = null;
static String strCommand = null;
static boolean boolStatus = false;
static BufferedReader objInputStream = null;
static BufferedReader objErrorStream = null;
static String strInputStream = "";
static String strErrorStream = "";
static String strXAuthToken = "";
static String strCurlPath = "D:\\curl\\";
public static void main(String[] args)
{
try
{
objRuntime = Runtime.getRuntime();
/*Authentication*/
strCommand = strCurlPath + "curl.exe -v -H \"X-Storage-User: system1:" +
"root1\" -H \"X-Storage-Pass: password1\" http://xxxxxx.com:7777/auth/v1.0";
objProcess = objRuntime.exec(strCommand);
strInputStream = "";
boolStatus = false;
objInputStream = new BufferedReader(new InputStreamReader(objProcess.getInputStream()));
while (strInputStream != null)
{
strInputStream = objInputStream.readLine();
if(strInputStream != null)
{
System.out.println(strInputStream);
if(strInputStream.contains("X-Auth-Token") == true)
{
boolStatus = true;
strXAuthToken = strInputStream.replace("< X-Auth-Token: ", "");
System.out.println("X-Auth-Token:" + strXAuthToken);
}
}
}
/*Above transaction has failed if boolStatus is false*/
if(boolStatus == false)
{
System.out.println("X-Auth-Token was not found");
}
else
{
System.out.println("Success");
}
/*Uploading file*/
strCommand = strCurlPath + "curl.exe -X PUT -T D:\\curl\\sumitbiswas.txt" +
" -H \"X-Auth-Token: " + strXAuthToken +
"\" http://xxxxxx.com:8080/v1/AUTH_admin/Container_1/";
objProcess = objRuntime.exec(strCommand);
strInputStream = "";
boolStatus = false;
objInputStream = new BufferedReader(new InputStreamReader(objProcess.getInputStream()));
while (strInputStream != null)
{
strInputStream = objInputStream.readLine();
if(strInputStream != null)
{
System.out.println(strInputStream);
if(strInputStream.contains("201 Created") == true)
{
boolStatus = true;
}
}
}
/*Above transaction has failed if boolStatus is false*/
if(boolStatus == false)
{
System.out.println("Uploading file was not successful");
}
else
{
System.out.println("Success");
}
/*Downloading file*/
strCommand = strCurlPath + "curl.exe -o D:\\curl\\sumitbiswas.txtxyz -H \"X-Auth-Token: " +
strXAuthToken + "\" http://xxxxxx.com:8080/v1/AUTH_admin/Container_1/sumitbiswas.txt";
objProcess = objRuntime.exec(strCommand);
strInputStream = "";
boolStatus = false;
objInputStream = new BufferedReader(new InputStreamReader(objProcess.getInputStream()));
while (strInputStream != null)
{
strInputStream = objInputStream.readLine();
if(strInputStream != null)
{
System.out.println(strInputStream);
if(strInputStream.contains("201 sent") == true)
{
boolStatus = true;
}
}
}
/*Above transaction has failed if boolStatus is false*/
if(boolStatus == false)
{
System.out.println("Downloading file was not successful");
}
else
{
System.out.println("Success");
}
}
catch(Exception ex)
{
System.out.println(ex);
}
}
}
运行项目,它应该能够成功运行。它应该连接到远程服务器、上传文件然后下载文件。一旦您对输出和期望的结果满意,就可以将其复制粘贴到 LoadRunner 中了。
注意
您可以使用 .getErrorStream()
代替 .getInputStream()
来获取错误输出流,并以与上述代码相同的方式读取它。
将以上代码复制粘贴到 LoadRunner 中
在本节中,我们将使用 **Java Vuser 协议**将 NetBeans 中可用的代码复制粘贴到 **LoadRunner** 中。然后,我们将修改代码,使其可被 LoadRunner 识别。我们还将添加参数和其他功能,以便我们可以对 CLI 进行负载测试,让 100 个用户并发运行 2 小时。
import lrapi.lr;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Actions
{
Runtime objRuntime = null;
Process objProcess = null;
String strCommand = null;
boolean boolStatus = false;
BufferedReader objInputStream = null;
BufferedReader objErrorStream = null;
String strInputStream = "";
String strErrorStream = "";
String strXAuthToken = "";
String strCurlPath = "D:\\curl\\";
public int init() throws Throwable
{
try
{
lr.start_transaction("CLI_01_Login");
objRuntime = Runtime.getRuntime();
/*Authentication*/
strCommand = strCurlPath + "curl.exe -v -H \"X-Storage-User: " +
"<UserNames>\" -H \"X-Storage-Pass: password1\" http://xxxxxx.com:7777/auth/v1.0";
objProcess = objRuntime.exec(strCommand);
strInputStream = "";
boolStatus = false;
objInputStream = new BufferedReader(new InputStreamReader(objProcess.getInputStream()));
while (strInputStream != null)
{
strInputStream = objInputStream.readLine();
if(strInputStream != null)
{
System.out.println(strInputStream);
if(strInputStream.contains("X-Auth-Token") == true)
{
boolStatus = true;
strXAuthToken = strInputStream.replace("< X-Auth-Token: ", "");
System.out.println("X-Auth-Token:" + strXAuthToken);
}
}
}
/*Above transaction has failed if boolStatus is false*/
if(boolStatus == false)
{
lr.error_message("X-Auth-Token was not found");
lr.end_transaction("CLI_01_Login", lr.FAIL);
}
else
{
lr.message("Success");
lr.end_transaction("CLI_01_Login", lr.PASS);
}
lr.think_time(10);
}
catch(Exception ex)
{
System.out.println(ex);
}
return 0;
}
public int action() throws Throwable
{
try
{
lr.start_transaction("CLI_02_UploadFile");
/*Uploading file*/
strCommand = strCurlPath + "curl.exe -X PUT -T D:\\curl\\sumitbiswas.txt" +
" -H \"X-Auth-Token: " + strXAuthToken +
"\" http://xxxxxx.com:8080/v1/AUTH_admin/Container_1/";
objProcess = objRuntime.exec(strCommand);
strInputStream = "";
boolStatus = false;
objInputStream = new BufferedReader(new InputStreamReader(objProcess.getInputStream()));
while (strInputStream != null)
{
strInputStream = objInputStream.readLine();
if(strInputStream != null)
{
if(strInputStream.contains("201 Created") == true)
{
boolStatus = true;
}
}
}
/*Above transaction has failed if boolStatus is false*/
if(boolStatus == false)
{
lr.error_message("Uploading file was not successful");
lr.end_transaction("CLI_02_UploadFile", lr.FAIL);
}
else
{
lr.message("Success");
lr.end_transaction("CLI_02_UploadFile", lr.PASS);
}
lr.think_time(10);
lr.start_transaction("CLI_03_DownloadFile");
/*Downloading file*/
strCommand = strCurlPath + "curl.exe -o D:\\curl\\sumitbiswas.txtxyz " +
"-H \"X-Auth-Token: " + strXAuthToken +
"\" http://xxxxxx.com:8080/v1/AUTH_admin/Container_1/sumitbiswas.txt";
objProcess = objRuntime.exec(strCommand);
strInputStream = "";
boolStatus = false;
objInputStream = new BufferedReader(new InputStreamReader(objProcess.getInputStream()));
while (strInputStream != null)
{
strInputStream = objInputStream.readLine();
if(strInputStream != null)
{
if(strInputStream.contains("201 sent") == true)
{
boolStatus = true;
}
}
}
/*Above transaction has failed if boolStatus is false*/
if(boolStatus == false)
{
lr.error_message("Downloading file was not successful");
lr.end_transaction("CLI_03_DownloadFile", lr.FAIL);
}
else
{
lr.message("Success");
lr.end_transaction("CLI_03_DownloadFile", lr.PASS);
}
lr.think_time(10);
}
catch(Exception ex)
{
System.out.println(ex);
}
return 0;
}
public int end() throws Throwable
{
return 0;
}
}
注意:请检查是否已从 LoadRunner 中删除了 static 关键字,因为它不是从静态 main 方法调用的。已定义事务名称。已为用户名提供了参数。通常,参数由 {} 分隔,但在此处设置为 <>。这可以在 VuGen 的 工具 -> 常规选项 -> 参数化 中配置。已提供思考时间和最后但同样重要的是,事务已分类为 init()
、action()
和 end()
。
curl 路径或文件路径是相对于脚本运行的机器的。请根据负载生成器机器进行相应更改。运行 LoadRunner 脚本 2 次迭代,检查它是否成功执行了操作。至此,我们的 LoadRunner 脚本已准备就绪,可以根据定义的场景在 LoadRunner 控制器中执行。
关注点
请注意,当您使用 Windows 机器时,请将字符串标记为双引号("),而在使用 Linux 机器时,请将字符串标记为单引号(')。
历史
这是第一个版本。