发布新日志

  • (转)常用的正则表达式

    2009-03-25 18:14:12

    常用的正则表达式
    http://www.suzhou35.com/blog/article.asp?id=163
    1、非负整数:^\d+$

    2、正整数:^[0-9]*[1-9][0-9]*$

    3、非正整数:^((-\d+)|(0+))$

    4、负整数:^-[0-9]*[1-9][0-9]*$

    5、整数:^-?\d+$

    6、非负浮点数:^\d+(\.\d+)?$

    7、正浮点数:^((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$

    8、非正浮点数:^((-\d+\.\d+)?)|(0+(\.0+)?))$

    9、负浮点数:^(-((正浮点数正则式)))$

    10、英文字符串:^[A-Za-z]+$

    11、英文大写串:^[A-Z]+$

    12、英文小写串:^[a-z]+$

    13、英文字符数字串:^[A-Za-z0-9]+$

    14、英数字加下划线串:^\w+$

    15、E-mail地址:^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$

    16、URL:^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$
    或:^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^ <>\"\"])*$

    17、邮政编码:^[1-9]\d{5}$

    18、中文:^[\u0391-\uFFE5]+$

    19、电话号码:^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$

    20、手机号码:^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$

    21、双字节字符(包括汉字在内):^\x00-\xff

    22、匹配首尾空格:(^\s*)|(\s*$)(像vbscript那样的trim函数)

    23、匹配HTML标记: <(.*)>.* <\/\1>| <(.*) \/>

    24、匹配空行:\n[\s| ]*\r

    25、提取信息中的网络链接:(h|H)(r|R)(e|E)(f|F)  *=  *('|")?(\w|\\|\/|\.)+('|"|  *|>)?

    26、提取信息中的邮件地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

    27、提取信息中的图片链接:(s|S)(r|R)(c|C)  *=  *('|")?(\w|\\|\/|\.)+('|"|  *|>)?

    28、提取信息中的IP地址:(\d+)\.(\d+)\.(\d+)\.(\d+)

    29、提取信息中的中国手机号码:(86)*0*13\d{9}

    30、提取信息中的中国固定电话号码:(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}

    31、提取信息中的中国电话号码(包括移动和固定电话):(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}

    32、提取信息中的中国邮政编码:[1-9]{1}(\d+){5}

    33、提取信息中的浮点数(即小数):(-?\d*)\.?\d+

    34、提取信息中的任何数字 :(-?\d*)(\.\d+)? 

    35、IP:(\d+)\.(\d+)\.(\d+)\.(\d+)

    36、电话区号:/^0\d{2,3}$/

    37、腾讯QQ号:^[1-9]*[1-9][0-9]*$

    38、帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

    39、中文、英文、数字及下划线:^[\u4e00-\u9fa5_a-zA-Z0-9]+$
  • (转)LoadRunner脚本解释分析

    2009-03-21 17:05:33

    1、获得网站首页
        web_url("www.seventest.net",
            "URL=www.seventest.net/",
            "TargetFrame=",  //
    目标窗口_BLANK:打开一个新窗口
                                              _PARENT:
    取代最后一个窗口的父窗口
                                              _SELF:
    取代最后一个窗口

                                              _TOP:
    取代整个页面
            "Resource=0",            //URL
    是否为一个资源  0:不是

                                                         1:

            "RecContentType=text/html", //
    录制过程中,响应报头内容格式
            "Referer=",                 //
    提交网页的URL
            "Snapshot=t1.inf",          //
    快照文件名

            "Mode=HTML",                //
    录制水平: HTML or HTTP.

    HTML level:指导VuGen录制直观的HTML动作,录制web_url,web_link,web_image。返回的是HTML页面,而不是脚本和程序。
    HTTP level:
    指导VuGen录制全部的服务器响应。不产生web_link,web_image,web_submit_form。比HTML高级,但当读脚本时不是很直观。
            EXTRARES,                   //
    参数表划分标志(下个标志是一个资源特征表)
           "Url=/dy.css", "Referer=http://www.seventest.net/index.htm", ENDITEM,     //
    资源结束志
       
           "Url=/images/bg_03.gif", "Referer=http://www.seventest.net/index.htm", ENDITEM, 
           "Url=/images/logo-end%2020GAI.swf","Referer=http://www.seventest.net/index.htm", ENDITEM,
            "Url=/images/2.swf", "Referer=http://www.seventest.net/index.htm", ENDITEM,
            LAST);                      //
    特征表结束标志

    2、下载一个游戏
    web_url("Games",
           "URL=ftp://joe:secret@mygames.com/games/archive/loderunner.exe",
           "FtpAscii=1",         //1:
    ASCII模式执行FTP传输
                                            //0:
    二进制模式
           LAST);

    3、百度搜索科学
    Action()
    {
        //
    打开首页

     web_add_cookie ("BAIDUID=AAFDECDD16EF55636CA63DC64381BBEC:FG=1; DOMAIN=www.baidu.com");

    web_add_cookie("BDSTAT=7e00ef72b41d6156ecc574f4a7efce1b9d16fdfaaf51f3debd8f8c5497eef01f3a292df5e2fe587d;DOMAIN=www.baidu.com");

                                 //网络接口的对象表达式,经常用在JavaVB.

                                //name=VALUE;必须
                                 //domain=DOMAIN_NAME;
    必须
                                  //expires=DATE;
                                  //path=PATH; (default path is "/")
                                  //secure
                                 //The elements in the Cookie parameter are the same as the elements in the
                                 //Set–Cookie HTTP Response Header.

     web_url("www.baidu.com",
      "URL=http://www.baidu.com/",  
      "TargetFrame=",
      "Resource=0",
      "RecContentType=text/html",
      "Referer=",
      "Snapshot=t1.inf",
      "Mode=HTML",
      EXTRARES,
      "Url=/favicon.ico", "Referer=", ENDITEM,
      LAST);

     web_add_cookie("BAIDUID=AAFDECDD16EF55636CA63DC64381BBEC:FG=1; DOMAIN=s.baidu.com");

     web_add_cookie("BDSTAT=7e00ef72b41d6156ecc574f4a7efce1b9d16fdfaaf51f3debd8f8c5497eef01f3a292df5e2fe587d;

    DOMAIN=s.baidu.com");

     lr_think_time(13);
       //
    搜索科学

     web_submit_data("s",         //
    提交数据

      "Action=http://www.baidu.com/s",    //
    提交数据的HTTP address
      "Method=GET",
      "EncType=",                       //
    编码方式

      "TargetFrame=",
      "RecContentType=text/html",
      "Referer=http://www.baidu.com/",
      "Snapshot=t2.inf",
      "Mode=HTML",               //
    录制水平
      ITEMDATA,
      "Name=wd", "Value=?", ENDITEM,
      "Name=cl", "Value=3", ENDITEM,
      EXTRARES,
      "Url=http://s.baidu.com/w.gif?path=http://www.baidu.com/s?wd=%BF%C6%D1%A7&cl=3&t=1200288916042",

    "Referer=http://www.baidu.com/s?wd=%BF%C6%D1%A7&cl=3", ENDITEM,
      LAST);

     return 0;
    }

     


  • (转)性能测试(并发负载压力)测试分析-简要篇

    2009-03-21 17:03:32

    在论坛混了多日,发现越来越多的性能测试工程师基本上都能够掌握利用测试工具来作负载压力测试,但多数人对怎样去分析工具收集到的测试结果感到无从下手,下面我就把个人工作中的体会和收集到的有关资料整理出来,希望能对大家分析测试结果有所帮助。

    分析原则:

    • 具体问题具体分析(这是由于不同的应用系统,不同的测试目的,不同的性能关注点)

    • 查找瓶颈时按以下顺序,由易到难。

        服务器硬件瓶颈-〉网络瓶颈(对局域网,可以不考虑)-〉服务器操作系统瓶颈(参数配置)-〉中间件瓶颈(参数配置,数据库,web服务器等)-〉应用瓶颈(SQL语句、数据库设计、业务逻辑、算法等)

        注:以上过程并不是每个分析中都需要的,要根据测试目的和要求来确定分析的深度。对一些要求低的,我们分析到应用系统在将来大的负载压力(并发用户数、数据量)下,系统的硬件瓶颈在哪儿就够了。

    • 分段排除法 很有效

    分析的信息来源:

    •1 根据场景运行过程中的错误提示信息

    •2 根据测试结果收集到的监控指标数据

    一.错误提示分析

    分析实例:

    1 •Error: Failed to connect to server “10.10.10.30:8080″: [10060] Connection

    •Error: timed out Error: Server “10.10.10.30″ has shut down the connection prematurely

    分析:

    •A、应用服务死掉。

    (小用户时:程序上的问题。程序上处理数据库的问题)

    •B、应用服务没有死

    (应用服务参数设置问题)

        例:在许多客户端连接Weblogic应用服务器被拒绝,而在服务器端没有错误显示,则有可能是Weblogic中的server元素的AcceptBacklog属性值设得过低。如果连接时收到connection refused消息,说明应提高该值,每次增加25%

    •C、数据库的连接

    (1、在应用服务的性能参数可能太小了 2、数据库启动的最大连接数(跟硬件的内存有关))

    2 Error: Page download timeout (120 seconds) has expired

    分析:可能是以下原因造成

    •A、应用服务参数设置太大导致服务器的瓶颈

    •B、页面中图片太多

    •C、在程序处理表的时候检查字段太大多

    二.监控指标数据分析

    1.最大并发用户数:

    应用系统在当前环境(硬件环境、网络环境、软件环境(参数配置))下能承受的最大并发用户数。

        在方案运行中,如果出现了大于3个用户的业务操作失败,或出现了服务器shutdown的情况,则说明在当前环境下,系统承受不了当前并发用户的负载压力,那么最大并发用户数就是前一个没有出现这种现象的并发用户数。

        如果测得的最大并发用户数到达了性能要求,且各服务器资源情况良好,业务操作响应时间也达到了用户要求,那么OK。否则,再根据各服务器的资源情况和业务操作响应时间进一步分析原因所在。

    2.业务操作响应时间:

        • 分析方案运行情况应从平均事务响应时间图和事务性能摘要图开始。使用“事务性能摘要”图,可以确定在方案执行期间响应时间过长的事务。

    • 细分事务并分析每个页面组件的性能。查看过长的事务响应时间是由哪些页面组件引起的?问题是否与网络或服务器有关?

    • 如果服务器耗时过长,请使用相应的服务器图确定有问题的服务器度量并查明服务器性能下降的原因。如果网络耗时过长,请使用“网络监视器”图确定导致性能瓶颈的网络问题

    3.服务器资源监控指标:

    内存:

    1 UNIX资源监控中指标内存页交换速率(Paging rate),如果该值偶尔走高,表明当时有线程竞争内存。如果持续很高,则内存可能是瓶颈。也可能是内存访问命中率低。

    2 Windows资源监控中,如果Process\Private Bytes计数器和Process\Working Set计数器的值在长时间内持续升高,同时Memory\Available bytes计数器的值持续降低,则很可能存在内存泄漏。

    内存资源成为系统性能的瓶颈的征兆:

    很高的换页率(high pageout rate);

    进程进入不活动状态;

    交换区所有磁盘的活动次数可高;

    可高的全局系统CPU利用率; 

    内存不够出错(out of memory errors)

    处理器:

    1 UNIX资源监控(Windows操作系统同理)中指标CPU占用率(CPU utilization),如果该值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。如果服务器专用于SQL Server,可接受的最大上限是80-85% 

    合理使用的范围在60%至70%。

    2 Windows资源监控中,如果System\Processor Queue Length大于2,而处理器利用率(Processor Time)一直很低,则存在着处理器阻塞。

    CPU资源成为系统性能的瓶颈的征兆: 

    很慢的响应时间(slow response time) 

    CPU空闲时间为零(zero percent idle CPU) 

    过高的用户占用CPU时间(high percent user CPU) 

    过高的系统占用CPU时间(high percent system CPU) 

    长时间的有很长的运行进程队列(large run queue size sustained over time)

    磁盘I/O:

    1 UNIX资源监控(Windows操作系统同理)中指标磁盘交换率(Disk rate),如果该参数值一直很高,表明I/O有问题。可考虑更换更快的硬盘系统。

    2 Windows资源监控中,如果 Disk Time和Avg.Disk Queue Length的值很高,而Page Reads/sec页面读取操作速率很低,则可能存在磁盘瓶径。

    I/O资源成为系统性能的瓶颈的征兆 :

    过高的磁盘利用率(high disk utilization) 

    太长的磁盘等待队列(large disk queue length) 

    等待磁盘I/O的时间所占的百分率太高(large percentage of time waiting for disk I/O) 

    太高的物理I/O速率:large physical I/O rate(not sufficient in itself) 

    过低的缓存命中率(low buffer cache hit ratio(not sufficient in itself)) 

    太长的运行进程队列,但CPU却空闲(large run queue with idle CPU)

    4.数据库服务器:

    SQL Server数据库:

    1 SQLServer资源监控中指标缓存点击率(Cache Hit Ratio),该值越高越好。如果持续低于80%,应考虑增加内存。

    2 如果Full Scans/sec(全表扫描/秒)计数器显示的值比1或2高,则应分析你的查询以确定是否确实需要全表扫描,以及SQL查询是否可以被优化。 

    3 Number of Deadlocks/sec(死锁的数量/秒):死锁对应用程序的可伸缩性非常有害,并且会导致恶劣的用户体验。该计数器的值必须为0。

    4 Lock Requests/sec(锁请求/秒),通过优化查询来减少读取次数,可以减少该计数器的值。

    Oracle数据库:

    1 如果自由内存接近于0而且库快存或数据字典快存的命中率小于0.90,那么需要增加SHARED_POOL_SIZE的大小。

    快存(共享SQL区)和数据字典快存的命中率: 

    select(sum(pins-reloads))/sum(pins) from v$librarycache; 

    select(sum(gets-getmisses))/sum(gets) from v$rowcache; 

    自由内存: select * from v$sgastat where name=’free memory’; 

    2 如果数据的缓存命中率小于0.90,那么需要加大DB_BLOCK_BUFFERS参数的值(单位:块)。

    缓冲区高速缓存命中率:

    select name,value from v$sysstat where name in (’db block gets’,

    ‘consistent gets’,'physical reads’) ;

    Hit Ratio = 1-(physical reads / ( db block gets + consistent gets))

    3 如果日志缓冲区申请的值较大,则应加大LOG_BUFFER参数的值。

    日志缓冲区的申请情况 :

    select name,value from v$sysstat where name = ‘redo log space requests’ ;

    4 如果内存排序命中率小于0.95,则应加大SORT_AREA_SIZE以避免磁盘排序 。

    内存排序命中率 :

    select round((100*b.value)/decode((a.value+b.value), 0, 1, (a.value+b.value)), 2)from v$sysstat a, v$sysstat b where a.name=’sorts (disk)’ and b.name=’sorts (memory)’

    注:上述SQL Server和Oracle数据库分析,只是一些简单、基本的分析,特别是Oracle数据库的分析和优化,是一门专门的技术,进一步的分析可查相关资料。

  • (转)防范SQL注入式攻击

    2009-03-21 17:01:33

    防范SQL注入式攻击

    SQL注入式攻击是利用是指利用设计上的漏洞,在目标服务器上运行Sql命令以及进行其他方式的攻击动态生成Sql命令时没有对用户输入的数据进行验证是Sql注入攻击得逞的主要原因。

    比如:
    如果你的查询语句是select * from admin where username="&user&" and password="&pwd&""

     那么,如果我的用户名是:1 or 1=1
     那么,你的查询语句将会变成:

     select * from admin where username=1 or 1=1 and password="&pwd&""

     这样你的查询语句就通过了,从而就可以进入你的管理界面。

    所以防范的时候需要对用户的输入进行检查。特别式一些特殊字符,比如单引号,双引号,分号,逗号,冒号,连接号等进行转换或者过滤。

    需要过滤的特殊字符及字符串有:

       net user
       xp_cmdshell
       /add
       exec master.dbo.xp_cmdshell
       net localgroup administrators
       select
       count
       Asc
       char
       mid
      
       :
       "
       insert
       delete from
       drop table
       update
       truncate
       from
       %

    下面关于解决注入式攻击的防范代码,供大家学习参考!

    js版的防范SQL注入式攻击代码:

      
    <scrīpt language="javascrīpt">
    <!--
     var url = location.search;
     var re=/^\?(.*)(select%20|insert%20|delete%20from%20|count\(|drop%20table|update%20truncate%20|asc\(|mid\(|char\(|xp_cmdshell|exec%20master|net%20localgroup%20administrators|\"|:|net%20user|\|%20or%20)(.*)$/gi;
     var e = re.test(url);
     if(e) {
      alert("地址中含有非法字符~");
      location.href="error.asp";
     }
    //-->
    <scrīpt>


    asp版的防范SQL注入式攻击代码~:

    [CODE START]
    <%
    On Error Resume Next
    Dim strTemp

    If LCase(Request.ServerVariables("HTTPS")) = "off" Then
     strTemp = "http://"
    Else
     strTemp = "https://"
    End If

    strTemp = strTemp & Request.ServerVariables("SERVER_NAME")
    If Request.ServerVariables("SERVER_PORT") <> 80 Then strTemp = strTemp & ":" & Request.ServerVariables("SERVER_PORT")

    strTemp = strTemp & Request.ServerVariables("URL")

    If Trim(Request.QueryString) <> "" Then strTemp = strTemp & "?" & Trim(Request.QueryString)

    strTemp = LCase(strTemp)

    If Instr(strTemp,"select%20") or Instr(strTemp,"insert%20") or Instr(strTemp,"delete%20from") or Instr(strTemp,"count(") or Instr(strTemp,"drop%20table") or Instr(strTemp,"update%20") or Instr(strTemp,"truncate%20") or Instr(strTemp,"asc(") or Instr(strTemp,"mid(") or Instr(strTemp,"char(") or Instr(strTemp,"xp_cmdshell") or Instr(strTemp,"exec%20master") or Instr(strTemp,"net%20localgroup%20administrators")  or Instr(strTemp,":") or Instr(strTemp,"net%20user") or Instr(strTemp,"") or Instr(strTemp,"%20or%20") then
     Response.Write "<scrīpt language=javascrīpt>"
     Response.Write "alert(非法地址!!);"
     Response.Write "location.href=error.asp;"
     Response.Write "<scrīpt>"
    End If
    %>
    [CODE END]





    C# 检查字符串,防SQL注入攻击
    这个例子里暂定为=号和号
    bool CheckParams(params object[] args)
    {
        string[] Lawlesses={"=",""};
        if(Lawlesses==null||Lawlesses.Length<=0)return true;
        //构造正则表达式,例:Lawlesses是=号和号,则正则表达式为 .*[=}].*  (正则表达式相关内容请见MSDN)
        //另外,由于我是想做通用而且容易修改的函数,所以多了一步由字符数组到正则表达式,实际使用中,直接写正则表达式亦可;

        string str_Regex=".*[";
        for(int i=0;i< Lawlesses.Length-1;i++)
            str_Regex+=Lawlesses[i]+"|";
        str_Regex+=Lawlesses[Lawlesses.Length-1]+"].*";
        //
        foreach(object arg in args)
        {
            if(arg is string)//如果是字符串,直接检查
            {
                if(Regex.Matches(arg.ToString(),str_Regex).Count>0)
                return false;
            }
            else if(arg is ICollection)//如果是一个集合,则检查集合内元素是否字符串,是字符串,就进行检查
            {
                foreach(object obj in (ICollection)arg)
                {
                    if(obj is string)
                    {
                        if(Regex.Matches(obj.ToString(),str_Regex).Count>0)
                        return false;
                    }
                }
            }
        }
        return true;
  • (转)LoadRunner性能测试指标分析

    2009-03-21 16:56:57

    LoadRunner性能测试指标

    Object

    Counters

    Descrīption

    Reference value

    Memory

    Available Mbytes

    可用物理内存数.如果Available Mbytes的值很小(4 MB或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存。

    4 MB或更小,至少要有10%的物理内存值

    Page/sec

    (Input/Out)

    为了解析硬页错误,从磁盘取出或写入的页数。一般如果Page/sec持续高于几百,那么您应该进一步研究页交换活动。有可能需要增加内存,以减少换页的需求(你可以把这个数字乘以4k就得到由此引起的硬盘数据流量)。Pages/sec的值很大不一定表明内存有问题,而可能是运行使用内存映射文件的程序所致。

    推荐00-20

    如果服务器没有足够的内存处理其工作负荷,此数值将一直很高。如果大于80,表示有问题(太多的读写数据操作要访问磁盘,可考虑增加内存或优化读写数据的算法)

    该系列计数器的值比较低说明响应请求比较快, 否则可能是服务器系统内存短缺引起(也可能是缓存太大, 导致系统内存太少)。

     

     

    >5越低越好

    Page Fault

    处理器每秒处理的错误页(包括软/硬错误)。

    当处理器向内存指定的位置请求一页(可能是数据或代码)出现错误时,这就构成一个Page Fault。如果该页在内存的其他位置,该错误被称为软错误(用Transition Fault/sec记数器衡量);如果该页必须从硬盘上重新读取时,被称为硬错误。许多处理器可以在有大量软错误的情况下继续操作。但是,硬错误可以导致明显的拖延。

    Page Input/sec

    为了解决硬错误页,从磁盘上读取的页数。

    Page Output/sec

     

    Page reads/sec

    为了解决硬错误页,从磁盘上读取的次数。解析对内存的引用,必须读取页文件的次数。阈值为>5.越低越好。大数值表示磁盘读而不是缓存读。

    Cache Bytes

    文件系统缓存,默认情况下为50%的可用物理内存。如IIS5.0运行内存不够时,它会自动整理缓存。需要关注该计数器的趋势变化

     

    内存泄露

    如果您怀疑有内存泄露,请监视Memory\\ Available BytesMemory\\ Committed Bytes,以观察内存行为,并监视您认为可能在泄露内存的进程的Process\\Private BytesProcess\\Working SetProcess\\Handle Count。如果您怀疑是内核模式进程导致了泄露,则还应该监视Memory\\Pool Nonpaged BytesMemory\\ Pool Nonpaged AllocsProcess(process_name)\\ Pool Nonpaged Bytes

     

    Process

    Page Faults/sec

    将进程产生的页故障与系统产生的相比较,以判断这个进程对系统页故障产生的影响。

     

    Private Bytes

    此进程所分配的无法与其它进程共享的当前字节数量。如果系统性能随着时间而降低,则此计数器可以是内存泄漏的最佳指示器。

     

    Work set

    处理线程最近使用的内存页,反映了每一个进程使用的内存页的数量。如果服务器有足够的空闲内存,页就会被留在工作集中,当自由内存少于一个特定的阈值时,页就会被清除出工作集。

     

    Processor

    % Processor Time

    被消耗的处理器时间数量.如果服务器专用于sql server可接受的最大上限是80% -85%.也就是常见的CPU使用率.

     

    ProcessorQueue Length

    判断CPU瓶颈,如果processor queue length显示的队列长度保持不变(>=2)并且处理器的利用率%Processor time超过90%,那么很可能存在处理器瓶颈.如果发现processor queue length显示的队列长度超过2,而处理器的利用率却一直很低,或许更应该去解决处理器阻塞问题,这里处理器一般不是瓶颈.

     

    Physical

    Disk

    %DiskTime

    指所选磁盘驱动器忙于为读或写入请求提供服务所用的时间的百分比。

    正常值<10,此值过大表示耗费太多时间来访问磁盘,可考虑增加内存、更换更快的硬盘、优化读写数据的算法。若数值持续超过80 (此时处理器及网络连接并没有饱和),则可能是内存泄漏。

     

    CurrentDiskQueueLength

    读取和写入请求(为所选磁盘在实例间隔中列队的)的平均数。(磁盘数1.5-2)

     

    Avg.Disk Queue

    Length

    Avg.Disk Read

    QueueLength

    Avg.Disk Write

    QueueLength

    Disk Read/sec

    Disk Write/sec

    读取和写入请求(为所选磁盘在实例间隔中列队的)的平均数。

    磁盘瓶颈判断公式:

    每磁盘的I/O=(读次数+4*写次数))/磁盘个数。

    如果计算出来的每磁盘的I/O数大于磁盘的处理能力,那么磁盘存在瓶颈。

    Avg.DiskQueue Length正常值<0.5,此值过大表示磁盘IO太慢,要更换更快的硬盘。

     

     

  • (转)LoadRunner常用函数

    2009-03-21 16:53:26

      LoadRunner常用函数......

    1.        Intweb_reg_save_param("参数名","LB=左边界","RB=右边界",LAST);/注册函数,在参数值出现的前面使用,注册成功时返回值为0,注册失败时返回值为1。左右边界需根据TreeView里相关步骤的SeverResponse代码来确定。用以上函数能获取第一个符合条件的数值。

    2.        web_reg_save_param("参数名”,"LB=左边界”,"RB=右边界","Ord=All",LAST);/当参数有多个值时,加上"Ord=All”后可获取所有的数值。注册成功后,{参数名_count}表示取得的数值个数,{参数名_1}为第一个数值,{参数名_2}为第二个数值。

    3.        lr_save_string(“字符串变量”,"参数名")/将字符变量里的值传递给指定参数。通过该函数来改变DataFile类型参数的数值。

    4.        lr_eval_string("{参数名}")/取得参数的数值。可取得已注册参数或DataFile类型参数的数值。eval就是evaluation(估价,评价,赋值)的缩写。

    5.        int sprintf(char * string , const char*format_string[,args]);/字符串赋值函数

    Action()

    {

    int index=56;

    charfilename[64],*suffix="txt";

    sprintf(filename,"log_%d.%s",index,suffix);

    lr_output_message("Thenewfilenameis%s",filename);

    return 0;

    }

    Output:Thenewfilenameislog_56.txt

    6.        char*strcat(char*to,constchar*from);/将一字符串追加到另一字符串后面

    7.        web_find("find_time","What=2006-03-0118:21:16.882",LAST);/增加检查点,检查“2006-03-0118:21:16.882”这个字符串是否出现在当前页面上。find_time为自己任意输入的检查点名称。

    8.      事务函数

    lr_end_sub_transaction/标记子事务的结束以便进行性能分析

    lr_end_transaction/标记LoadRunner事务的结束

    lr_end_transaction_instance/标记事务实例的结束以便进行性能分析

    lr_fail_trans_with_error/将打开事务的状态设置为LR_FAIL并发送错误消息

    lr_get_trans_instance_duration/获取事务实例的持续时间(由它的句柄指定)

    lr_get_trans_instance_wasted_time/获取事务实例浪费的时间(由它的句柄指定)

    lr_get_transaction_duration/获取事务的持续时间(按事务的名称)

    lr_get_transaction_think_time/获取事务的思考时间(按事务的名称)

    lr_get_transaction_wasted_time/获取事务浪费的时间(按事务的名称)

    lr_resume_transaction/继续收集事务数据以便进行性能分析

    lr_resume_transaction_instance/继续收集事务实例数据以便进行性能分析

    lr_set_transaction_instance_status/设置事务实例的状态

    lr_set_transaction_status/设置打开事务的状态

    lr_set_transaction_status_by_name/设置事务的状态

    lr_start_sub_transaction/标记子事务的开始

    lr_start_transaction/标记事务的开始

    lr_start_transaction_instance/启动嵌套事务(由它的父事务的句柄指定)

    lr_stop_transaction/停止事务数据的收集

    lr_stop_transaction_instance/停止事务(由它的句柄指定)数据的收集

    lr_wasted_time/消除所有打开事务浪费的时间

    lr_end_sub_transaction/标记子事务的结束以便进行性能分析

    r_end_transaction/标记LoadRunner事务的结束

    lr_end_transaction_instance/标记事务实例的结束以便进行性能分析

    lr_fail_trans_with_error/将打开事务的状态设置为LR_FAIL并

     

    9.     命令行分析函数

    lr_get_attrib_double/检索脚本命令行中使用的double类型变量

    lr_get_attrib_long/检索脚本命令行中使用的long类型变量

    lr_get_attrib_string/检索脚本命令行中使用的字符串

    10. 信息性函数

    lr_user_data_point/记录用户定义的数据示例

    lr_whoami/将有关Vuser脚本的信息返回给Vuser脚本

    lr_get_host_name/返回执行Vuser脚本的主机名

    lr_get_master_host_name/返回运行LoadRunnerController的计算机名

    11. 字符串函数

    lr_eval_string/用参数的当前值替换参数

    lr_save_string/将以NULL结尾的字符串保存到参数中

    lr_save_var/将变长字符串保存到参数中

    lr_save_datetime/将当前日期和时间保存到参数中

    lr_advance_param/前进到下一个可用参数

    lr_decrypt/解密已编码的字符串

    lr_eval_string_ext/检索指向包含参数数据的缓冲区的指针

    lr_eval_string_ext_free/释放由lr_eval_string_ext分配的指针

    lr_save_searched_string/在缓冲区中搜索字符串实例,并相对于该字符串实例,该缓冲区的一部分保存到参数中

    12. 消息函数

    lr_debug_message/将调试消息发送到输出窗口

    lr_error_message/将错误消息发送到输出窗口

    lr_get_debug_message/检索当前的消息类

    lr_log_message/将输出消息直接发送到output.txt文件,此文件位于Vuser脚本目录中。该函数有助于防止输出消息干扰TCP/IP通信。

    lr_output_message/将消息发送到输出窗口

    lr_set_debug_message/为输出消息设置消息类

    lr_vuser_status_message/生成格式化输出并将其打印到ControllerVuser状态区域。

    lr_message/将消息发送到Vuser日志和输出窗口

    13. 操作函数

    web_custom_request允许您使用HTTP支持的任何方法来创建自定义HTTP请求
    web_image在定义的图像上模拟鼠标单击
    web_link在定义的文本链接上模拟鼠标单击
    web_submit_data执行“无条件”或“无上下文”的表单
    web_submit_form模拟表单的提交
    web_url加载由“URL”属性指定的URL

    14. 身份验证函数

    身份验证函数web_set_certificate使Vuser使用在InternetExplorer注册表中列出的特定证书
    身份验证函数web_set_certificate_ex指定证书和密钥文件的位置和格式信息
    身份验证函数web_set_user指定Web服务器的登录字符串和密码,用于Web服务器上已验证用户身份的区域

    15. 缓存函数

    缓存函数web_cache_cleanup清除缓存模拟程序的内容

    16. 检查函数

    检查函数web_find在HTML页内搜索指定的文本字符串
    检查函数web_global_verification在所有后面的HTTP请求中搜索文本字符串
    检查函数web_image_check验证指定的图像是否存在于HTML页内
    检查函数web_reg_find在后面的HTTP请求中注册对HTML源或原始缓冲区中文本字符串的搜索

    17. 连接定义函数

    连接定义函数web_disable_keep_alive禁用Keep-AliveHTTP连接
    连接定义函数web_enable_keep_alive启用Keep-AliveHTTP连接
    连接定义函数web_set_connections_limit设置Vuser在运行脚本时可以同时打开连接的最大数目

    18. 并发组

    web_concurrent_end标记并发组的结束
    web_concurrent_start标记并发组的开始

    19. cook函数

    web_add_cookie添加新的Cookie或修改现有的Cookie
    web_cleanup_cookies删除当前由Vuser存储的所有Cookie
    web_remove_cookie删除指定的Cookie

    20. 关联函数

    web_create_html_param将HTML页上的动态信息保存到参数中。(LR6.5及更低版本)
    web_create_html_param_ex基于包含在HTML页内的动态信息创建参数(使用嵌入边界)(LR6.5及更低版本)。
    关联函数

     
  • (转)Loadrunner message函数详细分析

    2009-03-21 16:52:30

    Loadrunner提供了若干message函数,以在脚本回放中和脚本运行中,对外输入信息,主要的函数有:
    【lr_message】
     int lr_message (const char *format, exp1, exp2,...expn.);
     中文解释:lr_message函数将信息发送到日志文件和输入窗口。在VuGen中运行时,输入文件为output.txt。

    【lr_log_message】
     int lr_log_message (const char *format, exp1, exp2,...expn.);
     中文解释:lr_log_message函数将消息发送到Vuser或代理日志文件(取决于应用程序),而不是发送到输出窗口。通过向日志文件
        发送错误消息或其他信息性消息,可以将该函数用于调试。

    【lr_error_message】
     int lr_error_message (const char *format, exp1, exp2,...expn. );
     中文解释:lr_error_message函数将错误消息发送到输出窗口和Vuser日志文件。要发送不是特定错误消息的特殊通知,请使用lr_output_message。

    【lr_output_message】
     int lr_output_message (const char *format, exp1, exp2,...expn.);
     中文解释:lr_output_message函数将带有脚本部分的行号的消息发送到输出窗口和日志文件。

    【lr_vuser_status_message】
     int lr_vuser_status_message (const char *format);
     中文解释:lr_vuser_status_message函数向控制器或优化模块控制台的vuser窗口的“状态”区域发送字符串。它还将该字符串发送
        到vuser日志。从VuGen运行时,消息被发送到output.txt。

    下面大家看例子:
    Action()
    {
     int i,j,k;
     char *message;
     j = k = 1000;

     message = "信息";
     lr_message("****************输出区域开始*****************");
     lr_message("   lr_message   %s:十进制=%d,八进制=%o,十六进制=0x%x",message,j,j,j);
     lr_log_message("   lr_log_message   %s:十进制=%d,八进制=%o,十六进制=0x%x",message,j,j,j);
     lr_error_message("   lr_error_message   %s:十进制=%d,八进制=%o,十六进制=0x%x",message,j,j,j);
     lr_output_message("  lr_output_message   %s:十进制=%d,八进制=%o,十六进制=0x%x",message,j,j,j);
     lr_message("****************输出区域结束*****************");
     for (i=1;i<6;i++)
     {
      k += 1000;
      lr_think_time (5);
      lr_vuser_status_message("第%d次:%s,十进制=%d,八进制=%o,十六进制=0x%x",i,message,k,k,k);
     }
     return 0;
    }
    例子说明:
    1、message系列的函数参数格式和c语言中的printf格式是完全相同的。
    2、格式化输入标志符号"%",想必大家也比较熟悉。其中%d是十进制,%o是八进制,%x是十六进制,%s是字符;还有%g、%u、%c等,自己去查。
    3、回放这个脚本后,进入脚本根目录查看mdrv.log,所有输出都可以在这里找到。
    4、lr_error_message回放日志中显示的是红色的字体,且显示语句所在行号;同时,如果脚本在controllor中运行时,会生成一个error信息。
    5、lr_vuser_status_message会在controllor的vuser list的status列中显示,controllor每5秒刷新一次。
    6、当然,也支持转义字符的使用,列表如下:
    \a 铃声(警告)
    \b Backspace 键
    \f 换页
    \n 换行
    \r 回车
    \t 水平制表符
    \v 垂直制表符
    \' 单引号标记
    \" 双引号标记
    \\ 反斜杠
    \? 文本问号
    \ooo ASCII 字符 - 八进制
    支持的转换字符有:
    %a ASCII 表示形式
    %BX 大端(网络顺序)十六进制
    %BO 大端(网络顺序)八进制
    %BD 大端(网络顺序)十进制
    %LX 小端十六进制
    %LO 小端八进制
    %LD 小端十进制

    ==============================================================

    此外,loadrunner还提供了在脚本中控制runtime-setting的log设置的函数。
    【lr_debug_message函数组】
    int lr_debug_message (unsigned int message_level, const char *format, ... );
     中文解释:lr_debug_message函数在指定的消息级别处于活动状态时发送一条调试信息。如果指定的消息级别未出于活动状态,则不
        发送消息。您可以从用户界面或者使用lr_set_debug_message, 将处于活动状态的消息级别设置为MSG_CLASS_BRIEF_LOG
        或MSG_CLASSS_EXTENDED_LOG。要确定当前级别,请使用lr_get_debug_message。

    unsigned int lr_get_debug_message ( );
     中文解释:lr_get_debug_message函数返回当前的日志运行时设置。该设置确定发送到输出端的信息。日志设置是使用运行时设置对
        话框或通过使用lr_set_debug_message函数指定的。

    int lr_set_debug_message (unsigned int message_level, unsigned int on_off);
     中文解释:lr_set_debug_message函数设置脚本执行的调试消息级别message_lvl。通过设置消息级别,可以确定发送哪些信息。 启
        动设置的方法是将LR_SWITCH_ON作为on_off传递,禁用设置的方法是传递LR_SWITCH_OFF。

    参数message_level说明:
    【日志级别】====【C语言标志】====【值】====【Runtime-setting - Log操作】 
    【Disabled】====【LR_MSG_CLASS_DISABLE_LOG】====【0】====【不勾选Enable logging】 
    【Brief】====【LR_MSG_CLASS_BRIEF_LOG】====【1】====【勾选Standard log】
    【Extended Log】====【LR_MSG_CLASS_EXTENDED_LOG】====【16】====【勾选Extended log】
    【Result Data】====【LR_MSG_CLASS_RESULT_DATA】====【2】====【勾选Data returned by server】
    【Parameter Substitution】====【LR_MSG_CLASS_PARAMETERS】====【4】====【勾选Parameter substitution】 
    【Full Run-Time Trace】====【LR_MSG_CLASS_FULL_TRACE】====【8】====【 勾选 Advanced trace】
    【Only on error】====【LR_MSG_CLASS_JIT_LOG_ON_ERROR】====【512】====【勾选send messages only when an error occurs】 

    参数on_off说明:
    【LR_SWITCH_ON】启用设置
    【LR_SWITCH_OFF】禁用设置


    看下面的小例子:
    Action()
    {
     int log_leavl;
     log_leavl = lr_get_debug_message();
     lr_error_message ("当前是:%d",log_leavl);
     return 0;
    }
    当我设置只有错误信息(error)打印【勾选send messages only when an error occurs】,例子运行结果是:当前是:513;
    为什么不是512呢,我发现我实际选择的是【Enable logging + send messages only when an error occurs】,按上面的
    参数说明,就是【1+512】,也就是513了;因此:
    lr_get_debug_message返回的int数其实是所有勾选操作的代表值相加!


    再看下面设置的例子:

    Action()
    {
    //设置runtime-setting的日志选项【不勾选Enable logging】
     char *a;
     a = "ABC";
     lr_set_debug_message (LR_MSG_CLASS_EXTENDED_LOG |LR_MSG_CLASS_PARAMETERS,LR_SWITCH_ON);
     //打开Runtime-setting Log 的Parameter substitution设置
     lr_debug_message(LR_MSG_CLASS_PARAMETERS,"打开参数保存的系统日志");
     lr_save_string("aa",a);
     lr_debug_message(LR_MSG_CLASS_PARAMETERS,"关闭参数保存的系统日志");
     lr_set_debug_message (LR_MSG_CLASS_EXTENDED_LOG |LR_MSG_CLASS_PARAMETERS,LR_SWITCH_OFF);
     //关闭Runtime-setting Log 的Parameter substitution设置

     return 0;
    }
    因为设置了runtime-setting不打印任何日志,所以正常运行脚本应该没有任何日志输出;
    但是使用lr_set_debug_message函数打开了日志的设置(输出保存参数操作的日志)
    因此脚本运行到lr_save_string("aa",a)时,就输出了日志如下:

    打开参数保存的系统日志
    Action.c(7): Notify: Saving Parameter "ABC = aa"
    关闭参数保存的系统日志

  • (转)Loadrunner中参数设置详细分析

    2009-03-21 16:46:37

    Loadrunner中参数设置详细分析(一)

    相信对大家会有用的,这个版本是基于7.8的。
    做负载或者压力测试时,很多人选择使用了Loadrunner测试工具。该工具的基本流程是先将用户的实际操作录制成脚本,然后产生数千个虚拟用户运行脚本(虚拟用户可以分布在局域网中不同的PC机上),最后生成相关的报告以及分析图。但是在录制脚本的过程中会遇到很多实际的问题,比如不同的用户有不同的使用数据,这就牵涉到参数的设置问题。本文就Loadrunner中参数的设置进行说明,希望对大家有所帮助。
       在录制程序运行的过程中,VuGen(脚本生成器) 自动生成了包含录制过程中实际用到的数值的脚本。如果你企图在录制的脚本中使用不同的数值执行脚本的活动(如查询、提交等等),那么你必须用参数值取代录制的数值。这个过程称为参数化脚本。
       本文主要包括如下内容:理解参数的局限性、建立参数、定义参数的属性、理解参数的类型、为局部数据类型设置参数的属性、为数据文件设置参数的属性、从已经存在的数据库中引入数据。
       除了GUI,以下的内容适合于各种类型的用户脚本。
    一、关于参数的定义
       在你录制程序运行的过程中,脚本生成器自动生成由函数组成的用户脚本。函数中参数的值就是在录制过程中输入的实际值。
       例如,你录制了一个Web应用程序的脚本。脚本生成器生成了一个声明,该声明搜索名称为“UNIX”的图书的数据库。当你用多个虚拟用户和迭代回放脚本时,也许你不想重复使用相同的值“UNIX”。那么,你就可以用参数来取代这个常量。结果就是你可以用指定的数据源的数值来取代参数值。数据源可以是一个文件,也可以是内部产生的变量。
       用参数表示用户的脚本有两个优点:
    ① 可以使脚本的长度变短。
    ② 可以使用不同的数值来测试你的脚本。例如,如果你企图搜索不同名称的图书,你仅仅需要写提交函数一次。在回放的过程中,你可以使用不同的参数值,而不只搜索一个特定名称的值。
       参数化包含以下两项任务:
    ① 在脚本中用参数取代常量值。
    ② 设置参数的属性以及数据源。
       参数化仅可以用于一个函数中的参量。你不能用参数表示非函数参数的字符串。另外,不是所有的函数都可以参数化的。

     

    二、参数的创建
       可以指定名称和类型来创建参数。不存在对脚本中参数个数的限制。在Web程序的用户脚本中,你可以使用如下过程在基于文本的脚本视图中创建参数。或者,也可以在基于图标的树形视图中创建参数。
       在基于文本的脚本视图中创建一个参数:
    1、 将光标定位在要参数化的字符上,点击右键。打开弹出菜单。
    2、 在弹出菜单中,选择“Replace with a Parameter”。选择或者创建参数的对话框弹出。
    3、 在“Parameter name”中输入参数的名称,或者选择一个在参数列表中已经存在的参数。
    4、 在“Parameter type”下拉列表中选择参数类型。
    5、 点击“OK”,关闭该对话框。脚本生成器便会用参数中的值来取代脚本中被参数化的字符,参数用一对“{}”括住。
       注意:在参数化CORBA或者General-Java 用户脚本的时候,必须参数化整个字符串,而不是其中的部分。另外注意:除了Web或者WAP,缺省的参数括号对于任何脚本都是 “{}”。你可以在“General Options”对话框中的“Parameterization”标签(Tools>General Options)中定义参数括号种类。
    6、 用同样的参数替换字符的其余情况,选中参数,点击右键,弹出菜单。从弹出的菜单中,选择“Replace More Occurrences”。搜索和替换对话框弹出。“Find What”中显示了你企图替换的值。“Replace With”中显示了括号中参数的名称。选择适当的检验框来匹配整个字符或者大小写。如果要搜索规则的表达式(.,!,?等等),选中“Regular Expression”检验框,然后点击“Replace”或者“Replace All”。
       注意:小心使用“Replace All”,尤其替换数字字符串的时候。脚本生成器将会替换字符出现的所有情况。
    7、 如果想用以前定义过的参数来替换常量字符串的话,选中该字符串,点击右键,然后选择“Use Existing Parameter”,子菜单“Use Existing Parameters”弹出。从子菜单“Use Existing Parameters”选择参数,或者用“Select from Parameter List”来打开参数列表对话框。
       注意:如果用以前定义过的参数来替换常量字符串的话,那么,使用“Parameter List”非常方便。同时,还可以查看和修改该参数的属性。
    8、 对于已经用参数替换过的地方,如果想取回原来的值,那么,就在参数上点击右键,然后选择“Restore Original value”。
       在Web用户脚本的树形视图中创建参数:
    1、将光标定位在企图参数化的地方,点击右键,从弹出的菜单中选择“Properties”。则相关的属性对话框打开。
    2、点击在要参数化的参量的旁边的“ABC”形状的图标。“Select or Create Parameter”对话框打开。
    3、在“Parameter name”中输入参数的名称,或者从列表中选择一个已经存在的参数。
    4、在“Parameter type”中输入参数的类型。
    5、点击“OK”关闭该对话框。用户脚本生成器会用参数来替换最初的字符串常量,并用一个表格形状的图标替换“ABC”形状的图标。
    6、要恢复参数化以前的值,点击图标,然后从弹出的菜单中选择“Undo Parameter”,则以前的值便会重现。

     

    三、定义参数的属性
       创建参数完成后,就可以定义其属性了。参数的属性定义就是定义在脚本执行过程中,参数使用的数据源。在Web用户脚本中,你既可以在基于文本的脚本视图中定义参数属性,也可以在基于图标的树形视图中定义参数属性。下面的过程将教你如何在基于本文的脚本视图中定义参数属性。
       在基于文本的脚本视图中定义参数属性步骤:
    1、 在参数上点击右键,有菜单弹出。
    2、 在弹出的菜单中,选择“Parameter Properties”。参数属性对话框打开,显示和当前参数类型相关的属性。
    3、 输入参数的属性值。
    4、 点击“Close”关闭参数属性对话框。
        在Web用户脚本的树形视图中定义参数的属性:
    1、 将关标定位在参数上,然后点击右键,选择“Properties”。属性对话框打开。
    2、 点击要定义属性的参数旁边的表格形状按钮,点击右键,选择“Parameter Properties”。参数属性对话框打开,和参数类型相关的属性显示出来。
    3、 输入参数的属性。
    4、 点击“Close”关闭参数属性对话框。
       使用参数列表:
      使用参数列表可以在任意时刻查看所有的参数,创建新的参数、删除参数,或者修改已经存在参数的属性。
    1、 点击参数列表按钮或者用“Vuser>Parameter List”。参数列表对话框打开。
    2、 要创建新的参数,点击“New”按钮。新的参数则被添加在参数树中,该参数有一个临时的名字,你可以给它重新命名,然后回车。设置参数的类型和属性,点击“OK”,关闭参数列表对话框。
       注意:不要将一个参数命名为“unique”,因为这个名称是用户脚本生成器本身的。用户脚本生成器创建新的参数,但是不会自动用该参数在脚本中替换任意选中的字符串。
    3、 要删除已有的参数,那么,要先从参数树中选择该参数,点击“Delete”,然后确认你的行为即可。
    4、 要修改已有参数,那么,要先从参数树中选择该参数,然后编辑参数的类型和属性。

    四、理解参数的类型
      在你定义参数属性的时候,要指定参数值的数据源。你可以指定下列数据源类型的任何一种:
    Internal Data―― 虚拟用户内部产生的数据。
    Data Files ――存在于文件中的数据。可能是已存在的文件或者是用脚本生成器新创建的。
    User-Defined Functions―― 调用外部DLL函数生成的数据
      Internal Data包括以下几种:
    1、 Date/Time
      Date/Time用当前的日期/时间替换参数。要指定一个Date/Time格式,你可以从菜单列表中选择格式,或者指定你自己的格式。这个格式应该和你脚本中录制的Date/Time格式保持一致。
    2、 Group Name
      Group Name 用虚拟用户组名称替换参数。在创建scenario的时候,你可以指定虚拟用户组的名称。当从用户脚本生成器运行脚本的时候,虚拟用户组名称总是None。
    3、 Load Generator Name
      Load Generator Name用脚本负载生成器的名称替换参数。负载生成器是虚拟用户在运行的计算机。
    4. Iteration Number
      Iteration Number用当前的迭代数目替换参数。
    5、 Random Number
      Random Number用一个随机数替换参数。通过指定最大值和最小值来设置随机数的范围。
    6、 Unique Number
      Unique Number用一个唯一的数字来替换参数。你可以指定一个起始数字和一个块的大小。
    7、 Vuser ID
      Vuser ID用分配给虚拟用户的ID替换参数,ID是由Loadrunner的控制器在scenario运行时生成的。如果你从脚本生成器运行脚本的话,虚拟用户的ID总是-1。

    五、数据文件
      数据文件包含着脚本执行过程中虚拟用户访问的数据。局部和全局文件中都可以存储数据。可以指定现有的ASCII文件、用脚本生成器创建一个新的文件或者引入一个数据库。在参数有很多已知值的时候数据文件非常有用。数据文件中的数据是以表的形式存储的。一个文件中可以包含很多参数值。每一列包含一个参数的数据。列之间用分隔符隔开,比如说,用逗号。
      对数据文件设置参数属性
      如果使用文件作为参数的数据源,必须指定以下内容:文件的名称和位置、包含数据的列、文件格式,包括列的分隔符、更新方法。
     如果参数的类型是“File”,打开参数属性(Parameter Properties)对话框,设置文件属性如下:
    1、 在“File path”中输入文件的位置,或者点击“Browse”指定一个已有文件的位置。缺省情况下,所有新的数据文件名都是“parameter_name.dat”,注意,已有的数据文件的后缀必须是.dat。
    2、 点击“Edit”。记事本打开,里面第一行是参数的名称,第二行是参数的初始值。使用诸如逗号之类的分隔符将列隔开。对于每一新的表行开始一行新的数据。
      注意:在没有启动记事本的情况下如果想添加列,就在参数属性对话框中点击“Add Col”,那么“Add new column”对话框就会弹出。输入新列的名称,点击“OK”。脚本生成器就会添加该列到表中,并显示该列的初始值。
    3、 在“Select Column”部分,指明包含当前参数数据的列。你可以指定列名或者列号。列号是包含你所需要数据的列的索引。列名显示在每列的第一行(row 0)。
    4、 在“Column delimiter”中输入列分隔符,你可以指定逗号、空格符等等。
    5、 在“First data line”中,在脚本执行的时候选择第一行数据使用。列标题是第0行。若从列标题后面的第一行开始的话,那就在“First data line”中输入1。如果没有列标题,就输入0。
    6、 在“Select next row”中输入更新方法,以说明虚拟用户在脚本执行的过程中如何选择表中的数据。方法可以是:连续的、随机的、唯一的、或者与其它参数表的相同行。
    6.1、 顺序(Sequential):该方法顺序地给虚拟用户分配参数值。如果正在运行的虚拟用户访问数据表的时候,它会取到下一行中可用的数据。
    6.2、 随机(Random):该方法在每次迭代的时候会从数据表中取随机数
    6.3、 使用种子取随机顺序(Use Random Sequence with Seed):如果从Loadrunner的控制器来运行scenario,你可以指定一个种子数值用于随机顺序。每一个种子数值在测试执行的时候代表了一个随机数的顺序。无论你何时使用这个种子数值,在scenario中同样的数据顺序就被分配给虚拟用户。如果在测试执行的时候发现了一个问题并且企图使用同样的随机数序列来重复测试,那么,你就可以启动这个功能(可选项)。
    6.4、 唯一(Unique):Unique方法分配一个唯一的有顺序的值给每个虚拟用户的参数。
    6.5 、与以前定义的参数取同一行(Same Line As <parameter>):该方法从和以前定义过的参数中的同样的一行分配数据。你必须指定包含有该数据的列。在下拉列表中会出现定义过的所有参数列表。注意:至少其中的一个参数必须是Sequential、Random或者Unique。

    如果数据表中有三列,三个参数定义在列表中:id1,name1和title1,如下:。
    ID Name Title
    132 Kim Manager
    187 Cassie Engineer
    189 Jane VP
        对于参数id1,你可以指示虚拟用户使用Random方法,而为参数name1和title1就可以指定方法“Same Line as id1”。所以,一旦ID“132”被使用,那么,姓名(Name)“Kim”和职位(Title)“Manager”同时被使用。

    7、Updta value on数据的更新方法
    7.1、Each iteration――每次反复都要取新值
    7.2、Each occurrence――只要发现该参数就重新取值
    7.3、Once――在所有的反复中都使用同一个值
    8、When out of values超出范围:(选择数据为unique时才可用到)
    8.1、Abort Vuser――中止
    8.2、Continue in a cyclic manner――继续循环取值
    8.3、Continue with last value――取最后一个值
    9、Allocate Vuser values in the Controller在控制器中分配值:(选择数据为unique时才可用到)
    9.1、 Automatically allocate block size――自动分配
    9.2、Allocate()values for each Vuser――指定一个值

    六、从已存在的数据库中导入数据

    Loadrunner允许你利用参数化从已经存在的数据库中导入数据。可以使用下列两种方式之一:
    1、 使用Microsoft Query(要求在系统上先安装MS Query)。
    2、 指定数据库连接字符串和SQL语句。
        用户脚本生成器在从数据库中导入数据的过程中提供了一个向导。在向导中,你指明如何导入数据-通过MS Query创建查询语句或者直接书写SQL语句。在导入数据以后,以.dat为后缀并作为正规的参数文件保存。要开始导入数据库中数据的过程,在参数属性对话框中点击“Data Wizard”,则,数据库查询向导弹出。
      要创建新的查询
    1、 选择“Create new query”。如果需要MS Query的帮助,选择“Show me how to use Microsoft Query”,然后点击“Finish”。
    如果你还没有安装Microsoft Query,Loadrunner会提示你这个功能不可用。在进行之前,从Microsoft Office中安装MS Query。
    2、 在Microsoft Query中遵循以下步骤,导入期望的表和列。
    3、 在完成数据的导入后,选择“Exit and return to Virtual User Generator”,然后点击“Finish”。在参数属性对话框中数据库记录以data文件的形式显示出来。
    要在MS Query中编辑并查看数据,选择“View data or edit in Microsoft Query”。若要结束,则选择“File>Exit and return to Virtual User Generator”返回到脚本生成器。
    4、 在“Select Column”部分,指定包含当前参数数据的列可以指定列号或者列名。注意:列标题默认为第0行(row 0)。
    5、 从“Select next row”列表中选择一个更新方法来告诉虚拟用户在脚本指定的过程中如何选择表中的数据。可选项是:Sequential、Random、Unique或者Same Line As。其中每一项的含义文章前面已经讲述,就不再赘述。
    6、 如果选择“Advance row each iteration”,虚拟用户在每次迭代的时候会使用新的一行的数据而不是重复同样的数据。
      要指定数据库连接或者SQL语句
    1、 选择“Specify SQL Statement”,然后点击“Next”。
    2、 点击“Create”指定一个新的连接字符串。选择数据源的窗口弹出。
    3、 选择已有的数据源,或者点击“New”创建一个新的数据源。向导将提示你穿过创建ODBC数据源的过程。在完成后,连接字符串就会在连接字符串框中显示出来。
    4、 在SQL框中,输入或者粘贴SQL语句。
    5、 点击“Finish”继续SQL语句并导入数据。数据库记录将以data文件的形式显示在参数属性框中。
    6、 在“Select Column”部分中,指定包含当前参数数据的列。你可以指定列号或者列名。
    7、 从“Select next row”列表中选择一个更新方法来告诉虚拟用户在脚本指定的过程中如何选择表中的数据。可选项是:Sequential、Random、Unique或者Same Line As。


     

     

  • (转)学习loadrunner之一_事务

    2009-03-21 16:39:25

    Loadrunner是一款负载测试工具,它有三个核心组件分别是Virtual User GeneratorControllerAnalysisVirtual User Generator可以通过录制脚本准确的记录下来用户的每一步操作并且可以进行集合点设置、事务设置、参数化等操作从而为在Controller中执行特定的场景做准备。Controller顾名思义,它可以控制脚本的执行,通过把脚本放置在一个特定的场景中,模拟一批真实用户的操作过程,这些模拟的真实用户就叫做虚拟用户。通过这些虚拟用户可以对系统进行负载测试。Analysis应该是测试人员极为关注的一个组件,通过Controller执行完某一个场景之后,Analysis可以自动生成测试结果并通过图形的形式显示出来,测试人员只有借助这些图表才能准确分析出系统的瓶颈并且确定性能是否达到要求。

        下面介绍一下如何进行集合点、检查点以及参数化的设置:

        对于集合点、检查点的设置有两种方法,一种是在录制完脚本以后,手工在脚本中添加相关的关键字例如lr_start_transaction等,这种方法对脚本语言的理解能力要求较高。另一种是直接在录制的过程中添加集合点、检查点,这样lr就会自动把集合点、检查点的关键字添加到脚本中。

        事务:就是用户某一步或者某几步操作的集合。当我们需要通过某一步或是某几步操作从而衡量服务器的性能的时候,这时我们就把这些操作设置成一个事务,当事务开始执行的时候lr就开始计时当事务运行结束计时停止,执行事务的时间会在在最后的结果中显示出来。

        实例:登录sina网站,把点击“天气”设置成一个事务,衡量服务器处理处理该事务的性能。

        1,点击红色的录制按钮,输入URL开始录制。弹出sina的首页,点击<!--[if !vml]--><!--[endif]-->设置事物的开始位置,这时弹出事务开始对话框要求输入事务的名称,一般来讲我们都会把事务名称命名为容理解的名字,此处我们命名为“天气”

        点击OK完成事务的开始点设置。

        2,在sina页面上点击“天气”的连接,出现天气页面

        3,点击<!--[if !vml]--><!--[endif]-->设置事务的结束点,这时弹出事务结束对话框

        lr根据匹配原则已经自动把事务名字一栏填入“天气”,我们只需要选择事务的状态。状态有三种LR_AUTOLR_PASSLR_FAILLR_STOP

        LR_AUTO:事物的状态被自动设置,如果事务执行成功,状态设置为PASS,如果执行失败,状态设置为FAIL,如果由于异常中断,状态被设置成STOP.

        LR_PASS:事务如果执行成功,代码的返回状态就是PASS

        LR_FAIL:事务如果执行失败,代码的返回状态就是FAIL

        一般我们选择LR_AUTO那么我们会有疑问什么时候我们选择PASS或者是FAIL呢?

        Lr的帮助文档中有一条例子,可以很好的帮助我们理解

    lr.start_transaction("GetStocks");
    try {

    String stocks[];
    stocks = orStockServer1.getStockList();
    if (stocks.length == 0)

                  throw new Exception("No stocks returned/available");
    lr.end_transaction("GetStocks", lr.PASS);
    }

    catch (Exception e1) {

           lr.end_transaction("GetStocks", lr.FAIL);

           lr.message(" An exception occurred : " + e1.toString() );

           }

    代码说明:这时一个得到stock list的例子,程序中设置了异常检查来确保getStockList()方法返回非零的长度。

     

    同时我也进行了如下的脚本修改

    ………………

    lr_start_transaction("天气");

       lr_think_time( 3 );

       web_add_cookie("mysinal=ai_erica; DOMAIN=weather.news.sina.com.cn");

       web_add_cookie("SINAGLOBAL=221.219.31.58.924471172571904604; DOMAIN=weather.news.sina.com.cn");

    ………………

    lr_end_transaction("天气", LR_FAIL);

        在最后我把该事物的结束状态设置为FAIL,然后运行该脚本,其实该事物的运行是没有任何错误的,完全可以运行成功,只是在最后我把事务的状态手工设置为FAIL。当脚本执行完后,查看Ececution Log看到这样一条log语句:

        Action.c(297): Notify: Transaction "天气" ended with "Fail" status (Duration: 5.1436).

        那么这样做的意义是什么呢?为什么要设置事务结束状态呢?原因就是在Analysis中生成结果图表的时候我们就能看到这个名为“天气”的事务执行是失败的。如果语句是这样:

        Action.c(297): Notify: Transaction "天气" ended with "Pass" status (Duration: 5.1436).

        Analysis中生成结果图表的时候我们就能看到这个名为“天气”的事务执行是成功的。

        设置事务结束状态的用途就在这里。试想Lr为什么能自动生成结果图表?无非就是Analysis通过一些定义好的API获取执行脚本过程中的返回值,从而显示出事务执行的正确还是错误,或是显示出响应时间等信息,然后调用GUI使我们很直观的看到测试结果。

  • (转)LoadRunner脚本编程(例子)

    2009-03-21 15:37:06

    LoadRunner脚本编程

    今天想统计一下我的BLOG的访问情况,想知道那些文章被经常阅读。在BLOG的后台没找到相关功能,既然没有那就自已动手吧,要想统计就需要数据,数据只能从网页里来。从网页中取数据一个是手工取,一个是自动来取。手工取没啥兴趣,那就自动取吧,网页的格式都是有一定规律的,自动取会很方便。先打开一页,看看源代码需要取数据的点有那些特征。打开页面后找到了需要的特征,在每个标题前有一段HTML代码 “<img src=images/face/1.gif >” 在每篇文章的点击次数有特征标示 “阅读全文”,有了这两个特征就可以提取需要的数据了。

    下面是具体的LoadRunner脚本代码

    #include "as_web.h"
    int i,j; //定义变量,循环次数
    char URL1[512],COUNT[512],Name[512]; //定义变量,存储参数化名称
    Action1()
    {
       for(i=1;i<=10;i++)//当前BLOG只有10页 所以循环次数为10
       {  

           web_reg_save_param("Count","LB=阅读全文(","RB=)</a>","ORD=all",LAST);  //设定点击数参数化变量

           web_reg_save_param("Name","LB=<img src=images/face/1.gif >","RB=</a>","ORD=all",LAST);//设定标题参数化变量

           sprintf(URL1,"URL=http://www1.testage.net/blog/blog.asp?name=alanstone&page=%d",i);//准备需要访问的URL

           web_url("Link",URL1,LAST); //访问URL

           for(j=1;j<=atoi(lr_eval_string("{Count_count}"));j++) //按得到的参数化变量数量进行循环
           {

               sprintf(COUNT,"{Count_%d}",j); //准备点击次数参数化变量

               sprintf(Name,"{Name_%d}",j); //准备标题参数化变量

               lr_message("%s   %s",lr_eval_string(Name),lr_eval_string(COUNT));//打印标题和点击次数   
            }
        }
    return 0;
    }

    该脚本唯一有点难度的是需要一点C语言的基础,同时对于web_reg_save_param参数有一些了解,具体web_reg_save_param参数使用方法可以查看LR的联机文档。
  • 如何在loadrunner中做关联

    2009-03-21 15:22:10

    如何在LoadRunner脚本中做关联 (Correlation) (转贴hanxue1230)
    j%G}.z^3tLI138711当录制脚本时,VuGen会拦截client端(浏览器)与server端(网站服务器)之间的对话,并且通通记录下来,产生脚本。在VuGen的Recording Log中,您可以找到浏览器与服务器之间所有的对话,包含通讯内容、日期、时间、浏览器的请求、服务器的响应内容等等。脚本和Recording Log最大的差别在于,脚本只记录了client端要对server端所说的话,而Recording Log则是完整纪录二者的对话。
    +?dv0@[^Hz9h,Z138711
    u(p+h4Af)r2{,a;J138711当执行脚本时,您可以把VuGen想象成是一个演员,它伪装成浏览器,然后根据脚本,把当初真的浏览器所说过的话,再对网站伺服器重新说一遍,VuGen企图骗过服务器,让服务器以为它就是当初的浏览器,然后把网站内容传送给VuGen。51Testing软件测试网3k1?e8M:Y6A
    所以纪录在脚本中要跟服务器所说的话,完全与当初录制时所说的一样,是写死的(hard-coded)。这样的作法在遇到有些比较聪明的服务器时,还是会失效。这时就需要透过「关联(correlation)」的做法来让VuGen可以再次成功地骗过服务器。51Testing软件测试网l+].ZI2`Qxm{#_
    何谓关联(correlation)?51Testing软件测试网4b)tW\:U)^
    所谓的关联(correlation)就是把脚本中某些写死的(hard-coded)数据,转变成是撷取自服务器所送的、动态的、每次都不一样的数据。51Testing软件测试网z2D!@(\$k1|I
    举一个常见的例子,刚刚提到有些比较聪明的服务器,这些服务器在每个浏览器第一次跟它要数据时,都会在数据中夹带一个唯一的辨识码,接下来就会利用这个辨识码来辨识跟它要数据的是不是同一个浏览器。一般称这个辨识码为Session ID。对于每个新的交易,服务器都会产生新的Session ID给浏览器。这也就是为什么执行脚本会失败的原因,因为VuGen还是用旧的Session ID向服务器要数据,服务器会发现这个Session ID是失效的或是它根本不认识这个Session ID,当然就不会传送正确的网页数据给VuGen了。
    g&s Ws(U7K8OP5p\138711下面的图示说明了这样的情形:51Testing软件测试网UYP*Yo'B
    当录制脚本时,浏览器送出网页A的请求,服务器将网页A的内容传送给浏览器,并且夹带了一个ID=123的数据,当浏览器再送出网页B的情求时,这时就要用到ID=123的数据,服务器才会认为这是合法的请求,并且把网页B的内容送回给浏览器。51Testing软件测试网}r.U-H5M J
    在执行脚本时会发生什么状况?浏览器再送出网页B的请求时,用的还是当初录制的ID=123的数据,而不是用服务器新给的ID=456,整个脚本的执行就会失败。
    {&?6o mJVS138711
    tjujK\%Cu138711要对付这种服务器,我们必须想办法找出这个Session ID到底是什么、位于何处,然后把它撷取下来,放到某个参数中,并且取代掉脚本中有用到Session ID的部份,这样就可以成功骗过服务器,正确地完成整个交易了。
    j9VUv CZ,H H_138711哪些错误代表着我应该做关联(correlation)?
    kv5r/z`S138711假如脚本需要关联(correlation),在还没做之前是不会执行通过的,也就是说会有错误讯息发生。不过,很不幸地,并没有任何特定的错误讯息是和关联(correlation)有关系的。会出现什么错误讯息,与系统实做的错误处理机制有关。错误讯息有可能会提醒您要重新登入,但是也有可能直接就显示HTTP 404的错误讯息。
    '\)fmtA*j@'S138711要如何做关联(correlation)?51Testing软件测试网Y4Sv,h\1Ze
    关联(correlation)函数
    e*pCwN)G[ \138711关联(correlation)会用到下列的函数:51Testing软件测试网} s+Ms @
    • web_reg_save_param:这是最新版,也是最常用来做关联(correlation)的函数。
    z-A;U1d%`r1|~ ?138711语法:
    byp$d}0a138711web_reg_save_param ( “Parameter Name” , < list of Attributes >, LAST );51Testing软件测试网J/{b$L,y$A
    • web_create_html_param、web_create_html_param_ex:这二个函数主要是保留作为向前兼容的目的的。建议使用 web_reg_save_param 函数。
    v.|p%DF+mP[1d]N138711详细用法请参考使用手册。在VuGen中点选【Help】>【Function reference】>【Contexts】>【Web and Wireless Vuser Functions】>【Correlation Functions】。51Testing软件测试网 ?p{1W%S!ti
    如何找出要关联(correlation)数据
    Q*y9vI&E m138711简单的说,每一次执行时都会变动的值,就有可能需要做关联(correlation)。51Testing软件测试网&l4ZQ^l#I!rX
    VuGen提供二种方式帮助您找出需要做关联(correlation)的值:
    h3h'@5{Y&t1387111. 自动关联51Testing软件测试网O*WE j9xg$G;T`[
    2. 手动关联
    8J{ ~ot1C8hY y138711自动关联
    "f9}go/@4nY&R138711VuGen内建自动关联引擎(auto-correlation engine),可以自动找出需要关联的值,并且自动使用关联函数建立关联。
    r,t5j+V`$B f]1u;h138711自动关联提供下列二种机制:
    ZJHvj P-A;U138711• Rules Correlation:在录制过程中VuGen会根据订定的规则,实时自动找出要关联的值。规则来源有两种:
    .{;LX9U)d+WP.~138711o 内建(Built-in Correlation):
    (J!kc` i[~138711VuGen已经针对常用的一些应用系统,如AribaBuyer、BlueMartini、BroadVision、InterStage、mySAP、NetDynamics、Oracle、PeopleSoft、Siebel、SilverJRunner等,内建关联规则,这些应用系统可能会有一种以上的关联规则。您可以在【Recording Options】>【Internet Protocol】>【Correlation】中启用关联规则,则当录制这些应用系统的脚本时,VuGen会在脚本中自动建立关联。51Testing软件测试网0`$B0D,XYGK
    您也可以在【Recording Options】>【Internet Protocol】>【Correlation】检视每个关联规则的定义。51Testing软件测试网 av%u `4G"l0f
    o 使用者自订(User-defined Rules Correlation):
    V L"qZ"` |138711除了内建的关联规则之外,使用者也可以自订关联规则。您可以在【Recording Options】>【Internet Protocol】>【Correlation】建立新的关联规则。51Testing软件测试网Gq7Ich7R2c
    • Correlation Studio:有别于Rules Correlation,Correlation Studio则是在执行脚本后才会建立关联,也就是说当录制完脚本后,脚本至少须被执行过一次,Correlation Studio才会作用。Correlation Studio会尝试找出录制时与执行时,服务器响应内容的差异部分,藉以找出需要关联的数据,并建立关联。51Testing软件测试网+CG`3Bqc7\ G#z!OL$b
    Rule Correlation51Testing软件测试网{m RqG&^#k^
    请依照以下步骤使用Rule Correlation:51Testing软件测试网1W0EW(}i5hZ!g p4iy
    1. 启用auto-correlation51Testing软件测试网X#dOB qSZ [
    1. 点选VuGen的【Tools】>【Recording Options】,开启【Recording Options】对话窗口,选取【Internet Protocol】>【Correlation】,勾选【Enable correlation during recording】,以启用自动关联。51Testing软件测试网9c1V(Q#a(yn
    2. 假如录制的应用系统属于内建关联规则的系统,如AribaBuyer、BlueMartini、BroadVision、InterStage、mySAP、NetDynamics、Oracle、PeopleSoft、Siebel、SilverJRunner等,请勾选相对应的应用系统。
    T/q8| CvJu1387113. 或者也可以针对录制的应用系统加入新的关联规则,此即为使用者自订的关联规则。
    -T7wLK y:Y,@S1387114. 设定当VuGen侦测到符合关联规则的数据时,要如何处理:
    f(M rm#H#q5a138711 【Issue a pop-up message and let me decide online】:跳出一个讯息对话窗口,询问您是否要建立关联。
    TS-x4c |J{SV138711 【Perform. correlation in sceipt】:直接自动建立关联51Testing软件测试网OM$~:S)ddR
    2. 录制脚本
    2i9t7~0b8T"mu%?138711开始录制脚本,在录制过程中,当VuGen侦测到符合关联规则的数据时,会依照设定建立关联,您会在脚本中看到类似以下的脚本,此为BroadVision应用系统建立关联的例子,在脚本批注部分可以看到关联前的数据为何。
    H\?r0PU4y138711
    (fqi9BI&G#X1387113. 执行脚本验证关联是OK的。51Testing软件测试网!?1cxbR9j4y4S
    Correlation Studio51Testing软件测试网u6jPv-VZ2U
    当录制的应用系统不属于VuGen预设支持的应用系统时,Rule Correlation可能既无法发挥作用,这时可以利用Correlation Studio来做关联。
    -V7V ir4c;r ]138711Correlation Studio会尝试找出录制时与执行时,服务器响应内容的差异部分,藉以找出需要关联的数据,并建立关联。
    S'@i o0?138711使用Correlation Studio的步骤如下:
    $g RY9B`/E g$Ju1387111. 录制脚本并执行
    OJ+|&XBJT7}]1387112. 执行完毕后,VuGen会跳出下面的【Scan Action for Correlation】窗口,询问您是否要扫描脚本并建立关联,按下【Yes】按钮。
    N9o5pv1G3v];l138711
    N6s_T Y1387113. 扫描完后,可以在脚本下方的【Correlation Results】中看到扫描的结果。
    )~u0W}i:r4OO138711
    c2s,J+e$moBb1387114. 检查一下扫瞄的结果后,选择要做关联的数据,然后按下【Correlate】按钮,一笔一笔做,或是按下【Correlate All】让VuGen一次就对所有的数据建立关联。51Testing软件测试网.b HH,MF$|UC5~
    注意:由于Correlation Studio会找出所有有变动的数据,但是并不是所有的数据都需要做关联,所以不建议您直接用【Correlate All】。
    1_B^Zf+~1I T9T|1387115. 一般来说,您必须一直重复步骤1~4直到所有需要做关联的数据都找出来为止。因为有时前面的关联还没做好之前,将无法执行到后面需要做关联的部份。
    $r O_g8G+h)p138711有可能有些需要做关联的动态数据,连Correlation Studio都无法侦测出来,这时您就需要自行做手动关联了。
    ;b,{&` p,tnqS4UZ138711手动关联51Testing软件测试网B Md2C&G0N
    手动关联的执行过程大致如下:
    E0QR1l(e[[Q1387111. 使用相同的业务流程与数据,录制二份脚本51Testing软件测试网 \Bp$C'@kx
    2. 使用WinDiff工具协助找出需要关联的数据
    $mvc"n8XZq A1387113. 使用web_reg_save_param函数手动建立关联51Testing软件测试网.pu{R4_[ \
    4. 将脚本中有用到关联的数据,以参数取代
    'ib5T+^8|/X TI*O138711接下来将详细的说明如何执行每个步骤51Testing软件测试网B{.iC+B"G
    使用相同的业务流程与数据,录制二份脚本
    kJU \ c0{Qqm1387111. 先录制一份脚本并存档。51Testing软件测试网&g L#gHo[B x
    2. 依照相同的操作步骤与数据录制第二份脚本并存盘。注意,所有的步骤和输入的数据一定都要一样,这样才能找出由服务器端产生的动态数据。
    $o|0U-k2t#V{138711有时候会遇到真的无法使用相同的输入数据,那您也要记住您使用的输入数据,到时才能判断是您输入的数据,还是变动的数据。51Testing软件测试网Y TOR;qRp1C
    使用WinDiff工具协助找出需要关联的数据51Testing软件测试网ED1]/UIr
    1. 在第二份脚本中,点选VuGen的【Tools】>【Compare with Vuser…】,并选择第一份脚本。
    e0KB\P^4dq1387112. 接着WinDiff会开启,同时显示二份脚本,并显示有差异的地方。WinDiff会以一整行黄色标示有差异的脚本,并且以红色的字体显示真正差异的文字。(假如没看到红色字体,请点选【Options】>【View】>【Show Inline Differences】)。
    .Jznbl1387113. 逐一检视二份脚本中差异的部份,每一个差异都可能是需要做关联的地方。选取差异的脚本,然后复制。51Testing软件测试网8J1]k8vT(J
    在复制时,有时并不需要取整行脚本,可能只会选取脚本中的一部分。
    [C;R/V Q{+p138711注意:请忽略lr_thik_time的差异部份,因为lr_thik_time是用来模拟每个步骤之间使用者思考延迟的时间。
    ;s"\+D;|F6^ qXK M13871151Testing软件测试网#@my1GJ ` K
    4. 接着要在Recording Log(单一protocol)或是Generation Log(多重protocol)中找这个值。将鼠标光标点到Recording Log的第一行开头,按下Ctrl+F,开启【Find】窗口,贴上刚刚复制的脚本,找出在Recording Log第一次出现的位置。51Testing软件测试网`U1r$\!F2@ oz6R{'{ ^

    kI `,N$z t-M#v138711结果会有二种:51Testing软件测试网3aj}3a'x-{Z
    o 在Recording Log中找不到要找的数据,这时请先确认您找对了脚本,毕竟现在开启了二个几乎一样的脚本,很容易弄错。51Testing软件测试网)w ]2CiO
    o 在Recording Log中找到了要找的数据,这时要确认数据是从服务器端传送过来的。首先可以先检查数据的标头,从标头的Receiving response可以知道数据是从服务器端传送到client端的。假如此数据第一次出现是在Sending request中,则表示此数据是由client端产生,不需要做关联,但是有可能需要做参数化(parameterized)。51Testing软件测试网G)ZC(P3x$T"b{
    您要找的标头格式如下:
    j)?jPoI!f138711*** [tid=b9 Action1 2] Receiving response from host astra.merc-int.com:80 ( 25/11/2002 12:04:00 )
    T7ZBz5_ {*B+[,U138711
    ~ UR4VY:F{"e1387115. 现在您已经找到录制二次都不一样,而且是由服务器所产生的动态数据了,而此数据极有可能需要做关联。
    3E^U hp}?s138711使用web_reg_save_param函数手动建立关联
    !}N.eTJ5T(C(D138711在找到是由服务器所产生的动态数据之后,接下来要做的就是找出适当的位置,使用web_reg_save_param函数,将这个动态数据撷取到某个参数中。
    p+uL x{"q6ARK@1387111. 要在哪里使用web_reg_save_param函数?51Testing软件测试网d kNO~(S
    在之前的步骤,我们已经在Execution Log找到可能需要关联的动态数据。在Execution Log中选取动态数据前的文字然后复制,我们将会利用这段文字,来帮助我们找出要关联的动态数据。51Testing软件测试网El b1GRy-r.]
    51Testing软件测试网 Xt%H5Bruu2f#u
    不过在这之前我们要先找出使用web_reg_save_param函数的正确位置,所以我们要再重新执行一遍脚本,而且这次会开启所有的Log。
    M%|Z$Z~6WVO1387111. 在VuGen中点选【Vuser】>【Run-Time Settings】。
    OF W$J}1387112. 点选【General】>【Log】。
    |-hw6U%fw pc1387113. 勾选【Enable logging】、【Always sends messages】、【Extended log】,以及【Extended log】下的所有选项。51Testing软件测试网Iuz0bf*wn5ap@
    4. 按下【OK】就可以执行脚本了。
    K"N1I4C+H^%E138711执行完脚本之后,在Execution Log中搜寻刚刚复制的字符串。找到字符串后,在字符串前面会有A.tion1.c(7),这个7就是到时候要插入web_reg_save_param函数的位置,也就是要插入到脚本的第7行。
    dJ rc@;t-x}K[138711在脚本的第7行前插入一行空白行,然后输入
    6aaINtB r138711web_reg_save_param(“UserSession”,51Testing软件测试网m&}UW/p
    “UserSession” 这个 “UserSession” 就是到时要使用的参数名称,建议给个有意义的名字。
    QW f%f#m9W;sL*m@138711注意:到这里整个web_reg_save_param函数还没完成。51Testing软件测试网0U ss{o

    &|^kMD1bJR:BW1387112. 找出web_reg_save_param中要用到的边界
    1EZS/{)l c f138711web_reg_save_param函数主要是透过动态数据的前面和后面的固定字符串,来辨识要撷取的动态数据的,所以我们还需要找出动态数据的边界字符串。
    0^V.uCH/Y S7]f138711找出左边界字符串51Testing软件测试网 {6LW`P"C
    再回到Execution Log中,选取动态数据前的字符串并且复制它。51Testing软件测试网.Y} f7W(h Q/Gv
    这时会有个问题,到底要选取多少字符串才足以唯一识别要找的动态数据呢?建议是越多越好,但是尽量不要包含到特殊字符。
    8v\S1Lea2v B2MI8m138711在这边我们选取「input type=hidden name=userSession value=」字符串。选好之后,还要再确认一次这段字符串真的是可以唯一识别的,所以我们在Execution Log中透过Ctrl+F的搜寻,找找看这段字符串是否可以找到要找的动态数据。假如找不到,web_reg_save_param函数还有个ORD参数可以使用,ORD参数可以设定出现在第几次的字符串才是要找的字符串。51Testing软件测试网!|8f!q&dB/b(Y
    将这个边界字符串加到未完成的web_reg_save_param函数中:51Testing软件测试网2t_ y U*q Y
    web_reg_save_param(“UserSession”, “LB= input type=hidden name=userSession value=”,
    {_t;tA;z6i138711找出右边界字符串51Testing软件测试网&P5\%r2py/H Zm`&T
    接下来要找出动态数据的右边界字符串,这个字符串就比较好找了,从动态数据的最后一个字符开始,通常就是我们要找的右边界字符串了。
    ](i9_(h\ks+?138711以这个例子来看,就是「>」,所以再把右边界字符串加入,web_reg_save_param函数中,这时web_reg_save_param函数已经快完成了。最后再加上「LAST);」就完成整个web_reg_save_param函数了。
    | ra8N G138711web_reg_save_param(“UserSession”, “LB= input type=hidden name=userSession value=”, “RB=>”, LAST);51Testing软件测试网(J,D's,M:w4T
    51Testing软件测试网q2?b'DP%{]HN
    将脚本中有用到关联的数据,以参数取代51Testing软件测试网$V)PkPM:B b(z ]y3o
    当使用web_reg_save_param建立参数后,接下来就是用“UserSession”参数去取代脚本中写死的(hard-coded)资料。
    :C2N:vX0a$iPWL o z1`138711范例:51Testing软件测试网sTXdO!`2]s
    51Testing软件测试网7A&S pp#L
    “Name=userSession”, “Value=75893.0884568651DQADHfApHDHfcDtccpfAttcf”, ENDITEM,51Testing软件测试网)x~}j F)?
    换成51Testing软件测试网0kAcuA5a2d
    “Name=userSession”, “Value={UserSession}”, ENDITEM,51Testing软件测试网} C2]s|;AP$V%y
    51Testing软件测试网n^)?CW:C
    到这里您已经完成了一个关联了,接下来就是执行脚本,是否能成功运行,假如还是有问题,就要检查看看是否还需要再做另一个关联。51Testing软件测试网+_ lm@$STJ+B
    关于 web_reg_save_param 函数
    0Y"Y#uA+R-W+Q1[138711对于关联(correlation)来说,web_reg_save_param是最重要的一个函数,其功能是在下载的网页内容中,透过设定的边界字符串,找出特定的数据并将其储存在一个参数中,以供后续脚本使用。51Testing软件测试网.k-XR%d8i pF|
    接下来将针对web_reg_save_param做比较详细的说明。
    K4},q(C3I#L%nE|138711Service and registration type function
    ~+].Gm%M~ D138711web_reg_save_param是一个Service function。service function主要是用来完成一些特殊的工作的,如关联、设定proxy、提供认证信息等,当其作用时,不会对网页的内容做任何的修改。
    q5K"PJ B%R:pHXb138711web_reg_save_param同时也是一个registration type function (只要函数名称中包含_reg_的字眼,表示其为registration type function)。registration type function意味着其真正作用的时机是在下一个action function完成时执行的。举例来说,当某个web_url执行时所接收到的网页内容中包含了要做关联的动态数据,则必须将web_reg_save_param放在此web_url之前,则web_reg_save_param会在web_url执行完毕后,也就是网页内容都下载完后,再执行web_reg_save_param找寻要做关联的动态数据并建立参数。
    Gh*dn2FkHQ138711所以要记住一点,要使用registration type function时,要注意其放置的位置必须在要作用的action function之前。51Testing软件测试网e8z,fcq.v
    语法
    9^!yq#| ~w b138711int web_reg_save_param(const char *ParamName, <list of Attributes>, LAST);
    l;I+Vc&_@138711参数说明
    lb V1X OF138711ParamName:存放动态数据的参数名称
    l4M$|6w)z9v#_138711list of Attributes:其它属性,包含 Notfound, LB, RB, RelFrameID, Search, ORD, SaveOffset, Convert, 以及 SaveLen。属性值不分大小写,例如 Search=all。以下将详细说明每个属性值的意义:51Testing软件测试网 r I8w;K2d ]E
    • Notfound:指定当找不到要找的动态数据时该怎么处置。
    +pkpo f sA6`f138711o Notfound=error:当找不到动态数据时,发出一个错误讯息。假如没设定此属性,此为LoadRunner的默认值。51Testing软件测试网@#L"~p?`fovs
    o Notfound=warning:当找不到动态数据时,不发出错误讯息,只发出警告,脚本也会继续执行下去不会中断。在对角本除错时,可以使用此属性值。
    z!tE$_B!\T&lT138711• LB:动态数据的左边界字符串。此属性质是必须要有的,而且区分大小写。
    _9J1LpI|sx138711• RB:动态数据的右边界字符串。此属性质是必须要有的,而且区分大小写。51Testing软件测试网X%yRw n B
    • RelFrameID:相对于URL而言,欲搜寻的网页的Frame。此属性质可以是All或是数字,而且可有可无。51Testing软件测试网)I#q BZ?-C
    • Search:搜寻的范围。可以是Headers(只搜寻headers)、Body(只搜寻body部分,不搜寻header)、Noresource(只搜寻body部分,不搜寻header与resource)或是All(搜寻全部范围,此为默认值)。此属性质可有可无。51Testing软件测试网2f3|(i#\/I0b X Q
    • ORD:指明从第几次出现的左边界开始才是要撷取的数据。此属性质可有可无,默认值是1。假如值为All,则所有找到符合的数据会储存在数组中。
    ?q}"p*h5Fc138711• SaveOffset:当找到符合的动态数据时,从第几个字符开始才开始储存到参数中。此属性质不可为负数,其默认值为0。51Testing软件测试网 ea%TK#a`u,M^
    • Convert:可能的值有二种:51Testing软件测试网 m7D7VWB2x"v:vZ
    o HTML_TO_URL: 将HTML-encoded数据转成URL-encoded数据格式
    H(Z#N#LW4]l138711o HTML_TO_TEXT:将HTML-encoded数据转成纯文字数据格式
    Fd]}7bNu] iE138711• SaveLen:从offect开始算起,到指定的长度内的字符串,才储存到参数中。此参数可有可无,默认值是-1,表示储存到结尾整个字符串。51Testing软件测试网 @2o`j0] x
    范例
    )by6L*r:s'T\Oz138711web_reg_save_param("A", "LB/ic=<a href=", "RB='>", "Ord=All", LAST);nner会搜寻网页中所有以 「<a href=」 开头,且以 「’>」结束,当中包含的字符串,并且储存在「A」参数中。
    &v|?M [ w9_#Rv []/l [{138711Tips and Tricks51Testing软件测试网6GK]#Nh&~0T
    以下提供一些关联的常见问题:51Testing软件测试网6U8C&ZhBd
    • 如何打印出参数值?51Testing软件测试网yc4_8hRqA)X
    lr_output_message这二个函数来做到。例如:51Testing软件测试网7i;_0b7x"T9I*S
    lr_output_message(“Value Captured = %s”, lr_eval_string(“{ParameterName}”));
    v*a[*I_6E6I ~'VzT138711lr_eval_string与lr_output_message函数的使用说明请参考LoadRunner Online Function Reference。51Testing软件测试网*u vD%w'Ys6D!U
    • 在脚本的data目录下找不到路制时的快照(snapshot)51Testing软件测试网vk#H*mvs4{y0E1K
    造成在脚本的data目录下找不到路制时的快照(snapshot)的可能原因如下:51Testing软件测试网r9Nu:N^+Ty
    o 脚本是由VuGen 6.02或更早的版本所录制的51Testing软件测试网 JY&W/Js4a
    o 汇入的Action不会包含快照(snapshot)的档案
    $snGG}1X138711o 脚本是储存在只读的目录下,早成VuGen无法储存执行时撷取的快照(snapshot)51Testing软件测试网A%[]zm ~
    o 某些步骤并不会产生快照(snapshot),如浏览某个资源
    I0j {)Gb(aA138711o 快照(snapshot)功能被取消51Testing软件测试网arW8D"@
    【Tools】>【General options】>【Correlation】tab >【Save correlation information during replay】51Testing软件测试网l1m OBj i
    • 开启WinDiff时出现「File no longer available」的错误讯息
    6v k?s,^4a138711WinDiff这个工具有些限制,无法开启包含空格符的目录或是脚本,所以建议命名时不要使用空格符,并且尽可能将名称取短一点。
    ,W&I$jA3bkH c/C~138711• 录制时突然跳出【Correlation warning】对话窗口51Testing软件测试网m QW2FM1O V H
    当你有勾选自动关联的【Issue a popup message and let me decide online】选项,当VuGen发现有可能要做关联的数据时,就会跳出【Correlation warning】的窗口,询问你要做关联(Correlation in scrīpt)还是要忽略(Ignore)。51Testing软件测试网;yb9p td&|X
    另外你也可以勾选【Perform. correlation in scrīpt】,让VuGen自动作关联,不会再跳出询问窗口。
    X ILP/\"D#[138711或是勾选【Disable correlation engine】,关闭自动关联的功能。51Testing软件测试网R0k-s2~ t0m E

    a+N&aW:s138711• 如何手动启动「Scan action for correlation」的功能51Testing软件测试网G%IF!J`\
    要手动启动「Scan action for correlation」的功能,请先执行脚本一次后,点选【Vuser】>【Scan Action for Correlation】。
    ,Z$]\Cx138711
    `[%[D$R3_ L1~g138711• 执行完脚本后并未出现【Scan Action for Correlation】窗口51Testing软件测试网F:nS``}P Y0i#]
    要启用【Scan Action for Correlation】功能,请点选【Tools】>【General options】>【Correlation】tab,勾选【Show Scan for correlation popup after replay of Vuser】选项。

  • (转)LoadRunner监视的性能计数器

    2009-03-21 15:14:11

    今天,我先把我整理的一些计数器及其阈值要求等贴出来,这些计数器是针对我对windows操作系统,C/S结构的sql server数据库及WEB平台.net产品测试时的一些计数器;大家可以继续补充,作过unix平台上oracle数据库测试及J2EE架构及WEBLOGIC方面测试的朋友,也希望把自己使用的计数器贴出来,让大家分享。
    好了,先说这些了,希望通过这个专题,最终能让大家对自己的测试结果进行分析。

    Memory:内存使用情况可能是系统性能中最重要的因素。如果系统“页交换”频繁,说明内存不足。“页交换”是使用称为“页面”的单位,将固定大小的代码和数据块从 RAM 移动到磁盘的过程,其目的是为了释放内存空间。尽管某些页交换使 Windows 2000 能够使用比实际更多的内存,也是可以接受的,但频繁的页交换将降低系统性能。减少页交换将显著提高系统响应速度。要监视内存不足的状况,请从以下的对象计数器开始:
    Available Mbytes:可用物理内存数. 如果Available Mbytes的值很小(4 MB 或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存。


    page/sec:表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁盘以释放工作集空间的页面数。一般如果pages/sec持续高于几百,那么您应该进一步研究页交换活动。有可能需要增加内存,以减少换页的需求(你可以把这个数字乘以4k就得到由此引起的硬盘数据流量)。Pages/sec 的值很大不一定表明内存有问题,而可能是运行使用内存映射文件的程序所致。


    page read/sec:页的硬故障,page/sec的子集,为了解析对内存的引用,必须读取页文件的次数。阈值为>5. 越低越好。大数值表示磁盘读而不是缓存读。
    由于过多的页交换要使用大量的硬盘空间,因此有可能将导致将页交换内存不足与导致页交换的磁盘瓶径混淆。因此,在研究内存不足不太明显的页交换的原因时,您必须跟踪如下的磁盘使用情况计数器和内存计数器:
    Physical Disk\ % Disk Time
    Physical Disk\ Avg.Disk Queue Length
    例如,包括 Page Reads/sec 和 % Disk Time 及 Avg.Disk Queue Length。如果页面读取操作速率很低,同时 % Disk Time 和 Avg.Disk Queue Length的值很高,则可能有磁盘瓶径。但是,如果队列长度增加的同时页面读取速率并未降低,则内存不足。
    要确定过多的页交换对磁盘活动的影响,请将 Physical Disk\ Avg.Disk sec/Transfer 和 Memory\ Pages/sec 计数器的值增大数倍。如果这些计数器的计数结果超过了 0.1,那么页交换将花费百分之十以上的磁盘访问时间。如果长时间发生这种情况,那么您可能需要更多的内存。


    Page Faults/sec:每秒软性页面失效的数目(包括有些可以直接在内存中满足而有些需要从硬盘读取)较page/sec只表明数据不能在内存的指定工作集中立即使用。
    Cache Bytes:文件系统缓存(File System Cache),默认情况下为50%的可用物理内存。如IIS5.0 运行内存不够时,它会自动整理缓存。需要关注该计数器的趋势变化
    如果您怀疑有内存泄露,请监视 Memory\ Available Bytes 和 Memory\ Committed Bytes,以观察内存行为,并监视您认为可能在泄露内存的进程的 Process\Private Bytes、Process\Working Set 和Process\Handle Count。如果您怀疑是内核模式进程导致了泄露,则还应该监视 Memory\Pool Nonpaged Bytes、Memory\ Pool Nonpaged Allocs 和 Process(process_name)\ Pool Nonpaged Bytes。


    Pages per second :每秒钟检索的页数。该数字应少于每秒一页。

    Process:
    %Processor Time: 被处理器消耗的处理器时间数量。如果服务器专用于sql server,可接受的最大上限是80-85%
    Page Faults/sec:将进程产生的页故障与系统产生的相比较,以判断这个进程对系统页故障产生的影响。
    Work set: 处理线程最近使用的内存页,反映了每一个进程使用的内存页的数量。如果服务器有足够的空闲内存,页就会被留在工作集中,当自由内存少于一个特定的阈值时,页就会被清除出工作集。
    Inetinfo:Private Bytes:此进程所分配的无法与其它进程共享的当前字节数量。如果系统性能随着时间而降低,则此计数器可以是内存泄漏的最佳指示器。

    Processor:监视“处理器”和“系统”对象计数器可以提供关于处理器使用的有价值的信息,帮助您决定是否存在瓶颈。
    %Processor Time:如果该值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。
    %User Time:表示耗费CPU的数据库操作,如排序,执行aggregate functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水平分割大表格等方法来降低该值。
    %Privileged Time:(CPU内核时间)是在特权模式下处理线程执行代码所花时间的百分比。如果该参数值和"Physical Disk"参数值一直很高,表明I/O有问题。可考虑更换更快的硬盘系统。另外设置Tempdb in RAM,减低"max async IO","max lazy writer IO"等措施都会降低该值。
    此外,跟踪计算机的服务器工作队列当前长度的 Server Work Queues\ Queue Length 计数器会显示出处理器瓶颈。队列长度持续大于 4 则表示可能出现处理器拥塞。此计数器是特定时间的值,而不是一段时间的平均值。
    % DPC Time:越低越好。在多处理器系统中,如果这个值大于50%并且Processor:% Processor Time非常高,加入一个网卡可能会提高性能,提供的网络已经不饱和。

    Thread
    ContextSwitches/sec: (实例化inetinfo 和dllhost 进程) 如果你决定要增加线程字节池的大小,你应该监视这三个计数器(包括上面的一个)。增加线程数可能会增加上下文切换次数,这样性能不会上升反而会下降。如果十个实例的上下文切换值非常高,就应该减小线程字节池的大小。

    Physical Disk:
    %Disk Time %:指所选磁盘驱动器忙于为读或写入请求提供服务所用的时间的百分比。如果三个计数器都比较大,那么硬盘不是瓶颈。如果只有%Disk Time比较大,另外两个都比较适中,硬盘可能会是瓶颈。在记录该计数器之前,请在Windows 2000 的命令行窗口中运行diskperf -yD。若数值持续超过80%,则可能是内存泄漏。
    Avg.Disk Queue Length:指读取和写入请求(为所选磁盘在实例间隔中列队的)的平均数。该值应不超过磁盘数的1.5~2 倍。要提高性能,可增加磁盘。注意:一个Raid Disk实际有多个磁盘。
    Average Disk Read/Write Queue Length:指读取(写入)请求(列队)的平均数。
    Disk Reads(Writes)/s: 物理磁盘上每秒钟磁盘读、写的次数。两者相加,应小于磁盘设备最大容量。
    Average Disksec/Read: 指以秒计算的在此盘上读取数据的所需平均时间。
    Average Disk sec/Transfer:指以秒计算的在此盘上写入数据的所需平均时间。
    Network Interface:
    Bytes Total/sec :为发送和接收字节的速率,包括帧字符在内。判断网络连接速度是否是瓶颈,可以用该计数器的值和目前网络的带宽比较

    SQLServer性能计数器:
    Access Methods(访问方法) 用于监视访问数据库中的逻辑页的方法。
    . Full Scans/sec(全表扫描/秒) 每秒不受限的完全扫描数。可以是基本表扫描或全索引扫描。如果这个计数器显示的值比1或2高,应该分析你的查询以确定是否确实需要全表扫描,以及S Q L查询是否可以被优化。
    . Page splits/sec(页分割/秒)由于数据更新操作引起的每秒页分割的数量。
    Buffer Manager(缓冲器管理器):监视 Microsoft&reg; SQL Server? 如何使用: 内存存储数据页、内部数据结构和过程高速缓存;计数器在 SQL Server 从磁盘读取数据库页和将数据库页写入磁盘时监视物理 I/O。 监视 SQL Server 所使用的内存和计数器有助于确定: 是否由于缺少可用物理内存存储高速缓存中经常访问的数据而导致瓶颈存在。如果是这样,SQL Server 必须从磁盘检索数据。 是否可通过添加更多内存或使更多内存可用于数据高速缓存或 SQL Server 内部结构来提高查询性能。
    SQL Server 需要从磁盘读取数据的频率。与其它操作相比,例如内存访问,物理 I/O 会耗费大量时间。尽可能减少物理 I/O 可以提高查询性能。
    .Page Reads/sec:每秒发出的物理数据库页读取数。这一统计信息显示的是在所有数据库间的物理页读取总数。由于物理 I/O 的开销大,可以通过使用更大的数据高速缓存、智能索引、更高效的查询或者改变数据库设计等方法,使开销减到最小。
    .Page Writes/sec (.写的页/秒) 每秒执行的物理数据库写的页数。
    .Buffer Cache Hit Ratio. 在“缓冲池”(Buffer Cache/Buffer Pool)中没有被读过的页占整个缓冲池中所有页的比率。可在高速缓存中找到而不需要从磁盘中读取的页的百分比。这一比率是高速缓存命中总数除以自 SQL Server 实例启动后对高速缓存的查找总数。经过很长时间后,这一比率的变化很小。由于从高速缓存中读数据比从磁盘中读数据的开销要小得多,一般希望这一数值高一些。通常,可以通过增加 SQL Server 可用的内存数量来提高高速缓存命中率。计数器值依应用程序而定,但比率最好为90% 或更高。增加内存直到这一数值持续高于90%,表示90% 以上的数据请求可以从数据缓冲区中获得所需数据。
    . Lazy Writes/sec(惰性写/秒)惰性写进程每秒写的缓冲区的数量。值最好为0。
    Cache Manager(高速缓存管理器) 对象提供计数器,用于监视 Microsoft&reg; SQL Server? 如何使用内存存储对象,如存储过程、特殊和准备好的 Transact-SQL 语句以及触发器。
    . Cache Hit Ratio(高速缓存命中率,所有Cache”的命中率。在SQL Server中,Cache可以包括Log Cache,Buffer Cache以及Procedure Cache,是一个总体的比率。) 高速缓存命中次数和查找次数的比率。对于查看SQL Server高速缓存对于你的系统如何有效,这是一个非常好的计数器。如果这个值很低,持续低于80%,就需要增加更多的内存。
    Latches(闩) 用于监视称为闩锁的内部 SQL Server 资源锁。监视闩锁以明确用户活动和资源使用情况,有助于查明性能瓶颈。
    . Average Latch Wait Ti m e ( m s ) (平均闩等待时间(毫秒)) 一个SQL Server线程必须等待一个闩的平均时间,以毫秒为单位。如果这个值很高,你可能正经历严重的竞争问题。
    . Latch Waits/sec (闩等待/秒) 在闩上每秒的等待数量。如果这个值很高,表明你正经历对资源的大量竞争。
    Locks(锁) 提供有关个别资源类型上的 SQL Server 锁的信息。锁加在 SQL Server 资源上(如在一个事务中进行的行读取或修改),以防止多个事务并发使用资源。例如,如果一个排它 (X) 锁被一个事务加在某一表的某一行上,在这个锁被释放前,其它事务都不可以修改这一行。尽可能少使用锁可提高并发性,从而改善性能。可以同时监视 Locks 对象的多个实例,每个实例代表一个资源类型上的一个锁。
    . Number of Deadlocks/sec(死锁的数量/秒) 导致死锁的锁请求的数量
    . Average Wait Time(ms) (平均等待时间(毫秒)) 线程等待某种类型的锁的平均等待时间
    . Lock Requests/sec(锁请求/秒) 每秒钟某种类型的锁请求的数量。
    Memory manager:用于监视总体的服务器内存使用情况,以估计用户活动和资源使用,有助于查明性能瓶颈。监视 SQL Server 实例所使用的内存有助于确定:
    是否由于缺少可用物理内存存储高速缓存中经常访问的数据而导致瓶颈存在。如果是这样,SQL Server 必须从磁盘检索数据。
    是否可以通过添加更多内存或使更多内存可用于数据高速缓存或 SQL Server 内部结构来提高查询性能。
    Lock blocks:服务器上锁定块的数量,锁是在页、行或者表这样的资源上。不希望看到一个增长的值。
    Total server memory:sql server服务器当前正在使用的动态内存总量.

    监视IIS需要的一些计数器
    Internet Information Services Global:
    File Cache Hits %、File CacheFlushes、File Cache Hits
    File Cache Hits %是全部缓存请求中缓存命中次数所占的比例,反映了IIS 的文件缓存设置的工作情况。对于一个大部分是静态网页组成的网站,该值应该保持在80%左右。而File Cache Hits是文件缓存命中的具体值,File CacheFlushes 是自服务器启动之后文件缓存刷新次数,如果刷新太慢,会浪费内存;如果刷新太快,缓存中的对象会太频繁的丢弃生成,起不到缓存的作用。通过比较File Cache Hits 和File Cache Flushes 可得出缓存命中率对缓存清空率的比率。通过观察它两个的值,可以得到一个适当的刷新值(参考IIS 的设置ObjectTTL 、MemCacheSize 、MaxCacheFileSize)
    Web Service:
    Bytes Total/sec:显示Web服务器发送和接受的总字节数。低数值表明该IIS正在以较低的速度进行数据传输。
    Connection Refused:数值越低越好。高数值表明网络适配器或处理器存在瓶颈。
    Not Found Errors:显示由于被请求文件无法找到而无法由服务器满足的请求数(HTTP状态代码404)

  • (转)数据驱动在QTP中的运用--使用SQL数据库

    2009-03-20 16:22:33

    本篇主要讲述Flight打开订单的正确性测试,通过数据库进行数据驱动测试,主要步骤和考虑思路如下:

            1.从数据库中随机读取一条存在的记录
            2.在Flight中打开本条记录
            3.比较数据库中的数据和软件界面上的显示是否一致
       - 其中数据库中读出的记录数据保存在局部变量中
       - 界面显示的实际数据通过Output Value保存到QTP自带的DataTable中.

     

    Option Explicit

    Dim conn, rst, maxnumber, rndNumber, sql
    Dim dbFlightNumber, dbTicketNumber, dbPlaneType, dbCustomerName
    Dim oPlaneType
    '------------------------------------------------------------------------------------------------------------------------------------------------------

    '获取数据库中的记录数据(期望结果)
    Const  strConn = "Provider=MSDASQL.1;Persist Security Info=False;Data Source=QT_Flight32"
    Set conn=CreateObject("Adodb.Connection")
    Set rst=CreateObject("Adodb.RecordSet")
    conn.open strConn

    '获取最大Order_Number
    sql = "select max(order_number) from orders "
    rst.Open sql, conn
    maxNumber = rst.Fields(0).Value
    rst.Close

    '随即获取一条记录
    rndNumber = RandomNumber(1, maxNumber)
    sql = "Select  Flight_Number, Tickets_Ordered, Class, Customer_Name  from orders where order_number =" & CStr(rndNumber)
    rst.Open sql, conn

    While rst.EOF
     rndNumber = RandomNumber(1, maxNumber)
     sql = "Select  Flight_Number, Tickets_Ordered, Class, Customer_Name  from orders where order_number =" & CStr(rndNumber)
     rst.Open sql, conn
    Wend

    rst.MoveFirst
    While not rst.EOF
        dbFlightNumber = rst.Fields(0).value
        dbTicketNumber =rst.Fields(1).value
        dbPlaneType = rst.Fields(2).value
        dbCustomerName = rst.Fields(3).value
        rst.MoveNext
    Wend

    conn.close
    Set rst=nothing
    Set conn=nothing


    '------------------------------------------------------------------------------------------------------------------------------------------------------
    '录制脚本程序
    SystemUtil.CloseProcessByName "Flight4a.exe"
    SystemUtil.Run Environment.Value("ProductDir") & "\samples\flight\app\flight4a.exe"
    Dialog("Login").WinEdit("Agent Name:").Set "Admin"
    Dialog("Login").WinEdit("Password:").Set "Mercury"
    Dialog("Login").WinButton("OK").Click
    Window("Flight Reservation").WinButton("Button").Click
    Window("Flight Reservation").Dialog("Open Order").WinCheckBox("Order No.").Set "ON"
    Window("Flight Reservation").Dialog("Open Order").WinEdit("Edit").Set rndNumber  '在这里Set 随机打开的订单
    Window("Flight Reservation").Dialog("Open Order").WinButton("OK").Click
    Window("Flight Reservation").Activate


    '获取 界面显示的实际数据(实际结果)
    Window("Flight Reservation").WinEdit("Flight No:").Output CheckPoint("Flight No:")
    Window("Flight Reservation").WinEdit("Tickets:").Output CheckPoint("Tickets:")
    Window("Flight Reservation").WinEdit("Name:").Output CheckPoint("CustomerName")

    '将界面上的仓位转换为1,2,3
    If Window("Flight Reservation").WinRadioButton("First").GetROProperty("Text") = "ON" Then
     oPlaneType = 1
    ElseIf Window("Flight Reservation").WinRadioButton("Business").GetROProperty("Text") = "ON" Then
     oPlaneType = 2
    ElseIf Window("Flight Reservation").WinRadioButton("Economy").GetROProperty("Text") = "ON" Then 
     oPlaneType = 3
    End If


    '检查Flight Number
    If CStr(dbFlightNumber) = CStr(DataTable("oFlightNumber", dtLocalSheet)) Then
     Reporter.ReportEvent micPass, "打开订单- Flight Number", "期望结果是:" & dbFlightNumber & ", 界面显示实际结果是:" & DataTable("oFlightNumber", dtLocalSheet)
    Else
     Reporter.ReportEvent micPass, "打开订单- Flight Number", "期望结果是:" & dbFlightNumber & ", 界面显示实际结果是:" & DataTable("oFlightNumber", dtLocalSheet)
    End If

    '检查Ticket Number
    If CStr(dbTicketNumber) = CStr(DataTable("oTicketNumber", dtLocalSheet)) Then
     Reporter.ReportEvent micPass, "打开订单- TicketNumber", "期望结果是:" & dbTicketNumber & ", 界面显示实际结果是:" & DataTable("oTicketNumber", dtLocalSheet)
    Else
     Reporter.ReportEvent micPass, "打开订单- TicketNumber", "期望结果是:" & dbTicketNumber & ", 界面显示实际结果是:" & DataTable("oTicketNumber", dtLocalSheet)
    End If

    '检查Customer Name
    If CStr(dbCustomerName) = CStr(DataTable("oCustomerName", dtLocalSheet)) Then
     Reporter.ReportEvent micPass, "打开订单- CustomerName", "期望结果是:" & dbCustomerName & ", 界面显示实际结果是:" & DataTable("oCustomerName", dtLocalSheet)
    Else
     Reporter.ReportEvent micPass, "打开订单- CustomerName", "期望结果是:" & dbCustomerName & ", 界面显示实际结果是:" & DataTable("oCustomerName", dtLocalSheet)
    End If

    '检查Plane Type
    If CStr(dbPlaneType) = CStr(oPlaneType) Then
     Reporter.ReportEvent micPass, "打开订单- Plane Type", "期望结果是:" & dbPlaneType & ", 界面显示实际结果是:" & oPlaneType
    Else
     Reporter.ReportEvent micPass, "打开订单- Plane Type", "期望结果是:" & dbPlaneType & ", 界面显示实际结果是:" & oPlaneType
    End If

    'Close Prog
    Window("Flight Reservation").Close

  • (转)数据驱动在QTP中的运用--使用ADODB导入EXCEL数据文件

    2009-03-20 16:21:56

    前面介绍的是直接使用EXCEL导入数据文件,在这里介绍使用ADODB导入EXCEL数据文件的方法。操作思想基本上是一致的,就是链接数据文件的方法不同。

    Option Explicit

    Dim conn, rst, fileName, strConn
    Dim var, i

    fileName = Environment.Value("TestDir") & "\test.xls"
    strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info = False;"
    strConn = strConn & "Data Source = " & filename & ";Extended Properties='Excel 8.0'"

    Set conn = CreateObject("ADODB.Connection")
    conn.Open strConn
    Set rst = CreateObject("ADODB.RecordSet")
    rst.Open "select * from [Sheet1$]", conn, 1, 1

    Print rst.RecordCount
    i = 0
    '读取Excel表格时,自动从第二行开始读起,将第一行作为Title
    While Not rst.EOF
     i = i + 1
     Print "LINE " & CStr(i) & " : " & rst.Fields(0).Value & " " & rst.Fields(1).Value
     rst.MoveNext
    Wend
     
    rst.Close
    Set rst = Nothing 

  • (转)数据驱动在QTP中的运用--自定义EXCEL文件

    2009-03-20 16:21:10

    本节共有两个实例,第一个是把测试用例的数据写到EXCEL文件中,第二个是通过读取EXCEL文件中的数据,并把执行结果写入到EXCEL文件中。

    1.对EXCEL文件进行写操作
     
    Option Explicit
     
    Dim fso, ddFilePath, i
    Dim ExcelBook, ExcelSheet
     
    ddFilePath = Environment.Value("TestDir") & "\ddFile.xls"
     
    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso.FileExists(ddFilePath) Then
           fso.DeleteFile(ddFilePath)
    End If
    wait 3
     
     
    Set ExcelBook = CreateObject("Excel.Application")
    Set ExcelSheet = CreateObject("Excel.Sheet")
    ExcelSheet.Application.visible = False
     
    ExcelSheet.ActiveSheet.Cells(1,1).Value = "Agent Name"
    ExcelSheet.ActiveSheet.Cells(1,2).Value = "Password"
    ExcelSheet.ActiveSheet.Cells(1,3).Value = "Expire Value"
    ExcelSheet.ActiveSheet.Cells(1,4).Value = "Fact Value"
    ExcelSheet.ActiveSheet.Cells(1,5).Value = "Execute Result"
     
    ExcelSheet.ActiveSheet.Cells(2,1).Value = "ad"
    ExcelSheet.ActiveSheet.Cells(2,2).Value = "Mercury"
    ExcelSheet.ActiveSheet.Cells(2,3).Value = "Agent name must be at least 4 characters long."
     
    ExcelSheet.ActiveSheet.Cells(3,1).Value = "Admin"
    ExcelSheet.ActiveSheet.Cells(3,2).Value = "Merc"
    ExcelSheet.ActiveSheet.Cells(3,3).Value = "Incorrect password. Please try again"
     
    ExcelSheet.ActiveSheet.Cells(4,1).Value = "Admin"
    ExcelSheet.ActiveSheet.Cells(4,2).Value = "Mercury"
    ExcelSheet.ActiveSheet.Cells(4,3).Value = "Flight Reservation"
          
    ExcelSheet.SaveAs ddFilePath
    ExcelBook.Quit
    Set ExcelBook = Nothing
     
     
    2.对EXCEL文件进行读写操作
    Option Explicit
     
    Dim fso, filePath, i
    Dim ExcelBook, ExcelSheet, myExcelBook, myExcelSheet
     
    filePath = Environment.Value("TestDir") & "\ddFile.xls"
     
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ExcelBook = CreateObject("Excel.Application")
    Set ExcelSheet = CreateObject("Excel.Sheet")
     
    Set myExcelBook = ExcelBook.WorkBooks.Open(filePath)
    Set myExcelSheet = myExcelBook.WorkSheets("Sheet1")
     
    For i = 2 To 4
           SystemUtil.CloseProcessByName "Flight4a.exe"  
           SystemUtil.Run Environment.Value("ProductDir") & "\samples\flight\app\flight4a.exe"
     
           Dialog("Login").WinEdit("Agent Name:").Set myExcelSheet.Cells(i,1)
           Dialog("Login").WinEdit("Password:").Set myExcelSheet.Cells(i,2)
           Dialog("Login").WinButton("OK").Click
     
           If Dialog("Login").Dialog("Flight Reservations").Exist Then
                   myExcelSheet.Cells(i,4).Value = Dialog("Login").Dialog("Flight Reservations").Static("errInfo").GetROProperty("text")
                  
                  If Dialog("Login").Dialog("Flight Reservations").Static("errInfo").GetROProperty("text") = myExcelSheet.Cells(i,3) Then
                      myExcelSheet.Cells(i,5).Font.Color = vbBlue
                         myExcelSheet.Cells(i,5).Value = "测试成功"
                  Else
                         myExcelSheet.Cells(i,5).Font.Color = vbRed
                         myExcelSheet.Cells(i,5).Value = "测试失败"
                  End If
     
                  Dialog("Login").Dialog("Flight Reservations").WinButton("确定").Click
                  Dialog("Login").WinButton("Cancel").Click
                 
           Elseif Window("Flight Reservation").Exist Then
                  myExcelSheet.Cells(i,4).Value = Window("Flight Reservation").GetROProperty("text")
                  myExcelSheet.Cells(i,5).Font.Color = vbBlue
                  myExcelSheet.Cells(i,5).Value = "测试成功"
                  Window("Flight Reservation").Close
           Else
                  logFile.WriteLine "没有窗口弹出,测试失败!"
                  ExitAction
           End If    
    Next
     
    myExcelBook.Save
     
    ExcelBook.Quit
    Set ExcelBook = Nothing


  • (转)数据驱动在QTP中的运用--自定义TXT文件

    2009-03-20 16:19:55

    以下是对Mercury Interactive公司的Flight飞机订票系统的Login模块进行数据驱动测试的VBScript脚本实例,
            通过对自定义TXT文件进行读写操作。
    Option Explicit
     
    Dim fso
    ‘数据驱动文件路径,数据文件,当前行
    Dim ddFilePath, ddFile, ddCurrLine
    ‘执行日志文件路径,日志文件
    Dim logFilePath, logFile
     
    ddFilePath = Environment.Value("TestDir") & "\ddFile.txt"
    logFilePath = Environment.Value("TestDir") & "\logFile.txt"
     
    '====写入测试用例数据到数据驱动文件中===='
    Set fso = CreateObject("Scripting.FileSystemObject")
    'OpenTextFile第三个参数如果是False表示如果文件一定要存在.
    Set ddFile = fso.OpenTextFile(ddFilePath, 2, True)
     
    ddFile.WriteLine "ad,Mercury,Agent name must be at least 4 characters long."
    ddFile.WriteLine "admin,merc,Incorrect password. Please try again"
    ddFile.WriteLine "admin,Mercury,Flight Reservations"
    ddFile.Close
     
     
    '====写入测试结果到数据日志文件中===='
    Set logFile = fso.OpenTextFile(logFilePath, 2, True)
    logFile.WriteLine "************************************************************"
    logFile.WriteLine "************************************************************"
    logFile.WriteLine "*************************测试日志***************************"
    logFile.WriteLine "******************用例名称:用户登陆**************************"
    logFile.WriteLine "**********************作者:Holly zhao*************************"
    logFile.WriteLine "********************执行时间:" & Date & "*********************"
    logFile.WriteLine "************************测试开始:**************************"
     
    '从ddFile中读取测试数据
    Set ddFile = fso.OpenTextFile(ddFilePath, 1, True)
     
     
    While NOT ddFile.AtEndOfLine
           ddCurrLine = Split(ddFile.ReadLine, ",")
     
           SystemUtil.CloseProcessByName "Flight4a.exe"
           SystemUtil.Run Environment.Value("ProductDir") & "\samples\flight\app\flight4a.exe"
     
           Dialog("Login").WinEdit("Agent Name:").Set ddCurrLine(0)
           Dialog("Login").WinEdit("Password:").Set ddCurrLine (1)
           Dialog("Login").WinButton("OK").Click
     
          If Dialog("Login").Dialog("Flight Reservations").Exist Then
    If Dialog("Login").Dialog("Flight Reservations").Static("errInfo").GetROProperty("text") = ddCurrLine(2) Then
    logFile.WriteLine "测试成功!"
                  Else
                         logFile.WriteLine "测试失败!"
                  End If
                  Dialog("Login").Dialog("Flight Reservations").WinButton("确定").Click
                  Dialog("Login").WinButton("Cancel").Click
           Else
                  If Window("Flight Reservation").Exist Then
                         logFile.WriteLine "测试成功!"   
    End If    
                  Window("Flight Reservation").Close   
           End If    
    Wend
     
    logFile.WriteLine "==========================测试结束==================================="
    logFile.WriteLine "*********************************************************************"
  • (转)QTP关键技术—Test和Top-Level Action间参数传递

    2009-03-20 14:20:15

    以下讲述一个关于QTP的Test参数和Top-Level Action参数的使用例子,

            有些人不知道这个参数做什么用的,尤其是Test的output不知道怎么取。

            其实它是外部对象传给它的(这个外部对象可以是Quality Center,也可以是vbs这样的驱动程序)。

            以下给大家讲解一个关于QuickTest的Flight的例子。

            首先,在QTP里录制一段脚本,代码如下:

            SystemUtil.CloseProcessByName "Flight4a.exe"

            SystemUtil.Run Environment.Value("ProductDir") & "\samples\flight\app\flight4a.exe"

            Dialog("Login").WinEdit("Agent Name:").Set Parameter("InAction1")

            Dialog("Login").WinEdit("Password:").SetSecure "46f1f4259cf01348f5a4c630bcee96084f3d1619"

            Dialog("Login").WinButton("OK").Click

            Window("Flight Reservation").Close

            Parameter("OutAction1") = true

            然后在QTP中进行参数设置,

            1)设置Action的参数

            鼠标选中Keyword View中的Action1,

            点右键---Action Property,

            在Parameters的Tab标签下,分别加入:

            输入参数 InAction1 ,类型String;

            输出参数 OutAction1,类型 Boolean。

            2)设置Test的参数

            在QTP的菜单File--->>Settings的Parameters的Tab标签下,分别加入:

            输入参数 InTest1 ,类型String;

            输出参数 OutTest1,类型 Boolean。

            3)将Test和Action间参数进行关联传递

            鼠标还是选中Keyword View中的Action1,点右键,

            这次点“Action Call Properties”,

            在Parameter Values里进行参数化传递设置,

            把InTest1的值传递给InAction1,

            把OutAction1的值传递给OutTest1。

            以上设置完毕后,点“保存”,保存到C:\下,存为Test1好了。

            最后,在你的硬盘上新建一个vbs文件,文件内容如下:

            Dim qtApp ,pDefColl,pDef ,rtParams,rtParam

            Set qtApp = CreateObject("QuickTest.Application")

            qtApp.Launch

            qtApp.Visible = True

            qtApp.Open "C:\Test1"

            Set pDefColl = qtApp.Test.ParameterDefinitions

            cnt = pDefColl.Count

            Indx = 1

            While Indx <= cnt

                Set pDef = pDefColl.Item(Indx)

                Indx = Indx + 1

            Wend

            Set rtParams = pDefColl.GetParameters()

            Set rtParam = rtParams.Item("InParam1")

            rtParam.Value = "songfun"

            qtApp.Test.Run , True, rtParams

            MsgBox rtParams.Item("OutParam1").Value

            做完这步之后,保存这个vbs文件,双击执行这个vbs文件,你会发现它自动启动了QTP,而且进行了自动测试,最后还取到了运行成功与否的布尔值。

            这就是关于Test、Top-Level Action参数使用的例子,它的参数的整个传递过程是:

            外部vbs文件 传参数给QuickTest的Test的输入参数InTest1,然后InTest1传参数到InAction1去驱动了Action1的测试

            然后通过这个Action1得出了OutAction1的值,然后通过OutAction1传给OutTest1,最后再传回到vbs文件中。

            示例用MsgBox来打出重新传回到vbs文件中的字符串。

  • (转)QTP关键技术(二)——QTP同步点、并行Action间的参数传递

    2009-03-19 19:48:34

    一 对同步点的理解

      1)QTP的脚本语言是VBScript,脚本在执行的时候,执行语句之间的时间间隔是固定的,也就是说脚本在执行完当前的语句之后,等待固定的时间间隔后开始执行下一条语句
     
      2)问题:假设后一条语句的输入是前一条语句的输出,如果前一条语句还没有执行完,这时候将要导致错误的发生!
     
      3)措施:加入同步点、加入Wait语句

      4)同步点Synchronization Point
      QTP脚本在执行过程中如果遇到同步点,则会暂停脚本的执行,直到对象的属性获取到了预先设定的值,才开始执行下一条脚本。
    如果在规定的时间内没有获取到预先设定的值,则会抛出错误信息。
     
    例如:
      Window("Flight Reservation").ActiveX("Threed Panel Control").WaitProperty "text", "Insert Done...", 10000
      执行到上面这条语句时,QTP会暂停执行,直到显示”Insert Done…”,
      如果在规定的时间10,000ms后text的值没有等于”Insert Done…”,则会抛出错误信息
     
    5)如何获取Synchronization Point
           A.在Recording状态下,通过Insert è Synchronization Point实现
           B.非Recording状态下,在Expert View下,通过Insert è Step Generator è Category(Test Objects)è Object(The Object you’re Testing) è Operation(WaitProperty)è PropertyName、PropertyValue、TimeOut分别填写"text", "Insert Done...", 10000

    6)Wait
      总的来说就是死等,比如说wait 10,当运行到这条语句时,等待10秒钟后,才开始再读下面的语句。所以说写脚本的时候一定要估计好时间,否则的话会浪费运行的时间,或者出现等待时间不足的现象。

    二 并列Action间的参数传递 

      思路:将Action1的输出参数,传递给Action2作为输入参数。
     
      1)创建两个Action,关系是并列关系,不是嵌套的.
               

      2)右键Action1,选Action Properties,在Output Parameters中添加参数OutAction1,点OK
     
      3)右键Action2,选Action Properties,在Input Parameters中添加参数InAction2,点OK
      
      4)将Action1的输出OutAction1,传递给Action2的输入InAction2
     
      右键Action2,选Action Call Properties,弹出Action Call Properties窗口;
      选中InAction2的Value,弹出Value Configuration Options窗口;
      在Parameter中共有四项可供选择,选择Test/Action parameter,
      在Output from previous call(s)中的Action选择Action1,Parameter中选择OutAction1;
      表示Action2中的参数InAction2,是由Action1中的参数OutAction1传递而来。

          

      以上就完成了两个并列Action间参数的传递,Action2只能调用Action1的输出参数,而不能调用Action的输入参数。
     
    三 嵌套Action间的参数传递
      参数传递思路:
      将Action1的输入参数InAction1传递给Action2的输入参数InAction2,
      将Action2的输出参数OutAction2传递给Action1的输出参数OutAction1。
      此文为Hollyzhao于2007年09月在http://blog.csdn.net/softesting 发布,夜深了,有点累~
      1)创建两个Action,嵌套关系,在关键字视图,拖动Action2到Action1下面有缩进的地方
        
      2)右键Action1,选Action Properties,
      在Input Parameters中添加参数InAction1,
      在Output Parameters中添加参数OutAction1,点OK
     
      3)右键Action2,选Action Properties,
      在Input Parameters中添加参数InAction2,
      在Output Parameters中添加参数OutAction2,点OK
     
      4)在Action1和Action2间建立关联
      右键Action2,选Action Call Properties,弹出Action Call Properties窗口;
      此文为Hollyzhao于2007年09月在http://blog.csdn.net/softesting 发布,夜深了,有点累~
      选中InAction2的Value,弹出Value Configuration Options窗口;
      在Parameter中共有四项可供选择,选择Test/Action parameter,
      在Parent action parameters的parameter中选择Action1
      同理,OutAction2的Store In值为OutAction1
                 
      以上的操作就是把输入值 通过Action1的输入参数,传递给Action2的输入参数进行使用,
      然后Action2运行后,将输出参数通过Action1的输出参数传递出去。
      这里只是对嵌套Action进行最基本的讲解,在实际使用当中还要灵活运用。
  • (转)QTP关键技术(一)——对象识别及存储技术基本常识

    2009-03-19 19:45:32

    一 对象识别及存储技术基本常识

    1)测试对象模型(Test Object Model)
            测试对象模型是QTP用来描述应用程序中对象的一组对象类。每个测试对象类拥有一系列用于唯一确定对象属性和一组QTP能够录制的方法
     
    2)测试对象(Test Object)
            用于描述应用程序实际对象的对象,QTP存储这些信息用来在运行时识别和检查对象
     
    3)运行时对象(Run-Time Object)
            是应用程序中的实际对象,对象的方法将在运行中被执行
     
    4)QTP的录制过程
            A.确定用于描述当前操作对象的测试对象类,并创建测试对象
            B.读取当前操作对象属性的当前值,并存储一组属性和属性值到测试对象中
            C.为测试对象创建一个独特的有别于其他对象的名称,通常使用一个突出属性的值
            D.记录在对象上执行的操作
     
    5)QTP的回放过程
            A.根据对象的名称到对象存储库(Object Repository)中查找相应的对象
            B.读取对象的描述,即对象的属性和属性值
            C.基于对象的描述,QTP在应用程序中查找相应的对象
            D.执行相关的操作
     
    二 对Check Point的较为深入理解

    1. 定义:
            将特定属性的当前数据与期望数据进行比较的检查点,用于判定被测试程序功能是否正确
            Check Point可以分两类:QTP内置验证点和自定义验证点
     
    2. QTP内置验证点实现原理及优缺点
            A.录制时,根据用户设置的验证内容,记录数据作为基线数据
            B.回放时,QTP捕获对象运行时的数据,与脚本中的基线数据进行比较
            C.如果基线数据和运行数据相同,结果为PASS,反之为Failed.
            D.优点是 操作简单方便
            E.缺点是 QTP默认的检查的属性有时不符合自己的要求,如希望得到检查的属性没有在里面, 而默认的属性不需要检查等。
     
    3. QTP内置验证点结果的应用
            A.录制的验证点在没有进行调整前,仅仅是给出了检查结果是通过还是错误的
            B.实际的测试过程中,可以根据验证点的结果进行不同的操作
           If Window("Flight Reservation").WinEdit("Name:").Check(CheckPoint("Name:")) = True then
                  msgbox "oh, success!"
    Else
                  msgbox "oh, failure!"
    End If
     
    4. 自定义验证点的应用及优缺点
            A.使用条件语句对实际值和期望值进行对比,然后用Reporter对象报告结果
           '检查Ticket Number
    If CStr(dbTicketNumber) = CStr(DataTable("oTicketNumber", dtLocalSheet)) Then
           Reporter.ReportEvent micPass, "打开订单- TicketNumber", "期望结果是:" & dbTicketNumber & ", 界面显示实际结果是:" & DataTable("oTicketNumber", dtLocalSheet)
    Else
           Reporter.ReportEvent micPass, "打开订单- TicketNumber", "期望结果是:" & dbTicketNumber & ", 界面显示实际结果是:" & DataTable("oTicketNumber", dtLocalSheet)
    End If
            B.优点是 非常灵活,前者实现的所有检查都可以用此方法来实现;
            C.缺点是 代码量大,对测试人员的要求高。
     
    5. 对Check Point的深入理解

            A.个人认为在比较简单的和有Active Screen的情况下可以使用QTP内置的Check Point,在比较复杂的情况下可以通过编程和使用Reporter来完成.
            B.在使用check方法时,必须先在Keyword View或者Active Screen中新建CheckPoint。否则无法对该对象进行check,系统报错说无法在对象仓库中找到此对象。如果插入检查点,系统会自动把相关的对象添加到对象库中。
            我认为检查点并不是一个实实在在的对象。因为你可以对同一个对象设置不同的检查点,可以把它的某个属性既设定成True,也可以设定为False。而对象库中的对象的属性值是必须依赖于对象的实际属性值的。如果随意更改有可能无法识别。还有就是可以针对同一个对象设定多个检查点。在测试窗口中可以看到这两个检查点的名称是区分开来的。所以我认为检查点并不是实际存在的对象,而是一些类似映射的东西。
            尽管检查点并不是对象库中的实在的对象,但是它必须对应到对象库中的某个实实在在的对象,好像它的一个映像一样,而且在实际的操作过程中,QTP还是把它作为一个对象来处理的。
            因为我们无法像其他对象一样把“检查点对象”添加到对象库中,而QTP又认为它是个对象,所以我们无法在专家视图中直接添加检查点脚本。但是我们可以采用编成描述的方式来实现检查点的功能。
            CheckPoint 是一个依赖于Object Repository(对象库)中的某个对象的“虚拟对象”。其具体含义是:如果它所依赖的QTP 对象库中的对象没有了,那么此CheckPoint 也就不存在了;这个“虚拟对象”的属性是从它所依赖的对象的属性中“抽取”出来的,它具有它所依赖的对象的一个或几个属性,但不能增加它所依赖的对象没有的任何属性。
            CheckPoint 是一个“虚拟对象”的重要原因是:每个Object都能在Object Repository找到它的Name、Class Properties,而CheckPoint 在Object Repository中就根本不存在。选择脚本中的某个对象后,在Object Property 的对话框里面有个Respository按钮,点击它后,你会看到此对象在Object Respository 的Name、Class 和 Properties。
            选择一个CheckPoint后,在CheckPoint Properties 的对话框里没有 Respository 按钮,在Object Respository中也找不到此CheckPoint的Name、Class 和 Properties(因为它在对象库中根本就不存在!)。

  • (转)QTP脚本触发WEB客户端控件的事件

    2009-03-19 18:06:28

          前两天遇到一个QTP脚本编写的问题。脚本需要填写一个WEB表单然后提交,表单里面有两个WebEdit“商品单价”和“购买数量”,只要在“购买数量”中填写数据,页面会立即自动计算出商品的总价。结果发现,脚本回放的时候,无法计算出总价。
     
            经过分析发现原因是这样的。即时计算总价这个功能,是由客户端的js函数实现的,触发这个函数的事件是“购买数量”这个控件的“onkeyup”事件。在手工操作时候,我们敲击键盘会触发这个事件,但是在QTP脚本里面是这样写的:
    Browser("购买").Page("订单").WebEdit("购买数量").Set "8"
     
            这行代码是直接修改了控件的值,因此并没有触发“onkeyup”这个事件
     
            解决这个问题也很简单,只要再增加一句代码即可:
    Browser("购买").Page("订单").WebEdit("购买数量").FireEvent "onkeyup"
     
            需要注意的是,由于开发人员的编程习惯不同,有的可能是“onkeydown”或者其他事件,所以我们需要先弄清楚,是什么事件触发了js函数。
Open Toolbar