51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 3828|回复: 2
打印 上一主题 下一主题

[原创] LoadRunner JAVA Vuser协议开发性能测试脚本

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2009-9-22 09:31:08 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
引言: 最近性能测试项目中,尤其在测试应用系统接口时,经常用到JAVA VUSER这个协议,请见以下文章,希望对有需要的同学们提供帮助与支持!

众所周知,Java语言是一门非常适合网络开发的语言,用 Java语言进行性能测试脚本开发将会大大提高测试开发效率。LoadRunner中提供了对Java虚拟用户的支持。Java虚拟用户依托于JDK,这大大扩充了LoadRunner的脚本开发功能。测试人员既可以用Java虚拟用户来测试基于Java的应用系统的性能,又可以使用Java语言的强大开发脚本功能来测试其他平台的系统性能。

本章将和读者一起探索LoadRunner的Java世界,重点讨论如何开发Java自定义的虚拟用户脚本。本章主要内容如下:

n  认识Java虚拟用户

n  Java脚本开发基础

n  Java算法测试案例

7.1  认识Java虚拟用户

7.1.1  Java虚拟用户协议

Java虚拟用户脚本主要有Java Vuser、Corba-Java、RMI-Java、EJB等类型。这些类型的虚拟用户脚本均可以用Java语言来手工编写。下面将对各类Java虚拟用户简单地进行介绍。

Java Vuser

Java Vuser是自定义的Java虚拟用户脚本,脚本中可以使用标准的Java语言。这种虚拟用户不可以录制,只能采用纯手工编写,其适用范围和C Vuser一样,非常广泛。

本章主要探讨Java Vuser的开发方法。

Corba-Java

Corba-Java类型的虚拟用户主要用来测试用Java编写的、使用Corba应用程序或小程序的性能,用户可以先运行VuGen录制的脚本,然后使用标准的Java库函数以及LoadRunner特有的Java方法来增强该脚本。

RMI-Java

RMI-Java 虚拟用户适用于测试RMI(远程方法调用)Java应用程序或小程序。选择RMI-Java 用户进行录制,VuGen可以创建对应的Java脚本。完成录制后,可以使用JDK或自定义类,通过标准的Java代码来增强或修改脚本,还可以通过特定于LoadRunner的Java方法增强该脚本。

EJB

EJB虚拟用户专门用于测试Enterprise Java Beans对象。采用EJB协议,VuGen会自动创建脚本以测试EJB功能,无需录制或编程,这和标准的Java Vuser明显不同。

在使用EJB协议类型的虚拟用户生成脚本前,需要指定 JNDI属性和关于应用程序服务器的其他信息。LoadRunner的EJB检测器首先扫描应用程序服务器并确定哪些EJB可用;接着选择要测试的 EJB,LoadRunner将生成要测试每个EJB方法的脚本,并为每个方法创建事务,便于度量其性能并找出问题。

需要注意的是,创建EJB虚拟用户测试脚本必须在应用程序服务器主机上安装LoadRunner EJB检测器,而且检测器必须处于活动状态。EJB检测器是一个独立的代理程序,必须将其安装在要扫描查找EJB的每一台计算机上。安装EJB检测器前,计算机上还需要安装有效的JDK环境。

本书中将以Java Vuser为例来讲解Java虚拟用户的开发和使用方法。Corba-Java、RMI-Java、EJB、Jacada Vuser等类型的虚拟用户使用方法可以参考LoadRunner的联机帮助手册,但是其手工脚本的开发方法与Java Vuser是一样的。

在“新建虚拟用户”对话框中的“自定义”或“全部协议”类别下选择“Java Vuser”即可创建空的Java Vuser脚本,如图7-1所示。

在自动生成的脚本中,vuser_init、 vuser_end部分没有任何内容,Actions部分生成的脚本如图7-2所示。对于Java类型的虚拟用户,可以编辑Actions类,而 init、end部分则不可以进行编辑。在Actions类中,有三个方法init、action和end,通常在init方法中编写初始化代码、在 action方法中编写业务流程、在end方法中编写诸如释放资源之类的代码。

Java Vuser脚本中可以放置任何标准Java代码,这也是Java虚拟用户的魅力所在。

7.1.2  Java虚拟用户适用范围

LoadRunner完全支持C语言,原则上可以用C语言实现任何想要录制的功能。但是C语言的特点决定了这样做是不现实的:一是性能测试脚本开发成本非常高;二是很多企业的测试人员开发基础不好。因此,性能测试开发多选用C++、C#、Java等面向对象语言——因为这类语言既有成熟的集成开发工具,又有庞大的类库来支撑,测试脚本开发速度会更快。下一章将重点介绍如何用.NET来开发性能测试脚本。

Java虚拟用户适用范围非常广,归纳起来主要有两大类:一类是不太适合录制的业务功能点的性能测试,例如网页上Http文件的下载过程、视频播放等;另一类是基于Java语言开发的应用系统的性能测试,这类应用更适合采用Java虚拟用户进行测试。

用Java Vuser实现无法录制的测试需求

这类测试需求往往关注于对服务器产生的压力,重点测试在一定压力下服务器的负载情况,为评估、部署、调优系统提供参考。在这类测试工作中,Java的作用仅是一门语言,用于辅助测试人员完成测试程序的开发。

在性能测试工作中,不能录制的测试点很多,主要有以下几类:

l  含有控件的Web应用

在Web应用中,很多包含一些插件的浏览器应用经常不能录制。这类应用往往涉及很多协议,因此录制起来不是特别方便。

对于这类应用,可以用Java语言调用其功能来完成用户行为的模拟。

l  一些和媒体播放、文件下载等相关的应用

媒体播放或文件下载等过程的录制往往不容易控制,如果是应用基于P2P的协议,则会更加复杂。因此,这类测试只能由测试人员开发虚拟用户脚本来完成。

用Java Vuser测试基于Java语言的应用系统性能

相比前面,基于Java语言开发的应用系统,在性能测试中采用Java虚拟用户更显得“门当户对”。这类虚拟用户主要应用在下面两类测试中:

l  核心算法或业务的执行效率

对银行、电信等大型的基于J2EE的架构应用系统中,开发阶段的性能测试是必不可少的。为了降低后期遇到性能问题的风险,往往在开发阶段进行一些核心业务的性能测试。这些核心业务或要求较高的执行效率,或者要求支持较多用户的并发。因此,可以利用Java Vuser来测试这些业务的执行效率。

l  Java应用中不能录制的业务模块

很多时候,一些J2EE架构的业务系统用 LoadRunner录制起来不是特别方便,例如一些Java智能客户端程序。这时可以手工编写测试代码,完成测试任务。与非Java应用相比,Java 应用中不能录制的业务功能更适合采用Java虚拟用户,因为可以直接对一些方法进行调用。

由于Java语言的强大功能,Java虚拟用户的应用远不止上面这些,读者可以慢慢挖掘。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2
回复

使用道具 举报

该用户从未签到

3#
 楼主| 发表于 2009-9-22 10:48:03 | 只看该作者
谢谢楼上的脚本分享!

LR java vuser主要是针对服务端的
在这个协议下的性能测试,还会出现TPS逐渐下降的情况,被测应用服务器、LR controller客户端强大的前提下,都会出现这类情况。
事务改成循环之后,TPS逐渐下降的情况即消失。

[ 本帖最后由 GeorgeWangLC 于 2009-9-22 10:51 编辑 ]
回复 支持 反对

使用道具 举报

该用户从未签到

2#
发表于 2009-9-22 10:29:19 | 只看该作者
LZ好意,但好象少了一个例子。。我发下我以前项目中的测试脚本,是一个springupload的例子:(java vuser的缺点在于需要负载机性能强大内存大,而且主要是针对服务端的压力测试)
/*
* LoadRunner Java script. (Build: 759)
*
* Script Description:
*                     
*/
import java.math.BigDecimal;
import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ce.dpos.sale.payment.model.PaymentMannerDO;
import com.ce.dpos.sale.payment.model.PaymentTypeDO;
import com.ce.dpos.sale.remoteservice.IRemoteUploadService;
import com.ce.dpos.sale.trade.model.PaymentItemDO;
import com.ce.dpos.sale.trade.model.SaleDO;
import com.ce.dpos.sale.trade.model.SaleItemDO;

import com.ce.component.log4ce.core.BizLogInfo;
import com.ce.component.log4ce.core.BizOperationResult;
import com.ce.component.log4ce.core.BizOperationType;
import lrapi.lr;

public class Actions {
        public SaleDO saleDO;

        public BizLogInfo bizLogInfo;

        public IRemoteUploadService remoteUploadService;

        public int init() {
                ApplicationContext ctx = new ClassPathXmlApplicationContext(
                                "/invoker-client.xml");
                remoteUploadService = (IRemoteUploadService) ctx
                                .getBean("remoteUploadServiceProxy");
                saleDO = new SaleDO();
                // saleDO.setChangeItems(arg0);
                saleDO.setEdit();
                // saleDO.setFavourableAuthUser(1, 1, 2);
                // saleDO.setIdNull();
                saleDO.setIsUpdateStock(false);
                saleDO.setIsUpload(true);
                saleDO.setSaleCode("lijian123");
                saleDO.setSaleCreateTime(new Date());
                saleDO.setSaleId(1);
                saleDO.setSalePayTime(new Date());
                saleDO.setTerCode("001");
                // saleDO.setTradeSettings(arg0);
                saleDO.setUserId(2);
                saleDO.setWarehouseId(1);

                SaleItemDO saleItemDO = new SaleItemDO();
                saleItemDO.setAuthUserId(2);
                saleItemDO.setEdit();
                saleItemDO.setMerBarCode("barCode400101865");
                saleItemDO.setMerchandiseId(1);
                saleItemDO.setMerCode("00101");
                saleItemDO.setMerName("可乐-1287854501");
                saleItemDO.setSaleId(1);
                // saleItemDO.setSdAppStrategyState(arg0);
                saleItemDO.setSdCreateTime(new Date());
                // saleItemDO.setSdId(arg0);
                saleItemDO.setSdIdNull();
                saleItemDO.setSdMyid(1);
                saleItemDO.setSdOriginalPrice(BigDecimal.valueOf(4.29));
                // saleItemDO.setStrategyApplyId(arg0);
                // saleItemDO.setStrategyId(arg0);
                saleItemDO.setWrhId(1);
                saleItemDO.modifyAmount(BigDecimal.valueOf(1));
                saleItemDO.modifyPrice(BigDecimal.valueOf(4.29));

                PaymentItemDO paymentItemDO = new PaymentItemDO();
                paymentItemDO.setEdit();

                // paymentItemDO.setPiAdditionalInfo(arg0);
                paymentItemDO.setPiCreateTime(new Date());
                paymentItemDO.setPiExchangeRate(BigDecimal.valueOf(1));
                paymentItemDO.setPiExchangeSum(BigDecimal.valueOf(4.29));
                // paymentItemDO.setPiId(arg0);
                paymentItemDO.setPiPaySum(BigDecimal.valueOf(4.29));
                paymentItemDO.setPiPaytype(1);
                paymentItemDO.setPiState(Byte.valueOf("2"));
                paymentItemDO.setPiTicketAmount(0);
                // paymentItemDO.setPiWarrant(0);
                paymentItemDO.setSaleId(1);

                PaymentMannerDO paymentMannerDO = new PaymentMannerDO();
                paymentMannerDO.setCanChange(true);
                paymentMannerDO.setEdit();
                paymentMannerDO.setExchangeRate(BigDecimal.valueOf(1));
                paymentMannerDO.setIsBasicCurrency(true);
                paymentMannerDO.setPmCode("RMB");
                paymentMannerDO.setPmDeleted(false);
                paymentMannerDO.setPmDisabled(false);
                paymentMannerDO.setPmId(1);
                paymentMannerDO.setPmName("人民币");
                paymentMannerDO.setPmPlugin("Plugin001");
                paymentMannerDO.setPtId(1);
                paymentMannerDO.setShareProfitCalc(true);

                // paymentMannerDO.setValidEndDatetime(arg0);
                paymentMannerDO.setValidForever(true);
                // paymentMannerDO.setValidStartDatetime(arg0);

                PaymentTypeDO paymentTypeDO = new PaymentTypeDO();
                paymentTypeDO.setPtId(1);
                paymentTypeDO.setPtName("现金");
                paymentMannerDO.setTypeDO(paymentTypeDO);

                paymentItemDO.setPaymentMannerDO(paymentMannerDO);
                saleDO.addItem(saleItemDO);

                bizLogInfo = new BizLogInfo();
                bizLogInfo.setBizDescription("Unspecified biz description.");
                bizLogInfo.setBizOperationResult(BizOperationResult.SUCCESS);
                bizLogInfo.setBizOperationType(BizOperationType.UNKNOWN);
                bizLogInfo.setBizType("Unspecified");
                bizLogInfo.setClientAddress("192.168.102.9");
                // bizLogInfo.setExceptionMessage(arg0);
                bizLogInfo.setId(Long.parseLong("1"));
                bizLogInfo.setOperatingTime(new Date());
                bizLogInfo.setOperation("测试");
                bizLogInfo.setOperationMessage("测试");
                bizLogInfo.setOperator("lijian");
                bizLogInfo.setSystemAddress("1");
                bizLogInfo.setSystemName("88888888");
                bizLogInfo.setThreadId(Long.parseLong("100"));
                return 0;
        }// end of init

        public int action() {

                lr.start_transaction("uploadSale");

                try {
                        remoteUploadService.uploadSale(saleDO);
                } catch (Exception e) {
                        // TODO: handle exception
                        lr.end_transaction("uploadSale", lr.FAIL);
                }
                lr.end_transaction("uploadSale", lr.AUTO);

                lr.start_transaction("uploadLog");

                try {

                        remoteUploadService.uploadLog(bizLogInfo);
                } catch (Exception e) {
                        lr.end_transaction("uploadLog", lr.FAIL);
                }
                lr.end_transaction("uploadLog", lr.AUTO);

                return 0;
        }// end of action

        public int end() {
                return 0;
        }// end of end
}

以上只是脚本部分,如果不知道怎么设置,可以去查看相关资料(其实只用把所依赖的包放到classpath下就行了)
回复 支持 反对

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-19 04:16 , Processed in 0.072858 second(s), 28 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表