代码如下怎么定位进行js性能测试代码

五步定位性能瓶颈 - 张鱼 - 博客园
 1、着手在前:理清数据流向,数据流程分解
  通过绘制数据流向图,以便清晰的列出所有可能出现瓶颈的位置,避免在分析过程中遗漏可能的瓶颈点。
  系统架构分解&&水池模型
  要查找瓶颈,首先要对系统的架构有详细的了解,清楚知道所有可能成为瓶颈的位置。只有这样才能在遇到问题是合理的设计,对流程的各个步骤进行逐一排查。
  举个例子,家里厨房的水池下水堵了,我们要找原因,首先得知道水池的下水道都有哪些部分:
  简单的看,可以把下水道分解为水漏、上连接管、回水弯、下连接管最后接入地漏。再查找堵塞位置时,我们就可以将水直接导入回水弯,排除水漏和上连接管道堵塞的可能。
  应用在测试中,我们也可以利用直接向应用中间件发请求,来排除Web代理层的瓶颈。
  通过绘制流向图,可以更清晰的展现系统中数据流向,帮助我们在定位瓶颈的过程始终能迅速的分析预计到下一个可能的瓶颈位置。
  如上图,就是在play一个Mobile game时的数据流向图。
  2、最直观的指征:检索日志中的异常
  日志是系统异常的最直接反映,通过客户端(负载工具端)、服务器端的日志,可以迅速确定瓶颈可能存在的方向。一些在大用户量大并发情况下的功能问题,也会在错误日志中体现。
  在过程中,一般情况是不把全部日志打开的,而是尽量保持与生产环境的设置相同,生产环境开启什么样的日志级别,在性能测试环境中也应该开启同样的级别。
  但是往往在生产环境出于性能考虑,并不会把日志级别开的非常高,所以在发现系统存在性能问题时,我们可以适当调高日志级别,以便获得更多的信息。
  在日志中,我们可以由一些关键字直接推断出系统的问题所在,比如:
  & Too many open files
  下存在句柄数限制,系统的默认值较小,在测试前应该优化,另外还要怀疑是否程序存在打开句柄却在某些情况下没有关闭。
  & OutOfMemoryError/Cannot allocate memory
  Java环境的虚拟内存异常,往往需要关注是否有溢出。
  & SQLException
  语句执行异常,一般日志中还会有数据库返回的信息。
  & Connection closed/connection refused
  连接被关闭被拒绝,一般是连接数限制不能承担当前的压力。
  3、最底层的反映:分析硬件资源占用
  硬件资源也是系统性能达到瓶颈点的重要指征,如果没有在日志中找到异常,那么通过监控硬件资源消耗,往往可以发现系统的资源瓶颈。
  3.1 CPU占用率
  CPU的高占用,并不一定表示有问题,因为实现最优性能的一方面就是充分发挥当前的硬件资源能力。
  但是如上图这样CPU长期出于满负荷,就很值得我们关注,至少说明在大多数情况下,系统已经是在耗用最大的计算能力进行计算,运算能力已经成为瓶颈。
  另外还要注意CPU是消耗在User还是Sys还是Wait, 如果是Wait,还要观察其他硬件资源,查看CPU是在等待什么。
  3.2 内存占用
  内存在性能测试中是被重点关注的指标,因为它是反映重大缺陷&&内存泄露的最直接指标,但是我们应该注意到,在JAVA框架中的内存泄漏是发生在虚拟内存中的。
  观察内存/虚拟内存的占用情况,尤其是在压力消失后的内存占用恢复情况,是比较直接的判断内存泄漏的依据。
  如果观察到如上图的内存使用情况,在每次Full GC后,占用的内存都没能恢复到原来的水平,如果在压力撤除一段时间后,内存依旧不能恢复,那么十有八九当前系统存在内存泄漏。
  3.3 磁盘I/O
  通常情况下,磁盘是计算机中速度最慢的一个子系统,因此很多情况中,磁盘I/O会成为系统的瓶颈。实际上在设计高性能系统的时候,会把避免磁盘I/O作为一个首要准则。
  虽然当前的技术发展让存储系统的读写速度不断提升,但高昂的成本使得大多数情况下,高速存储会使用在数据库或文件服务器上,而不会使用在应用服务器中。所以在我们进行性能测试时,要更多的注意应用服务器的磁盘使用情况。
3.4 网络I/O
  很多时候大家都容易忽略网络对系统的影响,实际上网络带宽在一些情况下也会成为系统的瓶颈。一旦在业务的请求和响应中包含较大的数据传输时,往往会遇到网络瓶颈。因为更多的时候服务器采用的还是以太网卡,1000M网卡在全双工模式下传输速率也只有80M/s,如果响应中包含报表、图片之类的大尺寸数据,很有可能在性能测试中出现网络瓶颈。
  还有一点就是不要忽略回环地址传输的影响,比如一些应用访问本地监听的其他服务,都会受到网卡的传输速率限制的影响。
  4、软件性能软肋:数据库的监控分析
  对于Web系统,超过七成的瓶颈都出现在数据库子系统,因此在进行之前几步不能明确瓶颈位置的时候,应优先进行数据库的监控分析。
  Oracle数据库监控工具
  Oracle本身提供了ASH,AWR等Report来帮助进行性能分析,但是对于测试人员来说,掌握这些需要较深入的数据库知识学习,不是一朝一夕可以达成的。而一些第三方提供的工具,通过图形界面,可以更加直观的帮助我们进行Oracle数据库的监控和分析。
  Lab128就是国内开发的一块很不错的共享软件,而且它还提供无限期的试用key,可以免费试用。
  Oracle中的等待事件
  判断Oracle中的瓶颈,了解Oracle中的等待事件Wait event,对于查找瓶颈有很大的帮助。在Oracle中,处理SQL的过程,会产生一系列的等待事件。
  有等待事件并不代表数据库存在瓶颈,正常的处理也会有等待事件,但如果发现等待事件激增,或者SQL执行缓慢,这时候等待事件中排名靠前的事件将会直接反映出瓶颈所在。
  上图是在测试中的某一时刻,log sync的等待事件突然增高,同时数据库的吞吐率大幅下降,原本正常的SQL执行速度也突然变长。
  因为压力并没有突然改变,很有可能是写log的过程出现了问题,或者是在传输过程,或者是在存储子系统。后来经过排查,发现是存储集群的一个存储单元出现故障导致写入速度变慢致使出现大量等待。
  5、最后的大杀器:应用服务器监控及代码分析
  如果没能在其他位置发现瓶颈,那么软件程序所运行的平台&&应用服务器很可能是最大的潜在瓶颈点,进行应用服务器的监控与分析将是我们最后的大杀器。
  5.1 常见的软件资源种类
  相对于硬件资源,软件资源往往容易被忽略,它不像CPU占用率那么让人更直观的和性能联系起来,但是实际上,软件资源同样限制着软件系统能达到什么样的性能。
  软件资源不论是在Web层,应用层还是在数据库层,都可以按&入口&、&内部&、&出口&来划分。对于常见的原因中间件,&入口&就是如HTTP连接池之类,是数据来源方向的相关设置,比如连接数限制,超时时间,连接回收策略等等;&内部&就是处理请求的各项资源,不如线程数,线程调度策略,虚拟内存设置,GC策略等等;&出口&则是向后端交互的各项资源,如数据库连接池的配置。
  5.2 应用中间件监控
  要了解软件资源是否成为瓶颈,我们就需要监控这些软件资源指标。以JAVA环境为例,Weblogic 本身就有控制台,提供了各种计数器。
  上图显示的是Execute Threads的计数器,对请求的处理就在这些Thread中进行。
  Tomcat也有开源的控制台,常用的像PSI-Probe,提供了Tomcat服务器各项资源的图形化监控。如下图中对JVM的监控。
  5.3 应用中间件剖析
  仅仅监控只能初步判断问题的方向,例如发现ExecuteThreads持续的增加,我们虽然知道这个现象不正常,但是想要确定是程序中的哪个方法导致了当前问题,我还需要其他的工具进行深入剖析。
  对于Java程序,最常用的工具有JProfiler,YourKit,他们的原理类似,都是要把一个小插件挂在到应用服务器上,以获取需要的程序运行信息。
  而Sun在JDK1.7后版本整合了继承自JRockit的MissionControl,也提供了很强大的分析监控功能,而且开销较小,确实是个不错的选择。
  它提供的Mem leak detector可以对对象的创建进行趋势分析,帮你找到最有可能出现泄漏的对象,
  再通过展开剖析工具中的invoke tree,找出创建该对象的方法,可以更细致的定位问题的原因。
  同时,Call tree 也可以依据CPU时间进行分析,找到在虚拟机中消耗最高的方法。
转载:http://www.51testing.com/html/03/n-.html
随笔 - 152性能问题定位一般思路
原则:倒金字塔型,由表及里,逐步聚焦,大胆假设,小心求证
顺序:硬件-&操作系统-&网络-&中间件服务器-&应用环境-&性能脚本-&测试数据-&log-&profiling(分模块打点监控,工具)
Searchweb性能问题的简单分类
1、排除环境影响
环境主要的排查点为:
1)虚拟内存的使用情况,如果使用超过1m则需要重启服务器;
2)log级别
3)是否使用模板cache
4)jvm参数是否跟线上一致
5)log文件的大小是否超过1G
6)是否有其他服务干扰
2、响应时间和tps
1)在分支代码中加入时间打点统计,将应用耗时时间分为几块,对各个模块和部分打点统计进行分析。
2)通过调整并发和thinktime等压力参数得到tps拐点,如果仍然达不到预期,可通过上面的方法进一步优化响应时间
3、系统资源指标异常
系统资源涉及到众多的因素,cpu,memory,io,network等,各个因素相互影响,可通过sar,glance
plus等工具进行定位
4、系统报错
性能测试前一定要清空之前的log,保证每轮测试log的独立性,测试完成后要详细检查log中的各种ERROR级别的错误,比如
NullPointerException由于高并发导致的空指针错误必须要调查清楚。
(from guoliang.cuigl)
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。在 Rational Performance Tester 中增强自定义代码功能快速定位性能问题
免费下载:
下载更多的 ,并加入 ,参与在线交流。IBM Rational Performance Tester(RPT)提供了一些基本的测试计数器和内置的性能测试报告模板,通过脚本录制结合自定义代码的方式可以很快地构建灵活的测试场景。然而,在测试过程中用户往往需要自定义自己的性能计数器,并且希望 RPT 在运行过程中能够输出实时的控制台日志信息,以便于脚本的跟踪调试。通过在自定义的代码中定义一些计数器,在脚本中使用正则表达式匹配发现页面中的特殊信息并作统计,进而利用 RPT 的运行状态监控,实时查看自定义的计数器的值的变化动态;通过利用开源的 log4j,又丰富了 RPT 的日志功能。本文提供的解决方案能很好的达到实时监控特定指标的目的,同时也方便了性能问题的快速定位。RPT 的自定义代码自定义代码实现多种功能RPT 基于 Eclipse 平台,提供的自定义代码能实现很多复杂的功能,具体的功能介绍和示例可以参考参考资源中其他的文章。自定义代码能实现的功能下表列出了在 RPT8.1 中提供的常用的接口。表 1. RPT 中自定义代码提供的接口接口描述ICustomCode2用来创建所有的自定义代码ITestExecutionServices该接口是执行服务(execution service)的主要接口,其包含如下接口:IDataArea, IARM, ILoopControl, IPDLogManager, IStatisticsManager, ITestLogManager, ITime, and ITransactionIDataArea对象的容器,类似程序中的变量,如果要使用特定协议的对象,需要从特定的协议所提供的对象中获取IARM提供有关定义 ARM (Application Response Measurement) 所需要的信息,当虚拟用户需要抽样进行 ARM 处理的时候使用该接口ILoopControl在测试中或者性能调度中提供循环控制IPDLogManager记录问题严重级别、水平和错误信息IStatisticsManager用来存取性能计数器,性能计数器以层次结构组织,并且都有自己的类型。ITestLogManager用来提供日志信息和验证点信息,日志信息要在测试结束之后选择 display test log 来查看。ITransaction提供对事务的支持。事务信息的维护是针对每个虚拟用户的。在自定义代码中创建的事务可以在任意的代码中启动或者停止它,并且该事务可以跨越多个测试。事务的信息会体现在最终的报告中。IEngineInfo提供测试引擎的信息。比如在该引擎中运行的虚拟用户数,任务完成的用户数等。ITestInfo提供运行中的测试的信息,比如测试的名称,在本文后面的示例代码中会用到。IVirtualUserInfo提供虚拟用户的信息,如名称,组名等,后面的示例代码中会用到。IScalar提供整形计数器的方法,用于 SCALAR 和 STATIC 类型的计数器,用该接口来增加或者减少计数。IStatistics用来获取和当前统计处理器相关的性能计数器树目录。具体的接口的方法和类信息可以参考 RPT 的帮助内容。使用 log4j 扩展代码功能log4j 介绍Log4j 是 Apache 的开放源代码项目,通过使用 Log4j,可以控制日志信息输送的目的地是控制台、文件、邮件接收者、GUI 组件、甚至是套接口服务器、Windows 的事件记录器、UNIX Syslog 守护进程等;也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程。并且,这些控制可以通过一个修改配置文件来灵活地进行,而不需要修改代码。log4j 的好处在于:1. 在代码开发阶段可以打印详细的 log 信息以跟踪系统运行情况 , 而在代码稳定后可以关闭 log 输出 , 从而在能跟踪系统运行情况的同时 , 又减少了垃圾代码(System.out.println(......) 等)。2. 使用 log4j,可以使整个系统有一个统一的 log 机制,有利于系统的规划。更多详细的有关 log4j 的内容,请参考其他相关文章。自定义代码中使用 log4j通过以下步骤来设置 log4j1. 下载 log4j。本文使用的是 1.2.16 的版本。2. 给工程添加 log4j。把解压出来的 log4j-1.2.16.jar 将其添加到工程的 lib 目录下,即把 jar 包拷贝到 RPT 的项目下面的 lib 目录,然后把 jar 包添加到工程的构建路径。3. 导入所需要的包。在自定义的代码前面加入:import org.apache.log4j.L
import org.apache.log4j.PropertyC4. 设置 log4j 配置文件,示例如下:清单 1. log4j 配置示例# 配置根 logger,这里设置级别为 info,将显示 fatal、error、warn、info 级别的日志
log4j.rootLogger=info, appender1, appender2
# 日志输出到 console 控制台
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
# Configure log layout
log4j.appender.appender1.layout=org.apache.log4j.PatternLayout
log4j.appender.appender1.layout.ConversionPattern =%r [%t] [%p] - %c -%l %m%n
# 日志输出到指定的文件:D:/mylog.txt
log4j.appender.appender2=org.apache.log4j.FileAppender
log4j.appender.appender2.File=D:/mylog.txt
# Configure log layout
log4j.appender.appender2.layout=org.apache.log4j.PatternLayout
log4j.appender.appender2.layout.ConversionPattern=[%d{HH:mm:ss:SSS}][-%l] %m%n5. 在自定义代码中使用 logger,注意把 logger 的配置文件放在正确的位置,这里是:D:\\log4j_mix.properties6. 注意:在 log4j 的配置文件中指明日志输出路径时要用左斜杠(“/”)。清单 2. 自定义代码中使用 log4j 示例
// (1) 设置 logger
private static final Logger logger = Logger.getLogger(GetAccountID.class);
public String exec(ITestExecutionServices tes, String[] args) {
// (2) 加载 logger 配置文件
testlog.reportMessage("Get configure: log4j_mix.properties ");
PropertyConfigurator
.configure("D:\\log4j_mix.properties");
} catch (Exception e) {
e.printStackTrace();
testlog.reportMessage("Exception e:" + e);
logger.info("Load log4j file exception: " + e);
// (3) 使用 logger
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.fatal("fatal");
logger.error("error");6. 检查 logger 是否生效。到指定的目录中打开 log 文件查看,日志中将会列出时间戳,java 代码的类名称,信息所在的行号和日志内容。内容如下: [17:30:06:640][-test.CheckTicketURL_v3.exec(CheckTicketURL_v3.java:113)] info
[17:30:06:640][-test.CheckTicketURL_v3.exec(CheckTicketURL_v3.java:114)] warn
[17:30:06:640][-test.CheckTicketURL_v3.exec(CheckTicketURL_v3.java:115)] fatal
[17:30:06:640][-test.CheckTicketURL_v3.exec(CheckTicketURL_v3.java:116)] error7. 如果只想输入 error 级别的日志,只需要去 logger 的配置文件中修改:
log4j.rootLogger=info,appender1,appender2 为:log4j.rootLogger=error, appender1, appender28.其他高级配置可以参考相关文档。如果希望通过 logger 给自己发邮件或者把日志信息通过 socket 的方式传出去,都可以在 logger 的配置文件进行设置,具体的配置这里不列出。9. 要注意的是,在通过 PropertyConfigurator.Configure() 成功加载了 log4j 的配置文件之后,logger 才能生效。使用自定义性能计数器作统计RPT 中自定义的计数器介绍在代码中使用该计数器的方法参照如下示例。常用的有两种类型的计数器:表 2. RPT 中的计数器常用的类型计数器类型定义说明StatType.SCALAR用来对事件或者对象计数,计数器的值通过 IScalar 接口来修改。该值每次报告之后将重置为 0该值每次报告之后将重置。详细用法见 RPT 的帮助内容。StatType.STATIC用来做累计性的数值统计,该计数器的值在其生命周期中一直累计,计数器的值通过 IScalar 接口来修改。该值每次报告之后将不会重置为 0该计数器从定义之后将作用于整个测试的过程,并且一直累计,相当于全局静态变量,例如测试中的活动用户数就是通过该值来统计的。在自定义代码中使用自定义的计数器自定义计数器的语法见如下代码清单清单 3. 使用自定义计数器语法示例// Get all statistical counters.
IStatTree rootStat = tes.getStatisticsManager().getStatTree();
IStatTree MyS
IScalar TicketListPassStat =
IScalar TicketListFailStat =
// Setup the status report hierarchy
if (rootStat != null) {
MyStat = rootStat.getStat("Name_of_Root_Stat_Structure", StatType.STRUCTURE);
// Define counters
TicketListPassStat = (IScalar) MyStat.getStat("TicketListPass",StatType.STATIC);
TicketListFailStat = (IScalar) MyStat.getStat("TicketListFail",StatType.STATIC);
}在自定义代码中添加和使用计数器见如下代码清单:清单 4. 使用自定义计数器示例import com.ibm.rational.test.lt.kernel.services.IStatisticsM
import com.ibm.rational.test.lt.kernel.services.ITestExecutionS
import com.ibm.rational.test.lt.kernel.statistics.IS
import com.ibm.rational.test.lt.kernel.statistics.IStatT
import com.ibm.rational.test.lt.kernel.statistics.impl.StatT
public class CustomCounter implements
com.ibm.rational.test.lt.kernel.custom.ICustomCode2 {
* Instances of this will be created using the no-arg constructor.
public CustomCounter() {
public String exec(ITestExecutionServices tes, String[] args) {
IStatisticsManager sm = tes.getStatisticsManager();
IStatTree st = sm.getStatTree();
IScalar myCounter1 = (IScalar) st.getStat("mystatcounter1", StatType.SCALAR);
myCounter1.increment();
IScalar myCounter2 = (IScalar) st.getStat("mystatcounter2", StatType.STATIC);
myCounter2.increment();
}正则表达式结合计数器的使用正则表达式的使用以下是 RPT 中使用正则表达式的示例,该代码很直观的看出,RPT 中的正则表达式的语法跟 java 的语法是一致的。该代码展示的是从输入的内容中获取指定匹配模式的内容。清单 5. 自定义代码使用正则表达式示例
import com.ibm.rational.test.lt.kernel.services.ITestExecutionS
import java.util.regex.*;
* The ParseResponse class demonstrates using Custom Code to extract a
* string from its input argument using a regular expression for pattern
* matching.
* In this sample, the args[0] input string is assumed to be the full
response from a previous request. This response contains the day's
headlines in a format such as:
* &a class=f href=r/d2&In the News&/a&
* &small class=m&&&span id=nw&
* &/span&&/small&&/h2&
* &div class=ct&
* &a href=s/213231&Cooler weather moving into eastern U.S.&/a&
* &•&&a href=s/262502&Digital camera shipments up&/a&
* Given the above response, the extracted string would be:
* Cooler weather moving into eastern U.S.
* @author IBM Custom Code Samples
public class ParseResponse implements
com.ibm.rational.test.lt.kernel.custom.ICustomCode2 {
* Instances of this will be created using the no-arg constructor.
public ParseResponse() {}
public String exec(ITestExecutionServices tes, String[] args) {
String HeadlineStr = "No Headline Available";
String RegExpStr = ".*In the News[^;]*;[^;]*;[^;]*;&a
href=([^&]*)&([^&]*)&"; Pattern pattern =
Pattern.compile(RegExpStr, Pattern.DOTALL); Matcher matcher =
pattern.matcher(args[0]);
if (matcher.lookingAt())
HeadlineStr = matcher.group(2);
tes.getTestLogManager().reportMessage("Input does not match
pattern.");
return HeadlineS
}自定义代码中的正则表达式的示例RPT 可以通过加入页面的验证点的方式来检查返回的页面的内容或者 Return code,来确定页面的内容是否正确。但是直接插入验证点的方式不能直观地实时反应页面验证的情况,如果通过页面正则表达式的查找,结合 logger 的实时输出日志功能,就可以轻松的实时输出自己感兴趣的一些性能计数器的值。清单 6. 自定义代码使用正则表达式和计数器并结合 log4j 的示例1 public class CheckTicketURL_simple implements
com.ibm.rational.test.lt.kernel.custom.ICustomCode2 {
public CheckTicketURL_simple() {
// Define error log output folder
private final String Folder = "D:\\Project\\RPTLogs";
// Specify to output which vUser's log by default
private String vUserMon = "[User Group 1][000001]";
// Specify the vUser ID when running single test, rather than run the test
// in schedule
private int vUser0 = 0;
// Setup log4j logger
private static final Logger logger = Logger.getLogger(GetAccountID.class);
public String exec(ITestExecutionServices tes, String[] args) {
// Get UserID
String UserID = args[0];
// Get entire response content
String PageContent = args[1];
// Specify to output which vUser's log, get the argument from datapool,
// it will replace the default vUser ID
// defined previously
vUserMon = args[2];
// Initialize ticket ID to null
String TicketID = "NULL";
ITestLogManager testlog = tes.getTestLogManager();
// Load log4j configuration
testlog.reportMessage("Get configure: log4j_mix.properties ");
PropertyConfigurator
.configure("D:\\log4j_mix.properties");
} catch (Exception e) {
e.printStackTrace();
testlog.reportMessage("Exception e:" + e);
logger.info("Load log4j file exception: " + e);
// Get virtual User info and output to logs
IVirtualUserInfo vui = (IVirtualUserInfo) tes.findDataArea(
IDataArea.VIRTUALUSER).get(IVirtualUserInfo.KEY);
// Get test name
if (vui != null
&& vui.getUserName().toString().equalsIgnoreCase(vUserMon)
|| vui.getUID() == vUser0) {
// Output test name in log in order to identify the test
ITestInfo currTestInfo = (ITestInfo) tes.findDataArea(
IDataArea.TEST).get(ITestInfo.KEY);
logger.info("============== " + currTestInfo.getName()
+ "==============");
logger.info("vUserID=" + vui.getUID());
logger.info("vUserName=" + vui.getUserName());
// Setup data logger and IScalar
IDataArea DataLog = tes.findDataArea(IDataArea.VIRTUALUSER);
IStatTree rootStat = tes.getStatisticsManager().getStatTree();
IStatTree SEPS
IScalar TicketListPassStat =
IScalar TicketListFailStat =
// Setup the SEP status report hierarchy
if (rootStat != null) {
SEPStat = rootStat.getStat("SEP", StatType.STRUCTURE);
// Define counters
TicketListPassStat = (IScalar) SEPStat.getStat("TicketListPass",
StatType.STATIC);
TicketListFailStat = (IScalar) SEPStat.getStat("TicketListFail",
StatType.STATIC);
// Setup matcher to extract the ticket ID
Matcher matcher1 = Pattern.compile("SR([0-9]*)&", Pattern.DOTALL)
.matcher(PageContent);
// The response page isn't null, try to extract the ticketID
if (PageContent.length() != 0) {
// Can find the ticket ID
if (matcher1.lookingAt() == true) {
// Passed counter +1
if (TicketListPassStat != null) {
TicketListPassStat.increment();
TicketID = matcher1.group(1);
if (testlog.wouldReport(ITestLogManager.ALL)) {
if (vui.getUserName().toString().equalsIgnoreCase(vUserMon)
|| vui.getUID() == vUser0) {
.info(UserID + " Selected Ticket ID: "
+ TicketID);
testlog.reportMessage(UserID + " Selected Ticket ID: "
+ TicketID);
// Report passed verification status in RPT report
if (testlog.wouldReport(ITestLogManager.SCHEDULE)) {
testlog.reportVerificationPoint("PageContent isn't null",
VerdictEvent.VERDICT_PASS);
if (vui.getUserName().toString().equalsIgnoreCase(vUserMon)
|| vui.getUID() == vUser0) {
logger.info("\r\n");
// Return the ticketID
return TicketID;
// Cannot find the ticket ID, failed counter +1
if (TicketListFailStat != null) {
TicketListFailStat.increment();
// Report failed verification status in RPT report
if (testlog.wouldReport(ITestLogManager.ALL)) {
testlog.reportVerificationPoint(
"Cannot extract the ticket ID",
VerdictEvent.VERDICT_FAIL);
// Page Content is null, failed counter +1
if (TicketListFailStat != null) {
TicketListFailStat.increment();
// Report failed verification status in RPT report
if (testlog.wouldReport(ITestLogManager.ALL)) {
testlog.reportVerificationPoint("Page content is null",
VerdictEvent.VERDICT_FAIL);
if (testlog.wouldReport(ITestLogManager.SCHEDULE))
testlog.reportMessage("Page content is null. Page content = "
+ PageContent);
if (vui.getUserName().toString().equalsIgnoreCase(vUserMon)
|| vui.getUID() == vUser0) {
logger.info("page content is null");
if (vui.getUserName().toString().equalsIgnoreCase(vUserMon)
|| vui.getUID() == vUser0) {
// Output pass/fail verdict counters
logger.info("Total TicketListPassStat = " + TicketListPassStat.value());
logger.info("Total TicketListFailStat = " + TicketListFailStat.value());
.info("Passed % = "
+ TicketListPassStat.value()
/ (TicketListPassStat.value() + TicketListFailStat.value()));
logger.info("\r\n");
return "Error";
140 }对以上代码清单的一些说明(加入了行号便于说明):第 9,12 行。
private String vUserMon = "[User Group 1][000001]"; private int vUser0 = 0;这两行定义的是 RPT 中的针对虚拟用户的标识。在性能调度中的第一个用户组的第一个 vUser 的 ID 是 [User Group 1][000001],在单个测试中的 vUser 的 ID 为 0,定义这个并加入如下的条件判断:if (vui != null && vui.getUserName().toString().equalsIgnoreCase(vUserMon)
|| vui.getUID() == vUser0)可以保证在运行单个测试或者运行性能调度的时候都能输出指定的 log,并且在性能调度下可以输出指定的用户组的单个用户的 log,这个可是通过 datapool 的引用。用起来更灵活且避免输出的 log 太多。第 48~53 行在 log 中输出该测试的名称,便于区别代码在哪一个测试中调用,因为 RPT 中可以在不同的测试中插入同一个 java 代码。第 56~71 行设置统计相关的变量和定义计数器。第 74 行设置正则表达式匹配器。第 78~129 行是页面内容匹配和判断并作相应的统计。第 133~135 行是输出计数器的统计值。注意这里面的统计的结果是累计的。也就是所有的虚拟用户的运行统计的累加值。下图是 RPT 中的参数传入配置,注意这里面用了三个参数,分别是登录帐户信息、页面返回的内容、datapool 中指定的输出 log 的用户 ID。图 1. RPT 中的自定义代码参数配置示例运行测试过程中的部分日志: [11:57:15:134][-test.CheckTicketURL_simple.exec(CheckTicketURL_simple.java:80)]
============== 5.ViewTicket_migration==============
[11:57:15:134][-test.CheckTicketURL_simple.exec(CheckTicketURL_simple.java:82)]
[11:57:15:134][-test.CheckTicketURL_simple.exec(CheckTicketURL_simple.java:83)]
vUserName=[DefaultUserGroup][000001]
[11:57:15:134][-test.CheckTicketURL_simple.exec(CheckTicketURL_simple.java:171)]
Total TicketListPassStat = 0
[11:57:15:134][-test.CheckTicketURL_simple.exec(CheckTicketURL_simple.java:172)]
Total TicketListFailStat = 1
[11:57:15:150][-test.CheckTicketURL_simple.exec(CheckTicketURL_simple.java:174)]
Passed % = 0
[11:57:15:150][-test.CheckTicketURL_simple.exec(CheckTicketURL_simple.java:178)]另外,如果希望日志信息自动滚屏,用 notepad++ 的插件可以很容易的实现。只需要在 notepad 中点击插件管理器,选择名为 Document Monitor 的插件,并安装,然后用 notepad++ 打开输出的日志文件,选择“插件”菜单,“Document Monitor”子菜单,选择“Start monitoring”即可。添加计数器为实时监控如果希望把自定义的计数器添加到 RPT 的实时监控界面,更直观的观察计数器的变化趋势,也很简单,步骤如下:运行测试。选择正在运行的测试,选中验证点报告,便于浏览结果。图 2. 选择验证点报告选中自定的计数器,拖拽到右面的面板中,这样就能看到实时的统计结果。图 3. 添加实时计数器统计总结通过上面的示例和说明,可以看出使用 log4j 能够非常方便地配置自定义代码的日志输出内容,样式,级别等,增强了 RPT 中的实时输出日志的功能,并加速自定义代码的调试过程。利用 RPT 提供的接口,在自定义代码中使用用户自定义的计数器可以灵活地实现特定性能指标的统计和监控,加速性能问题的发现和定位。
相关主题参考其他 Rational Performance Tester 文章:
访问 ,获得关于 IBM Rational 软件交付平台(Rational Software Delivery Platform)产品的技术资源和最佳实践。订阅 ,一份关于 developerWorks 指南、文章、下载、社区活动、网络广播和技术讲座的电子周刊。访问 ,了解最新的 IBM Rational Functional Tester (RFT) 产品文档和产品信息,获得关于软件自动化测试的技术文档和参考资源,可以查阅产品概览、产品手册、产品技术支持、试用版下载,以及相关文章、教程、多媒体课堂和产品演示等信息。下载免费的 。。获取免费的 ,了解最新的 IBM Rational 软件开发工具技术文档和资源。下载更多免费的 ,了解 IBM Rational 软件的最新特性。
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=http://www.ibm.com/developerworks/js/artrating/SITE_ID=10Zone=RationalArticleID=783397ArticleTitle=在 Rational Performance Tester 中增强自定义代码功能快速定位性能问题publish-date=

我要回帖

更多关于 代码性能测试工具 的文章

 

随机推荐