海是我向往的地方,吸纳和咆哮是他的魅力!!!

发布新日志

  • 人的一生必读的60本书

    zibeike 发布于 2009-02-05 09:17:18

     《人的一生必读的60本书》:
    北京工业大学出版社
    在人生无以反复的过程中,只有那些历史上最具天赋的作家才能使我们的灵魂受到一次又一次的震憾,只有那些超越了时空的经典文字,才能把无数的智慧和美好对比着愚昧和丑陋一起呈现给我们,指引着我们远离浮华虚空……

    ·《堂吉诃德》
    ·《一千零一夜》
    ·《倾城之恋》
    ·《昆虫记》
    ·《本草纲目》
    ·《小王子》
    ·《呐喊》
    ·《西游记》
    ·《钢铁是怎样炼成的》
    ·《飘》
    ·《胡雪岩全传》
    ·《国富论》
    ·《老人与海》
    ·《百年孤独》
    ·《悲惨世界》
    ·《红楼梦》
    ·《红与黑》
    ·《汤姆叔叔的小屋》
    ·《毛泽东传》
    ·《曾国藩家书》
    ·《水浒传》
    ·《战争论》
    ·《三国演义》
    ·《孙子兵法》
    ·《史记》
    ·《君王论》
    ·《全球通史》
    ·《物种起源》
    ·《论语》
    ·《圣经》
    ·《我与地坛》
    ·《我的精神家园》
    ·《活着》
    ·《伊索寓言》
    ·《麦田里的守望者》
    ·《美的历程》

    ·《日瓦戈医生》
    ·《冰心散文选》
    ·《穆斯林的葬礼》
    ·《瓦尔登湖》
    ·《苏菲的世界》
    ·《西厢记》
    ·《情人》
    ·《围城》
    ·《生命中不能承受之轻》
    ·《四世同堂》
    ·《罪与罚》
    ·《复活》
    ·《喧哗与骚动》
    ·《边城》
    ·《雪国》
    ·《梦的解析》
    ·《神曲》
    ·《茶花女》
    ·《雷雨》
    ·《简·爱》
    ·《哈姆莱特》
    ·《欧也妮·葛朗台》
    ·《吉檀迦利》
    ·《变形记》

      好多书都没有看过,看来应该列个名单每本都来仔细读读了.

  • 工作小知识

    zibeike 发布于 2007-08-10 14:58:08

     在做功能测试的时候,因为使用的黑盒测试方法,对软件内部的代码不熟悉,所以不能做到代码的全部覆盖.测试的时候注意测试软件在报错之后程序的功能情况,有可能正常的情况,功能是正确的,而在程序提示一些错误信息后,再去测试这些原来的正确的功能,会有可能发现一些问题.如:测试类似QQ登陆,普通登陆错误,然后使用HTTP代理登陆,那就要看这个HTTP代理是否是真正使用的代理.虽然,在登陆的时候,我已经测试过了,是按照对应代理登陆的.但是在软件登陆失败情况下,这种情况是否还是正确的,还需要测试. 这也是我测试中原来没有注意到的地方,结果在这里就出现了BUG.
  • 微软测试人的BLOG

    zibeike 发布于 2007-11-19 13:21:35

      在MSDN上逛的时候发现了Test Center,然后辗转发现了微软测试人员的一些BLOG,都是英文的,呵呵

    http://blogs.msdn.com/imtesty/   这个感觉有许多我想学习的东西,而且里面讲的测试的知识很多都是理论实际相结合。其实一直都想了解微软是如何进行测试的,也很想看些微软测试人员的BLOG,正好找到了,就学习了。而且也非常愿意分享给大家看。

    呵呵,最近工作不太忙,正好补充学习下测试的知识和技术。

  • 发现一个好的英文测试BLOG

    zibeike 发布于 2007-08-04 18:14:08

      哈哈,今天在浏览BLOG的时候发现一个英文测试BLOG,不错,即可以增强自己的英文水平,又可以看到外国的测试情况和他们的经验总结,网址如下: http://www.testingreflections.com/ 

     

  • 拔出网线和禁用网卡有何区别

    zibeike 发布于 2007-08-01 11:10:41

    今天看了rickyzhu的<拔出网线和禁用网卡有何区别>http://www.rickyzhu.com/2007/07/25/plug-cable-and-disable/#more-279 发现自己也有这样的疑问. 我在测试一个软件的通信,需要模拟网络故障,就使用了拔出网线和禁用网卡两种方式,但也不知道两者有什么区别,不过在这篇文章中学到了使用命令行禁用网络的方法. 至于这两者的区别我也不清楚,望有人能解答?以后我也会把自己的一些问题及时记录下来,放到BLOG上,不错的习惯呀,哈哈
  • 有关正则表达式的资料

    zibeike 发布于 2007-07-27 16:06:46

  • 软件开发相关视频

    zibeike 发布于 2008-06-16 12:52:42

    《J2EE 课程视频教程》赛迪网校罗泽彬老师主讲
    http://www.ibeifeng.com/read.php?tid=886&u=2198
    《张孝祥JAVA视频教程》完整版[RMVB]
    http://www.ibeifeng.com/read.php?tid=422&u=2198
    尚学堂148班高清晰版本Hibernate(王勇主讲)---共40集
    http://www.ibeifeng.com/read.php?tid=1338&u=2198
    新东方J2ee系列
    http://www.ibeifeng.com/read.php?tid=531&u=2198
    树人J2EE高级框架实战教学(视频教程)郭克华
    http://www.ibeifeng.com/read.php?tid=620&u=2198
    MLDN J2EE 开发视频(共54讲)
    http://www.ibeifeng.com/read.php?tid=443&u=2198
    北大青鸟 Asp.net 视频(主讲:于海涛)共32 讲
    http://www.ibeifeng.com/read.php?tid=475&u=2198
    达内anyfo--EJB视频第一集发布!!
    http://www.ibeifeng.com/read.php?tid=1329&u=2198
    郭克华J2ME
    http://www.ibeifeng.com/read.php?tid=241&u=2198
    H.S联盟VIP东西[黑客特训班]
    http://www.ibeifeng.com/read.php?tid=216&u=2198
    oracle10g快捷版使用视频
    http://www.ibeifeng.com/read.php?tid=996&u=2198
  • SQLServer连接失败错误的解决(转)

    zibeike 发布于 2007-07-17 09:31:59

    SQLServer连接失败错误的解决
     
        在使用SQLServer的过程中,用户遇到的最多的问题莫过于连接失败了。一般而言,有以下两种连接 SQL Server 的方式:
        一是利用 SQL Server 自带的客户端工具,如企业管理器、查询分析器、事务探查器等。
        二是利用用户自己开发的客户端程序,如ASP 脚本、VB程序等,客户端程序中又是利用 ODBC 或者 OLE DB 等连接 SQL Server。下面,我们将就这两种连接方式,具体谈谈如何来解决连接失败的问题。

        一、客户端工具连接失败
        在使用 SQL Server 自带的客户端工具(以企业管理器为例)连接 SQL Server时,最常见的错误有如下一些:

    1、SQL Server 不存在或访问被拒绝
    ConnectionOpen (Connect())
    2、用户@#sa@#登录失败。原因:未与信任 SQL Server 连接相关联
    3、超时已过期
    下面我们依次介绍如何来解决这三个最常见的连接错误。

    第一个错误"SQL Server 不存在或访问被拒绝"通常是最复杂的,错误发生的原因比较多,需要检查的方面也比较多。一般说来,有以下几种可能性:

    1、SQL Server名称或IP地址拼写有误;

    2、服务器端网络配置有误;

    3、客户端网络配置有误。

    要解决这个问题,我们一般要遵循以下的步骤来一步步找出导致错误的原因。

    首先,检查网络物理连接:

       ping <服务器IP地址>
     
      或者

       ping <服务器名称>
     

    如果 ping <服务器IP地址>失败,说明物理连接有问题,这时候要检查硬件设备,如网卡、HUB、路由器等。还有一种可能是由于客户端和服务器之间安装有防火墙软件造成的,比如 ISA Server。

    防火墙软件可能会屏蔽对 ping、telnet 等的响应,因此在检查连接问题的时候,我们要先把防火墙软件暂时关闭,或者打开所有被封闭的端口。

    如果ping <服务器IP地址> 成功而 ping <服务器名称>失败,则说明名字解析有问题,这时候要检查 DNS 服务是否正常。

    有时候客户端和服务器不在同一个局域网里面,这时候很可能无法直接使用服务器名称来标识该服务器,这时候我们可以使用HOSTS文件来进行名字解析,具体的方法是:

    1、使用记事本打开HOSTS文件(一般情况下位于C:\WINNT\system32\drivers\etc)。

    2、添加一条IP地址与服务器名称的对应记录,如:

        172.168.10.24 myserver
     

    也可以在 SQL Server 的客户端网络实用工具里面进行配置,后面会有详细说明。

    其次,使用 telnet 命令检查SQL Server服务器工作状态:

       telnet <服务器IP地址> 1433
     

    如果命令执行成功,可以看到屏幕一闪之后光标在左上角不停闪动,这说明 SQL Server 服务器工作正常,并且正在监听1433端口的 TCP/IP 连接;如果命令返回"无法打开连接"的错误信息,则说明服务器端没有启动 SQL Server 服务,也可能服务器端没启用 TCP/IP 协议,或者服务器端没有在 SQL Server 默认的端口1433上监听。

    接着,我们要到服务器上检查服务器端的网络配置,检查是否启用了命名管道,是否启用了 TCP/IP 协议等等。我们可以利用 SQL Server 自带的服务器网络使用工具来进行检查。

    点击:程序 -> Microsoft SQL Server -> 服务器网络使用工具。

    从这里我们可以看到服务器启用了哪些协议。一般而言,我们启用命名管道以及 TCP/IP 协议。

    点中 TCP/IP 协议,选择"属性",我们可以来检查 SQK Server 服务默认端口的设置

    一般而言,我们使用 SQL Server 默认的1433端口。如果选中"隐藏服务器",则意味着客户端无法通过枚举服务器来看到这台服务器,起到了保护的作用,但不影响连接。

    检查完了服务器端的网络配置,接下来我们要到客户端检查客户端的网络配置。我们同样可以利用 SQL Server 自带的客户端网络使用工具来进行检查,所不同的是这次是在客户端来运行这个工具。

    点击:程序 -> Microsoft SQL Server -> 客户端网络使用工具

    从这里我们可以看到客户端启用了哪些协议。一般而言,我们同样需要启用命名管道以及 TCP/IP 协议。

    点击 TCP/IP 协议,选择"属性",可以检查客户端默认连接端口的设置,该端口必须与服务器一致。

    单击"别名"选项卡,还可以为服务器配置别名。服务器的别名是用来连接的名称,连接参数中的服务器是真正的服务器名称,两者可以相同或不同。我们可以使用myserver来代替真正的服务器名称sql2kcn-02,并且使用网络库 Named Pipes。别名的设置与使用HOSTS文件有相似之处。

    通过以上几个方面的检查,错误 1 发生的原因基本上可以被排除。下面我们再详细描述如何来解决错误 2。

    当用户尝试在查询分析器里面使用sa来连接SQL Server,或者在企业管理器里面使用sa来新建一个SQL Server注册时,经常会遇到如图 2 所示的错误信息。

    该错误产生的原因是由于SQL Server使用了"仅 Windows"的身份验证方式,因此用户无法使用SQL Server的登录帐户(如 sa )进行连接。解决方法如下所示:

    1、 在服务器端使用企业管理器,并且选择"使用 Windows 身份验证"连接上 SQL Server;

    2、 展开"SQL Server组",鼠标右键点击SQL Server服务器的名称,选择"属性",再选择"安全性"选项卡;

    3、 在"身份验证"下,选择"SQL Server和 Windows ";

    4、 重新启动SQL Server服务。

    在以上解决方法中,如果在第 1 步中使用"使用 Windows 身份验证"连接 SQL Server 失败,那么我们将遇到一个两难的境地:首先,服务器只允许了 Windows 的身份验证;其次,即使使用了 Windows 身份验证仍然无法连接上服务器。

    这种情形被形象地称之为"自己把自己锁在了门外",因为无论用何种方式,用户均无法使用进行连接。实际上,我们可以通过修改一个注册表键值来将身份验证方式改为 SQL Server 和 Windows 混合验证,步骤如下所示:

    1、点击"开始"-"运行",输入regedit,回车进入注册表编辑器;

    2、依次展开注册表项,浏览到以下注册表键:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer]
     

    3、在屏幕右方找到名称"LoginMode",双击编辑双字节值;

    4、将原值从1改为2,点击"确定";

    5、关闭注册表编辑器;

    6、重新启动SQL Server服务。

    此时,用户可以成功地使用sa在企业管理器中新建SQL Server注册,但是仍然无法使用Windows身份验证模式来连接SQL Server。这是因为在 SQL Server 中有两个缺省的登录帐户:BUILTIN\Administrators 以及<机器名>\Administrator 被删除。要恢复这两个帐户,可以使用以下的方法:

    1、打开企业管理器,展开服务器组,然后展开服务器;

    2、展开"安全性",右击"登录",然后单击"新建登录";

    3、在"名称"框中,输入 BUILTIN\Administrators;

    4、在"服务器角色"选项卡中,选择"System Administrators" ;

    5、点击"确定"退出;

    6、使用同样方法添加 <机器名>\Administrator 登录。

    以下注册表键

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\LoginMode
     

    值决定了SQL Server将采取何种身份验证模式。该值为1,表示使用Windows 身份验证模式;该值为2,表示使用混合模式(Windows 身份验证和 SQL Server 身份验证)。

    看完如何解决前两个错误的方法之后,让我们来看一下第三个错误。

    如果遇到第三个错误,一般而言表示客户端已经找到了这台服务器,并且可以进行连接,不过是由于连接的时间大于允许的时间而导致出错。这种情况一般会发生在当用户在Internet上运行企业管理器来注册另外一台同样在Internet上的服务器,并且是慢速连接时,有可能会导致以上的超时错误。有些情况下,由于局域网的网络问题,也会导致这样的错误。

    要解决这样的错误,可以修改客户端的连接超时设置。默认情况下,通过企业管理器注册另外一台SQL Server的超时设置是 4 秒,而查询分析器是 15 秒(这也是为什么在企业管理器里发生错误的可能性比较大的原因)。具体步骤为:

    1、在企业管理器中,选择菜单上的"工具",再选择"选项";

    2、在弹出的"SQL Server企业管理器属性"窗口中,点击"高级"选项卡;

    3、在"连接设置"下的"登录超时(秒)"右边的框中输入一个比较大的数字,如 20。

    查询分析器中也可以在同样位置进行设置。

    二、应用程序连接失败

    以上的三种错误信息都是发生在 SQL Server 自带的客户端工具中,在应用程序中我们也会遇到类似的错误信息,例如:

    Microsoft OLE DB Provider for SQL Server (0x80004005)
    [DBNETLIB][ConnectionOpen (Connect()).]Specified SQL server not found.

    Microsoft OLE DB Provider for SQL Server (0x80004005)
    用户 @#sa@# 登录失败。原因: 未与信任 SQL Server 连接相关联。

    Microsoft OLE DB Provider for ODBC Drivers 错误 @#80004005@#.
    [Microsoft][ODBC SQL Server Driver]超时已过期.
     

    首先,让我们来详细看以下的示意图来了解一下使用 ODBC 和使用 OLE DB 连接 SQL Server 有什么不同之处。

    在实际使用中,应用程序创建和使用各种 ADO 对象,ADO 对象框架调用享用的 OLE DB 提供者。

    为了访问 SQL Server 数据库,OLE DB 提供了两种不同的方法:用于 SQL Server 的 OLE DB 提供者以及用于 ODBC 的 OLE DB 提供者。这两种不同的方法对应于两种不同的连接字符串,标准的连接字符串写法如下所示:

    1、使用用于 SQL Server 的 OLE DB 提供者:

    使用 SQL Server 身份验证:

    oConn.Open "Provider=sqloledb;" & _
    "Data Source=myServerName;" & _
    "Initial Catalog=myDatabaseName;" & _
    "User Id=myUsername;" & _
    "Password=myPassword"
     
    使用 Windows 身份验证(信任连接):

    oConn.Open "Provider=sqloledb;" & _
    "Data Source=myServerName;" & _
    "Initial Catalog=myDatabaseName;" & _
    "Integrated Security=SSPI"
     

        2、使用用于 ODBC 的 OLE DB 提供者(不使用 ODBC 数据源):

    使用 SQL Server 身份验证:

    oConn.Open "Driver={SQL Server};" & _
    "Server=MyServerName;" & _
    "Database=myDatabaseName;" & _
    "Uid=myUsername;" & _
    "Pwd=myPassword"
     

    使用 Windows 身份验证(信任连接):

    oConn.Open "Driver={SQL Server};" & _
    "Server=MyServerName;" & _
    "Database=myDatabaseName;" & _
    "Trusted_Connection=yes"
     

     3、使用用于 ODBC 的 OLE DB 提供者(使用 ODBC 数据源):

    oConn.Open "DSN=mySystemDSN;" & _
    "Uid=myUsername;" & _
    "Pwd=myPassword"
     

    如果遇到连接失败的情况,我们只要按照一中所示的方法,结合程序中的连接字符串进行检查,基本都能得到解决。另外,还有以下几个要注意的地方:

         1、配置 ODBC 数据源时,点击"客户端"配置选项可以让我们指定连接使用的网络库、端口号等属性。

        2、如果遇到连接超时的错误,我们可以在程序中修改 Connection 对象的超时设置,再打开该连接。例如:

    <%Set Conn = Server.CreateObject
    ("ADODB.Connection")DSNtest="DRIVER={SQL
     Server};SERVER=ServerName;UID=USER;
    PWD=password;DATABASE=mydatabase"Conn.
     Properties("Connect Timeout") = 15 @#
    以秒为单位Conn.open DSNtest%>
         3、如果遇到查询超时的错误,我们可以在程序中修改 Recordset 对象的超时设置,再打开结果集。例如:

    Dim cn As New ADODB.ConnectionDim rs As ADODB.Recordset. . .
    cmd1 = txtQuery.TextSet rs = New ADODB.Recordsetrs.Properties
    ("Command Time Out") = 300@#
    //同样以秒为单位,如果设置为 0 表示无限制
    rs.Open cmd1, cnrs.MoveFirst. . .
     
        三、小结
        本文针对大部分用户在使用 SQL Server 过程中常见的连接失败的错误,重点讨论了在使用 SQL Server 客户端工具以及用户开发的应用程序两种情况下,如何诊断并解决连接失败的错误。看过本文以后,相信每一个读者都会对 SQL Server 的连接工作原理、身份验证方式以及应用程序开发等有一个较为全面而深入的连接。

        本文中所有的测试或者示例均在 Windows 2000 Advanced Server + SQL Server 2000 企业版上通过。

  • LoadRunner编程之跳出迭代

    zibeike 发布于 2008-02-13 16:48:57

        LoadRunner中提供了函数exit(-1)来结束迭代。 使用return 0 来结束本次迭代,进入下一次迭代。

    例子如下:

        在运行时设置中,设置迭代次数为5,运行下面的脚本:

        int i;
        char aaa[]="test"; 
    Action()
    {

        i=0;
        if (i==0) {
        exit(-1);
        }
       
     lr_output_message("value:%s",aaa);

     return 0;
    }

    结果为:

    Virtual User scrīpt started
    Starting action vuser_init.
    Ending action vuser_init.
    Running Vuser...
    Starting iteration 1.
    Starting action Action.

        只运行了一次迭代,就结束了。

    下面的代码:

        int i;
        char aaa[]="test"; 
    Action()
    {

        i=0;
        if (i==0) {
        return 0;
        }
       
     lr_output_message("value:%s",aaa);

     return 0;
    }

    结果:

    Virtual User scrīpt started
    Starting action vuser_init.
    Ending action vuser_init.
    Running Vuser...
    Starting iteration 1.
    Starting action Action.
    Ending action Action.
    Ending iteration 1.
    Starting iteration 2.
    Starting action Action.
    Ending action Action.
    Ending iteration 2.
    Starting iteration 3.
    Starting action Action.
    Ending action Action.
    Ending iteration 3.
    Starting iteration 4.
    Starting action Action.
    Ending action Action.
    Ending iteration 4.
    Starting iteration 5.
    Starting action Action.
    Ending action Action.
    Ending iteration 5.
    Ending Vuser...
    Starting action vuser_end.
    Ending action vuser_end.
    Vuser Terminated.

        运行了5次迭代,但是每次迭代运行到lr_output_message("value:%s",aaa)之前都跳出迭代,进行下一次迭代。

       

  • LoadRunner例子:检查点为参数的一个例子

    zibeike 发布于 2008-01-23 13:58:31

         检查点是LoadRunner的一个功能,用来验证业务功能的正确性。如果检查的内容是变化的,脚本该如何写呢?

         问题提出:LoadRunner订票网站例子中,创建一个虚拟用户脚本,在登陆完成之后,设立一个检查点,来检查“welcome, xxx”。其中xxx为登陆的用户名称。

          解决方法:

         1)使用web_find() 做检查点

         Action()
    {

    //连接字符串,把welcome和用户名组合成一个字符串

     char teststring[1024]="Welcome, ";
     strcat( teststring,lr_eval_string("{username}") );
     lr_output_message("%s", teststring);
     lr_save_string( teststring,"findtext" );

     // [WCSPARAM WCSParam_Diff1 43 97279.0909680032fAADHQDpctVzzzzHDAAccpHfQtf]

    //Parameter {WCSParam_Diff1} created by Correlation Studio

    //关联操作
     web_reg_save_param("WCSParam_Diff1",
      "LB=userSession value=",
      "RB=>",
      "Ord=1",
      "RelFrameId=1.2.1",
      "Search=Body",
      "IgnoreRedirections=Yes",
      LAST);


     web_url("WebTours",
      "URL=http://127.0.0.1:1080/WebTours/",
      "TargetFrame=",
      "Resource=0",
      "RecContentType=text/html",
      "Referer=",
      "Snapshot=t1.inf",
      "Mode=HTML",
      LAST);
     lr_think_time(11);
       

     lr_start_transaction("test");


     web_submit_data("login.pl",
      "Action=http://127.0.0.1:1080/WebTours/login.pl",
      "Method=POST",
      "TargetFrame=body",
      "RecContentType=text/html",
      "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",
      "Snapshot=t2.inf",
      "Mode=HTML",
      ITEMDATA,
      "Name=userSession", "Value={WCSParam_Diff1}", ENDITEM,
      "Name=username", "Value={username}", ENDITEM,     //参数化用户名
      "Name=password", "Value=bean", ENDITEM,
      "Name=JSFormSubmit", "Value=off", ENDITEM,
      "Name=login.x", "Value=42", ENDITEM,
      "Name=login.y", "Value=13", ENDITEM,
      LAST);

    //检查点

     web_find("web_find",
      "What={findtext}",
      LAST);
       

     lr_end_transaction("test", LR_AUTO);


     return 0;
    }

         2)使用web_reg_find()做检查点

    Action()
    {

    //字符串操作,生成要检查的字符串变量

    char teststring[1024]="Welcome, <b>";
     strcat( teststring,
      lr_eval_string("{username}") );
     lr_output_message("%s", teststring);
     lr_save_string( teststring,"findtext" );

     //关联

    // [WCSPARAM WCSParam_Diff1 43 97279.0909680032fAADHQDpctVzzzzHDAAccpHfQtf]   Parameter {WCSParam_Diff1} created by Correlation Studio
     web_reg_save_param("WCSParam_Diff1",
      "LB=userSession value=",
      "RB=>",
      "Ord=1",
      "RelFrameId=1.2.1",
      "Search=Body",
      "IgnoreRedirections=Yes",
      LAST);
     web_url("WebTours",
      "URL=http://127.0.0.1:1080/WebTours/",
      "TargetFrame=",
      "Resource=0",
      "RecContentType=text/html",
      "Referer=",
      "Snapshot=t1.inf",
      "Mode=HTML",
      LAST);
     lr_think_time(11);
       

     lr_start_transaction("test");

     //检查点
     web_reg_find("Text={findtext}",
      "Search=Body",
      LAST);

     web_submit_data("login.pl",
      "Action=http://127.0.0.1:1080/WebTours/login.pl",
      "Method=POST",
      "TargetFrame=body",
      "RecContentType=text/html",
      "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",
      "Snapshot=t2.inf",
      "Mode=HTML",
      ITEMDATA,
      "Name=userSession", "Value={WCSParam_Diff1}", ENDITEM,
      "Name=username", "Value={username}", ENDITEM,  //参数化登陆名称
      "Name=password", "Value=bean", ENDITEM,
      "Name=JSFormSubmit", "Value=off", ENDITEM,
      "Name=login.x", "Value=42", ENDITEM,
      "Name=login.y", "Value=13", ENDITEM,
      LAST);
       

     lr_end_transaction("test", LR_AUTO);


     return 0;
    }

     

     

  • LoadRunner中字符串的操作

    zibeike 发布于 2008-02-26 10:08:55

          LoadRunner中常用的字符串操作函数有:

                   strcpy(destination_string, source_string);

                   strcat(string_that_gets_appended, string_that_is_appended);

                   atoi(string_to_convert_to_int); //returns the integer value

                   itoa(integer_to_conver_to_string, destination_string, base); // base is 10

                   strcmp(string1, string2); // returns 0 if both strings are equal

    对各函数的定义:

                 strcpy( ):拷贝一个字符串到另一个字符串中.

                 strcat( ):添加一个字符串到另一个字符串的末尾。

                strcmp( ):比较两个字符串,如果相等返回0。

                atoi():转换一个ASCII字符串为一个整型。

                itoa():根据给定的进制,转换一个整型数据为ASCII字符串

    下面的例子使用了上面这些函数:

                

    Actions()

    {

            char MyString1[20] = "";

            char MyString2[20] = "";

            char MyString3[20] = "Mercury2";

            char Cstring[10] = "12345";

            int Cint;

     

     

            // MyString1 is empty

            //

            lr_output_message(">>>>>>>>>> MyString1 = %s",MyString1);

     

            // copy "Mercury1" into MyString1

            //

            strcpy(MyString1,"Mercury1");

     

            // Now MyString1 contains "Mercury1"

            //

            lr_output_message(">>>>>>>>>> MyString1 = %s",MyString1);

     

     

            // Copy MyString3 into MyString2

            //

            lr_output_message(">>>>>>>>>> MyString2 = %s",MyString2);

            strcpy(MyString2,MyString3);

            lr_output_message(">>>>>>>>>> MyString2 = %s",MyString2);

     

     

            // Catenate MyString2 to MyString1

            //

            strcat(MyString1,MyString2);

            lr_output_message(">>>>>>>>>> MyString1 = %s",MyString1);

     

            // Cstring is converted to integer Cint

            //

            lr_output_message(">>>>>>>>>> Cstring = %s",Cstring);

            Cint = atoi(Cstring);

            lr_output_message(">>>>>>>>>> Cint = %d",Cint);

     

            // Cint is converted to string

            Cint = 100;

            itoa(Cint,Cstring,10);

            lr_output_message(">>>>>>>>>> Cstring = %s",Cstring);

     

            return 0;

    }

     

     

  • LoadRunner编程之文件的操作

    zibeike 发布于 2008-02-26 18:33:57

    本文出自zibeike的51Testing软件测试博客,转载请保留出处及链接:http://www.51testing.com/?34866


    这篇文章主要写下LoadRunner下如何进行文件的操作。

    1,文件的声明

        LoadRunner不支持FILE数据类型,所以在LoadRunner中用int来声明一个文件:

         int MyFile;

    2,文件的打开

         fopen():返回一个FILE数据类型的指针.因为LoadRunner不支持FILE数据类型,所以返回值需要转化成int.

          int MyFile;

          MyFile=(int)fopen("C:\\temp\\loans.txt","w");

          fopen()函数的第一个参数是创建文件的路径.第二个参数指定了创建文件的模式.下面是常用的几种模式

    “w” -  , 当需要往文件中写的时候. 如果文件存在,就覆盖该文件,如果文件不存在,根据第一个参数来创建新文件. 

    “r” – , 需要从文件中读的时候. 这个文件必须已经存在.

    “a” – 附加, 当往文件末尾添加数据时用到.

    “rw” – 读和写.

    第一个参数中注意文件路径为"\\",因为"\"C语言中为转义字符.另外,如果文件和脚本在同一个目录中,文件的完整路径可以省略.

    3, 读文件

            fscanf():用来读文件。函数语法如下:

           int MyFile;

                int LoanNumber;

                MyFile = fopen(“C:\\temp\\loans.txt”,”r”);

                fscanf(MyFile,”%d”, &LoanNumber);

         需要注意的是:MyFile是个文件指针(在LoadRunner中并不是真正的指针),被用来代替实际的文件。所有文件的操作都是使用文件指针而不是文件名称。

         练习1

         先创建一个文件c:\temp\loans.txt,文件包含的内容为:

         11111

         22222

         33333

         44444

         55555

     循环读取并显示该文件中的每行数据,脚本如下:


    Actions()

    {

            int MyFile;

            int LoanNumber,i;

            // Assigning the file path to a string

            char FileName[80] = "C:\\temp\\loans.txt";

     

     

            // Opening the file

            // Note the use of variable to replace the file path

            //

            MyFile = (int)fopen(FileName,"r");

     

     

            // Reading and printing one loan number at a time

            for(i=1;i<=5;i++)

                   {

                   fscanf(MyFile,"%d", &LoanNumber);

                   lr_output_message("Loan Number %d: %d",i,LoanNumber);

                   }

     

            fclose(MyFile);

     

            return 0;

    }

    当文件打开之后,文件指针在文件的最开始。每读一次,指针就移动到下一行,这就是为什么程序能自动读取下面元素的原因。


    a)  如果把循环改为fori=1i<=7;i++),会出现什么样的结果呢?

    会出现三个都是打印55555的结果,原因是文件指针移动到最后就不再移动了,但是有7次循环,那多出来的2次循环打印的数据仍然是最后一行的数据。

    b) 如果不知道该文件下包含数据的行数, 就无法用for循环。需要使用while循环。可以使用feof函数。feofMyFile)在文件指针没有到达返回文件末尾的时候返回0,如果到末尾返回非0值。这样可以修改程序的循环为:

           whilefeofMyFile== 0);

    注意:如果文件末尾有空行,feof也会把它最为文件的一部分。


    本文出自zibeike的51Testing软件测试博客,转载请保留出处及链接:http://www.51testing.com/?34866


    4,写文件

       fprintf():用来往文件写。语法如下:

                int MyFile;

             char Name[] = “John Doe”;

             MyFile = fopen(“C:\\temp\\loan.txt”,”w”);

                   fscanf(MyFile,”%s”,Name);

      第一个参数是文件指针,第二个参数是格式,第三个参数是指定格式对应的变量。

    Actions()

    {

            int MyFile;

            char Name[] = "John Doe";

     

     

            MyFile = fopen("C:\\temp\\names.txt","w");

    // note that "w" is used to write

           

    fprintf(MyFile,"%s", Name);

    // note that we are printing a string here



    本文出自zibeike的51Testing软件测试博客,转载请保留出处及链接:http://www.51testing.com/?34866
  • LoadRunner脚本实例来验证参数化的取值

    zibeike 发布于 2008-02-27 18:29:54

    问题提出:  主要想试验下,在Controller中,多个用户,多次迭代中参数的取值.

    方法:

    脚本: 我把取到的参数值和对应的VuserID记录下来保存到一个文件中,下面是例子的脚本

    long fileopen;

    char *filename = "C:\\temp\\params.log";

     

    vuser_init()

    {

       

            if ((fileopen = fopen(filename,"a+")) == NULL) {

                   lr_error_message ("file isn't open,path=%s",filename);

                   return 0;

            }

            return 0;

    }

    Action()

    {

       

            int id,scid;

            char *vuser_group;

     

            //typedef long time_t;

            //time_t t;

            long t;

            char *a = "{aaa}";

            char *b = "{bbb}";

       

        lr_whoami(&id, &vuser_group, &scid);

     

        fprintf(fileopen,"%d,%s,%s,%s",id,lr_eval_string (a),lr_eval_string (b),ctime(&t));

           

            return 0;

    }

    vuser_end()

    {

            fclose(fileopen);

            return 0;

    }      

     

    参数设置为:

    取唯一值,每次迭代更新。

     

    运行时设置的迭代次数为2。

     

    场景的设置:

    虚拟用户数:5个

    运行模式:没有设置duration,选择的“Run until complete”

    完成后的日志文件params.log的内容如下:

    1,a1,b1,Thu Jan 01 08:00:05 1970
    1,a2,b2,Thu Jan 01 08:00:05 1970
    10,a5,b5,Thu Jan 01 08:00:05 1970
    10,a6,b6,Thu Jan 01 08:00:05 1970
    2,a3,b3,Thu Jan 01 08:00:05 1970
    2,a4,b4,Thu Jan 01 08:00:05 1970
    30,a9,b9,Thu Jan 01 08:00:05 1970
    30,a10,b10,Thu Jan 01 08:00:05 1970
    21,a7,b7,Thu Jan 01 08:00:05 1970
    21,a8,b8,Thu Jan 01 08:00:05 1970

     

    从生成的日志文件中可以看到VuserID分别为1,2,10,21,30

    第一次迭代取参数分别为1,3,5,7,9

    第二次迭代取参数分别为2,4,6,8,10

    那试验的结果就是每个Vuser取参数的时候相同的Vuser在多个迭代中取的是连续的。不同的Vuser第一个的取值是计算了迭代次数后的那个顺序上的值。

     

     

     

     

  • LoadRunner关联函数的脚本实例--如何操作关联参数

    zibeike 发布于 2008-02-28 16:45:40

    这几天一直在学习LoadRunnerVuGen编程,今天想对关联函数web_reg_save_param做详细的试验和研究:

     

    问题提出:如何对关联的数据进行字符串操作。下面使用了LoadRunner自带的订票例子为例,进行了这方面的试验。假设我要关联的数据是由几个字符串组成的。如何使这些字符串组成一个参数,供我后面的函数使用?

     

    解决方法: 使用多个关联函数,对关联参数进行字符串操作,最后把生成的字符串保存成一个参数,供下面调用该参数的函数使用。

     

    脚本如下:

    Action()

    {

        int number1,number2;

            char session11[1000];

            char string[1000];

            int length;

            char *stringtemp;

            //char session22[20];

            web_reg_save_param("session1","LB=name=userSession value=","RB=.","Ord=ALL",LAST);

            web_reg_save_param("session2","LB=.","RB=<table border=0><tr><td>&nbsp;</td>","Ord=ALL",LAST);

           

     

            web_url("WebTours",

                   "URL=http://127.0.0.1:6080/WebTours/",

                   "Resource=0",

                   "RecContentType=text/html",

                   "Referer=",

                   "Snapshot=t1.inf",

                   "Mode=HTML",

                   LAST);

     

            strcpy(string,"");

            strcpy(string,lr_eval_string("{session1_1}"));

     

            //strcpy(session1,"");

     

            sprintf(session11,"{session2_1}");

            strcat(string,".");

            length= strlen(lr_eval_string(session11));

            length=length-2;

     

            number1=atoi(lr_eval_string("{session1_count}"));

            number2=atoi(lr_eval_string("{session2_count}"));

     

            lr_output_message("%d,%d",number1,number2);

     

            //lr_output_message("%d",length);

             stringtemp=lr_eval_string(session11);

            strncat(string,stringtemp,length);

            //srcat(string,session11);

     

            lr_save_string(lr_eval_string(string),"session");

     

            lr_output_message("%s",lr_eval_string("{session1_1}"));

            lr_output_message("%s",lr_eval_string("{session2_1}"));

           

            web_submit_data("login.pl",

                   "Action=http://127.0.0.1:6080/WebTours/login.pl",

                   "Method=POST",

                   "RecContentType=text/html",                   "Referer=http://127.0.0.1:6080/WebTours/nav.pl?in=home",

                   "Snapshot=t2.inf",

                   "Mode=HTML",

                   ITEMDATA,

                   "Name=userSession", "Value={session}", ENDITEM,

                   "Name=username", "Value=jojo", ENDITEM,

                   "Name=password", "Value=bean", ENDITEM,

                   "Name=JSFormSubmit", "Value=on", ENDITEM,

                   "Name=login.x", "Value=50", ENDITEM,

                   "Name=login.y", "Value=10", ENDITEM,

                   LAST);

            lr_output_message("%s",lr_eval_string("{session}"));

     

            return 0;

    }

     有两个关联的参数,session1session2,最后生成session,被web_submit_data函数调用。蓝色部分是需要特别注意的地方。

    脚本编写调试过程中遇到的问题和解释:

    1.  web_reg_save_param()中如果没有指定Ord=ALL的话,默认是取的第一个符合左右边界的值,这样我们使用关联的参数时可以直接使用变量名,如session1

    2.  web_reg_save_param()中如果指定Ord=ALL的话,会生成一个数组,这样想取某个参数的话,需要使用的参数名需要加_和数组中的位置,如例子中取第一个session1_1,如果这时候仍然用session1,是取不到参数的值的.

    3.  顺序问题:对关联参数相关的操作,需要放到包含该关联数据的请求函数之后,如上紫色部分代码用到关联的参数的语句,都需要放到web_url()之后,否则也不会取到关联的数据

    4.注意lr_eval_string()函数和lr_save_string()函数的用法..

    查看(23034) 评论(5) 收藏 分享 管理

  • LoadRunner添加系统资源监控时遇到的几个问题和解决方法

    zibeike 发布于 2008-05-06 10:58:33

      1.windows资源监控  监控xp系统的资源,启动了Remote Procedure Call(RPC) Remote Registry Service,Controller中添加该monitor,出错。访问被监控主机的共享目录,出现的登陆页面总是以guest帐号登陆

       解决方法:推测xp系统网络访问的用户都是guest帐号,应该在本地安全策略中有设置,找到本地安全设置--〉安全选项--〉网络访问:本地用户的共享和安全模式的 安全设置默认为:仅来宾 修改成经典模式,再次访问被监控主机的共享目录,谈出登陆对话框输入管理员帐号和密码之后在Controller中添加monitor成功。

      2.liunx监控  按照网上介绍的方法,安装了rpc.rstatd,但是在启动该服务时,出错.

       Cannot register service: RPC: Unable to receive; errno = Connection refused

      解决方法:portmap服务没有启动,使用如下命令启动该服务:

      /etc/rc.d/init.d/portmap start

      这时,使用rpcinfo -p 可以看到portmapper的信息,再启动rpc.rstatd之后,再用rpcinfo -p 查看,就可以看到portmapper和rstatd 两个服务的信息了.

      

  • LoadRunner如何在大负载下测试

    zibeike 发布于 2008-06-10 14:36:10

       在大负载中使用LoadRunner进行负载测试,需要配置一些环境来满足大负载下各种资源的充足:

    1.为了避免出现“No Buffer Space Available”的错误,需要进行如下配置:

       1)修改注册表:

          * 设置“HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\tcpip\Par
    ameters\TcpTimedWaitDelay”为 30
          * 设置“HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\tcpip\Par
    ameters\MaxUserPort”为 65534
          * 在“HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session
    Manager\Sub Systems\Windows”设置SharedSection 为 4096

        2)通过在每个脚本的开头添加如下函数来设置“SHUTDOWN”模式为"ABRUPT"

         web_set_sockets_option(“SHUTDOWN_MODE”,”ABRUPT”)

     2.关闭所有的杀毒,反间谍扫描软件等。同时也关闭任务扫描和所有不需要的服务。

     3.脚本运行时设置:

       1)设置日志为“只在错误发生时发送信息” 

       2)去掉错误时产生snapshot的选项

       3)在miscellaneous上,去掉 定义每一步为一个事务 的选项

       4)不选择 模拟浏览器缓存,选上“simulate new user on each iteration”和它的子选项

     4.如果下载的页没有资源,在web_url函数中添加“Mode=HTTP”,这样会减少LG上的负载(不用转换成HTML)。默认情况下,web_url的Mode为Mode=HTML

     5.重启LG并且确保他们都能跟Controller连接.

     6.确保LG和控制器上有足够的剩余磁盘空间.

     7.在controller中去掉web page breakdown

     8.限制Vuser在所有LG上同时进行初始化的数目.可以在Controller的Tools > Options > Run-Time Settings中进行修改.每个LG都有这个设置.

     9.限制controller在运行时存储的错误数.通过修改wlrun.ini中的[output]项来实现:

      • FlagLimitOutputMessages=1
      • MaxNumberOfOutputMessages=<errors count> (default is 10,000)

     10.在Controller上修改Monitor的采样率来降低CPU的使用.可以在Controlller的Tools > Options > Monitors 下修改,如下图所示:

    11. 如果有很多错误产生,最好不要经常打开Error/Output窗口,因为这样会因为访问数据库而打开另外的数据库连接.

    12.负载测试中不要使用"Show Vuser"选项.

    13.把输出信息重定向到一个文本文件中来代替输出到mdb文件中.可以在wlrun7.ini中修改[output]下的

    ExportMessageToFile=1来实现.

    14.不要在Controller机器上运行虚拟用户.

    15.在场景中设置监视器:

      * 内存使用上 mmdrv进程的private bytes

      * disk使用

      * CPU使用

      * 网络使用

    16.把脚本中所与打印信息的脚本去掉.如下面的代码每次迭代都会调用一次,对大量并发用户的运行产生负面的影响.

    lr_vuser_status_message("pIteration: %s -
    START Action", lr_eval_string("{pIteration}"));
    lr_output_message("pIteration: %s - START Action", lr_eval_string("{pIteration}"));

    Controller处理所有虚拟用户的信息,这样会大大降低Controller的性能. 如下是类似的代码:

    web_reg_find("Text=Time on Server", "SaveCount=cErr", ..);
    web_url( some url …);
    if (atoi(lr_eval_string("{cErr}"))>0) {
    lr_error_message(some message);
    lr_end_transaction("S05_T01_Request_Content_Page", LR_FAIL);
    }

      通常认为在脚本中插入lr_error_message是不好的,除非是调用的客户化的API失败了才有必要插入该语句.如果是LoadRunner的函数调用失败(如上面的web_url调用),它会自动发送一个错误消息.

      在大量用户运行的情况下,控制Controller和LG之间的通信流量是非常重要的.发送多余的信息(错误,输出等信息)会增大通信流量降低负载能力.所以,通常都需要把代码中不必要的信息去掉.

    17.去掉脚本中所有的sleep()的调用,用lr_think_time()来代替.lr_think_time给LR让出控制,即LR能够在Vuser休眠的时候去做其他有用的事情.

    18.不要去掉lr_think_time:使用该函数能更准确的模拟负载,对LG产生相对小的压力

    19.web_reg_save_param和web_reg_find()函数:

       • 在 web_reg_save_param() 中添加“Notfound=empty” 参数.
       • 在 web_reg_find() 添加 "Savecount=some_parameter_name". 如果你想知道它是否成功可以使用atoi(lr_eval_string("{some_paramater_name }"))来衡量.

    20.其他

      可能会出现的问题:

       * 测试产生了太多的错误:

         错误引擎不能处理多于1.5GB的错误

         如果测试过程中每秒产生多与1000个错误,Controller的行为将不可预测

       * 测试产生了大量的在线数据

     上面的两个问题都可以使用如下的方法解决:

       例如: 场景是一个组有1000个虚拟用户

       可以把这个组分成两个组:

       G1 100 Vusers
       G2 900 Vusers

       这两个组可以跟原始的组产生一样的负载,对于G2在组命令行中添加如下参数:

       -disable_data -disable_messages

        _disable_data : 让这个组不发送任信息,不发送任何online信息,不写任何offline信息.

        _disable_message: 让这个组不给Controller发送任何信息(错误,日志)

    注意:使用上面的命令行选项会使该LG不给congtroller发送online和offline信息.这样这个组上的虚拟用户的分析数据就收集不到了.

    21.如果需要远程访问,Mercury仅支持PC anywhere.

    翻译自<LoadRunner Large Load Test Considerations>

      

       

     

  • LoadRunner脚本编写(5)-- 检查点,关联等函数

    zibeike 发布于 2008-07-07 22:46:35

    本文接着前面脚本编写4 http://www.51testing.com/?34866/action_viewspace_itemid_70224.html来继续翻译wilsonmar的文章。其中在翻译过程中,都以zibeike注的方式添加了自己对相关知识点的一些经验和理解。转载请注明作者zibeike和出处,谢谢。

    1.  错误预防和恢复

    参数默认是用{}括起来的,但也可以指定用<>

    NTLM或用户登录验证

    web_set_user("X\\Y", "Z", "A.com:80");

    在域与X上的用户名为Y的用户,使用密码Z来登录到A.com:80。在windows基本验证的时候这个脚本被默认录制下来,但如果web服务器需要更安全的NTLM或更深层次的验证,需要手动的添加这个函数到脚本中。对于NTML验证,用户名必须在域名之后,并且以\分割。使用\等符号,需要使用\\,前面的\用来做转义用,否则会出现警告提示。

     

    zibeike注:在论坛中也看到了一些朋友讨论windows弹出登录框的操作LR无法录制到,导致回放出错,一般出错信息多为“Error -26547: Authentication required, please use web_set_user, e.g. web_set_user("domain\\user", "password", "host:port");   [MsgId: MERR-26547]”,其实这种情况错误信息已经很明显的给你提示了,需要往脚本中添加web_set_user函数即可。

     

    2.  IP欺骗(略)

    3.  验证检查点

    通常脚本录制完后需要手动添加些脚本来来确保预期的操作确实进行了正确的响应(如在操作之后后验证显示的一段文本或者图片)。这些检查可以使用正则表达式。

    Web虚拟用户脚本中不会录制到检查点,需要手动添加或者使用VuGen的用户接口来添加函数代码。

    最常用的检查点函数是web_reg_find。这个注册函数会查找脚本中下一个操作如web_url后产生的一段文本。它是从返回的缓冲区扫描而不是在接收的页面中查找。这是比web_find更高效的一个函数。

    可以使用下面的代码来验证文本出现的次数:

    • web_reg_find("Text=ABC", "SaveCount=abc_count", LAST);
      web_url("Step", "URL=...", LAST);
      if (strcmp(lr_eval_string("{abc_count}"), "0") == 0)

    lr_output_message("not found");

    else

    lr_output_message("{abc_count} found");

    如果想保存并且显示找到的文本,可以使用web_reg_save_param界定左右边界把找到的信息保存到参数中。如下:

    • char *str1,*str2;
      str1="desired text";
      // Register the left and right beacons sought:
      web_reg_save_param("param","LB/ic=xxx","RB=xxx");
      // Do the monitored deed:
      web_url("some url","URL=www.xxx.com",LAST);
      // Compare:
      str2=lr_eval_string("{param}");
      if(strcmp(str1,str2)==0) {

    lr_output_message("param found");

    }else{

    lr_output_message("Value found is %s",str2);

    }

    zibeike注:1)这里想跟大家说下注册函数,在web/http协议的脚本中,注册函数均以web_reg为前缀,这种注册型的函数都是从缓冲区扫描或者获得数据,因此需要提前声明即需要在能获得该查找信息的函数之前添加这些注册函数。例如,web_url()请求了一个页面,我需要验证该页面中是否有某个特定的文本,那需要在web_url()函数之前加上web_reg_find,类似的还有关联的函数web_reg_save_para是一样的,需要放到能获得想要的数据的请求的函数之前。但如果想查看这些函数最终保存的结果,如想打印关联函数web_reg_save_para中保存的参数内容,打印的操作就需要放到请求的函数之后了。

    2web_findweb_reg_find的区别:前面的是查找页面显示的数据,因此需要放在请求页面的函数之后,而且查找的信息是显示的web页面上的信息。后者是注册型函数,需要放到请求的页面之前,而且查找的内容是服务器返回的缓冲数据中查找,所以查找内容应该看html源代码的内容。

    基于HTML录制方式的代码,可以使用web_image_checkHTML页面中包含的图片进行验证。并且需要注意的是只有在Runtime Settings > Internet Protocol Preferences 选择了"Enable Image and text check" 检查点才有效。

       

        下面会讲到数据类型转换,字符串操作等LoadRunner脚本编写知识,今天就到这里了。


    本文为zibeike原创,转载请注明出处:http://www.51testing.com/?34866

  • LoadRunner脚本编写(6)— 数据类型转换和字符串操作

    zibeike 发布于 2008-07-09 16:05:57

     

    一,数据类型转换

    没有使用过C编程的LoadRunner脚本编写者会发现在数据类型转化方面比较困难。下面介绍这方面的知识。

    1.  相似函数的输出在不同的位置

    象很多C函数一样,使用atoi函数的结果即为返回值

    intResult = atoi( charY );

    而:itoa的返回结果为第二个参数。

    itoa( intX, charY, 10);

       第一个参数是需要转换的数字,第二个参数是转换后存储的字符数组,需要注意的是数组必须定义为固定的长度,如:char chary[20]

    数组的最大长度为3206432K),否则会出现“too many variables”编译错误。

    如果定义为变长的字符串如char *charY,则程序会出错。

       第三个参数不是数组的长度,而是数字的基数,10进制是最常用的,其他还有二进制,八进制,十六进制。

    2.  有一些函数实现了同样的功能

    itoa不是一个标准的ANSI C函数但是是Cstdlib.h中的一个函数。所以它不被包括在unix机器上的LibC中。我们可以使用标准的sprintf函数来代替:

    sprintfcharY,“%d”,intX);

    3.  是用%X来转换一个十六进制数

    int intNum

    sscanf(“ffff”,“%X”,&Num;

    lr_output_message(“%d”,intNum);  // 打印65535 ,ffff的整数值

    4.  从文本中提取数字的规则

    如果第一个字符不是数字或者为空,atoi返回0,即“e24”会返回0

    atoi 转换一个非数字的字符会返回组成这个字符的数字,如“-3.2返回-3.0。“123XXX345”返回123

    5.  LoadRunner脚本中的参数必须转换成C字符串。有两种方式来转化LR的参数为C语言的数字。

      i = atoi( lr_eval_string("{pX}") );

    sprintf( intX, "%d", lr_eval_string("{pX}") );

    6.  参数的算术运算

    LoadRunner没有提供对参数的算术运算的函数。所以LR的参数必须:

    1)  转换成C的整数

    2)  使用C的函数来运算最后返回一个C的字符串

    3)  把返回的字符串保存成参数

    char cBuf[10];

    int i;

    // 1. Evaluate parameter into a C integer:

    i = atoi( lr_eval_string("{pNum_in}") );

    // 2. Do the math and output the result to a C string:

    sprintf( cBuf, "%d", i+1);

    // 3. Save the string as a parameter to be passed on:

    lr_save_string( cBuf, "pNum_out");

    //Print out the parameter value after incrementing it.

    lr_message("**** Parameter from %s to %s",

         lr_eval_string("{pNum_in}"));

         lr_eval_string("{pNum_out}"));

    zibeike注:除了对于数字类型的参数的运算之外,对于文本形式的参数的操作,可以参考我的另一篇文章的内容:http://www.51testing.com/?34866/action_viewspace_itemid_75592.html

    二.字符串操作

    C语言中,字符串是固定长度的,因为他们本身由独立的字符组成的字符数组。数组是只读的。任何修改字符串长度的函数调用都会报错:

    Error: "C interpreter runtime error - memory violation error during replay.

    LoadRunneras_web.h库中的字符串函数可以使用“prototyping”声明的方式读写内存:

    char *strtok(char *, char *); // tokenizer prototype
    char *strstr(char *, char *); // substring prototype
    char *strdup(char *); // String duplication prototype
    float atof(); // alpha to return float datatype
    #include "as_web.h"
    char *strtok(char *, char *); // prototype function call.
     
    ActionX()
    {
       char aBuffer[256]; // input string to be parsed.
        char *cToken; // individual token from strtok.
       char cSeparator[] = " "; // blank separator.
       int i; // incrementer
       char val[3][20]; // output array of strings.
       char modified_val[20]; 
        
       // Create a parameter named pDate:
       lr_save_string("January 2, 2001", "pDate");
     
       // Put parameter into a string buffer:
       strcpy( aBuffer,lr_eval_string("{pDate}"));
     
       // Show the buffer for debugging:
       lr_output_message("%s\n",aBuffer);
     
       // get first word (to the first blank):
        cToken = strtok( aBuffer,cSeparator); 
       i = 1;
     
       if(!token) { // first token was not found:
               lr_output_message("No tokens found in string!");
               return( -1 );
       } else {
               while( cToken != NULL) { // tokens are not NULL:
                       lr_output_message("Token=%s", cToken);
     
                       // Stuff in another array:
                       strcpy( val[i], cToken ); 
     
                       // Get next token:
                       cToken = strtok( NULL, cSeparator); 
                       i++; // increment 
               }
               lr_output_message("Val #1 is: %s", val[1]);
               lr_output_message("Val #2 is: %s", val[2]);
               lr_output_message("Val #2 is: %s", val[3]);
     
               strncpy( modified_val, val[2], 1 );
               modified_val[2] = '\0';
               while (modified_val[2] != NULL) {
                       lr_output_message("===>%s", modified_val);
                       modified_val[2] = strtok(NULL, " ");
               }
       }
       return 0;
    }

    strcat 连接两个字符串

    strchr 返回指向第一个要查找的字符出现的位置的指针

    strcmp 比较两个字符

    strcpy 复制字符串到另一个

    stricmp 执行一个大小写敏感的比较

    其他还有strdupstrncatstrncpystrnicmpstrrchrstrsetstrspnstrstr等字符串操作的函数。

    zibeike注:关于更多字符串操作的脚本编写,可以参考我的另一篇文章:

    http://www.51testing.com/?34866/action_viewspace_itemid_75428.html

    zibeike翻译自:http://www.wilsonmar.com/1lrscrīpt.htm

  • LoadRunner中HTTP协议的录制及两种录制模式的比较

    zibeike 发布于 2008-08-21 20:06:52

    一,脚本编写

    1,  HTML –base scrīpt”和“URL-base scrīpt”的区别

    1)“HTML –base scrīpt”默认模式,为每个用户请求生成单独的函数

    如:

    Action()

    {

    web_url("WebTours",

            "URL=http://127.0.0.1:1080/WebTours/",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=",

            "Snapshot=t4.inf",

            "Mode=HTML",

            LAST);

           web_submit_form("login.pl",

            "Snapshot=t5.inf",

            ITEMDATA,

            "Name=username", "Value=jojo", ENDITEM,

            "Name=password", "Value=bean", ENDITEM,

            "Name=login.x", "Value=53", ENDITEM,

            "Name=login.y", "Value=13", ENDITEM,

            LAST);

    return 0;

    }

    2)“URL-base scrīpt”可以捕获所有作为用户操作的结果发送到服务器的HTTP请求,然后一一记录下来。可以捕获非HTML应用程序,例如小程序和非浏览器应用程序。

    如:

    Action()

    {

     

    web_url("WebTours",

            "URL=http://127.0.0.1:1080/WebTours/",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=",

            "Snapshot=t1.inf",

            "Mode=HTTP",

            LAST);

     

    web_concurrent_start(NULL);

     

    web_url("header.html",

            "URL=http://127.0.0.1:1080/WebTours/header.html",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=http://127.0.0.1:1080/WebTours/",

            "Snapshot=t2.inf",

            "Mode=HTTP",

            LAST);

     

    web_url("welcome.pl",

            "URL=http://127.0.0.1:1080/WebTours/welcome.pl?signOff=true",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=http://127.0.0.1:1080/WebTours/",

            "Snapshot=t5.inf",

            "Mode=HTTP",

            LAST);

     

    web_concurrent_end(NULL);

     

    web_concurrent_start(NULL);

     

    web_url("hp_logo.png",

            "URL=http://127.0.0.1:1080/WebTours/images/hp_logo.png",

            "Resource=1",

            "RecContentType=image/png",

            "Referer=http://127.0.0.1:1080/WebTours/header.html",

            "Snapshot=t3.inf",

            LAST);

     

    web_url("webtours.png",

            "URL=http://127.0.0.1:1080/WebTours/images/webtours.png",

            "Resource=1",

            "RecContentType=image/png",

            "Referer=http://127.0.0.1:1080/WebTours/header.html",

            "Snapshot=t4.inf",

            LAST);

     

    web_concurrent_end(NULL);

     

    web_concurrent_start(NULL);

     

    web_url("home.html",

            "URL=http://127.0.0.1:1080/WebTours/home.html",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=http://127.0.0.1:1080/WebTours/welcome.pl?signOff=true",

            "Snapshot=t6.inf",

            "Mode=HTTP",

            LAST);

     

    web_url("nav.pl",

            "URL=http://127.0.0.1:1080/WebTours/nav.pl?in=home",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=http://127.0.0.1:1080/WebTours/welcome.pl?signOff=true",

            "Snapshot=t7.inf",

            "Mode=HTTP",

            LAST);

     

    web_concurrent_end(NULL);

     

    web_url("mer_login.gif",

            "URL=http://127.0.0.1:1080/WebTours/images/mer_login.gif",

            "Resource=1",

            "RecContentType=image/gif",

            "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",

            "Snapshot=t8.inf",

            LAST);

     

    web_submit_data("login.pl",

            "Action=http://127.0.0.1:1080/WebTours/login.pl",

            "Method=POST",

            "RecContentType=text/html",

            "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",

            "Snapshot=t9.inf",

            "Mode=HTTP",

            ITEMDATA,

            "Name=userSession", "Value=97276.8320777643fAADzHHpAfDAAccpAzcD", ENDITEM,

            "Name=username", "Value=jojo", ENDITEM,

            "Name=password", "Value=bean", ENDITEM,

            "Name=JSFormSubmit", "Value=off", ENDITEM,

            "Name=login.x", "Value=56", ENDITEM,

            "Name=login.y", "Value=11", ENDITEM,

            LAST);

     

    web_concurrent_start(NULL);

     

    web_url("login.pl_2",

            "URL=http://127.0.0.1:1080/WebTours/login.pl?intro=true",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=http://127.0.0.1:1080/WebTours/login.pl",

            "Snapshot=t10.inf",

            "Mode=HTTP",

            LAST);

     

    web_url("nav.pl_2",

            "URL=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",

            "Resource=0",

            "RecContentType=text/html",

            "Referer=http://127.0.0.1:1080/WebTours/login.pl",

            "Snapshot=t11.inf",

            "Mode=HTTP",

            LAST);

     

    web_concurrent_end(NULL);

     

    web_concurrent_start(NULL);

     

    web_url("in_home.gif",

            "URL=http://127.0.0.1:1080/WebTours/images/in_home.gif",

            "Resource=1",

            "RecContentType=image/gif",

            "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",

            "Snapshot=t12.inf",

            LAST);

     

    web_url("flights.gif",

            "URL=http://127.0.0.1:1080/WebTours/images/flights.gif",

            "Resource=1",

            "RecContentType=image/gif",

            "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",

            "Snapshot=t13.inf",

            LAST);

     

    web_url("signoff.gif",

            "URL=http://127.0.0.1:1080/WebTours/images/signoff.gif",

            "Resource=1",

            "RecContentType=image/gif",

            "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",

            "Snapshot=t14.inf",

            LAST);

     

    web_url("itinerary.gif",

            "URL=http://127.0.0.1:1080/WebTours/images/itinerary.gif",

            "Resource=1",

            "RecContentType=image/gif",

            "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",

            "Snapshot=t15.inf",

            LAST);

     

    web_concurrent_end(NULL);

     

    return 0;

    }

    3)如何选择?什么时候选择url的录制方式:

    * 不是基于浏览器的

    * 基于浏览器但是包含javascrīpt,并且发送了请求到服务器

    * 使用了https 安全协议

    4)两种脚本的内容比较:

    * http脚本直观,易于理解和维护

    * url 内容多,可伸缩性强,记录了更详细的用户操作信息。

    2HTML 高级选项:

    1)  默认是选择 描述用户行为的脚本

    2)  仅包含明确的URL脚本,录制结果如下:

    Action()

    {

     

         web_url("WebTours",

                "URL=http://127.0.0.1:1080/WebTours/",

                "TargetFrame=",

                "Resource=0",

                "RecContentType=text/html",

                "Referer=",

                "Snapshot=t1.inf",

                "Mode=HTML",

                LAST);

     

     

         web_url("Update.htm",

                "URL=http://scdown.qq.com/download/Update.htm",

                "TargetFrame=",

                "Resource=0",

                "RecContentType=text/html",

                "Referer=",

                "Snapshot=t2.inf",

                "Mode=HTML",

                LAST);

     

         web_url("Update.htm_2",

                "URL=http://scdown.qq.com/download/Update.htm",

                "TargetFrame=",

                "Resource=0",

                "RecContentType=text/html",

                "Referer=",

                "Snapshot=t3.inf",

                "Mode=HTML",

                LAST);

     

         web_url("Update.htm_3",

                "URL=http://scdown.qq.com/download/Update.htm",

                "TargetFrame=",

                "Resource=0",

                "RecContentType=text/html",

                "Referer=",

                "Snapshot=t4.inf",

                "Mode=HTML",

                LAST);

     

     

         web_submit_data("login.pl",

                "Action=http://127.0.0.1:1080/WebTours/login.pl",

                "Method=POST",

                "TargetFrame=",

                "RecContentType=text/html",

                "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",

                "Snapshot=t5.inf",

                "Mode=HTML",

                ITEMDATA,

                "Name=userSession", "Value=97276.9197245848fAADziVpffiDDDDDDAAccpAiQDf", ENDITEM,

                "Name=username", "Value=jojo", ENDITEM,

                "Name=password", "Value=bean", ENDITEM,

                "Name=JSFormSubmit", "Value=off", ENDITEM,

                "Name=login.x", "Value=52", ENDITEM,

                "Name=login.y", "Value=8", ENDITEM,

                LAST);

     

         return 0;

    }

    3,录制header

       默认设置是不录制, 选择需要录制的Headers,以便服务器能够正确处理编码信息。需要注意的是“accept-language,websphere这类服务器会根据HTTP   请求中的Header来确定编码。

  • LoadRunner函数的介绍

    zibeike 发布于 2008-08-21 20:14:14

    LoadRunner函数

    一:通用函数

    LoadRunner的通用函数以lr为前缀,可以在任何协议中使用。可以如下分类:

    信息相关的函数:

    lr_error_message  lr_output_message

    事务函数:

    lr_start_transaction    lr_end_transaction

    运行时函数:

    lr_think_time         lr_exit

    参数相关的函数:

    lr_save_datetime  lr_advance_param  lr_eval_string  lr_save_string  lr_get_attrib_string

    一些函数的详细解释:

    1lr_error_message

    VuGen的回放日志和Controller的输出窗口发送错误信息,例子:

    lr_error_message("string");

    2lr_abort()

    中止脚本的执行。如果在Action中使用,就会中止Action的执行,而去执行vuser_end.

    3lr_exit

    退出脚本,action或者迭代。

    lr_exit(int continuation_option, int exit_status);

    4lr_save_string

    保存指定的非空字符串到一个参数。

    lr_save_string(const char *param_value, const char *param_name);

    5lr_save_date_time

    保存日期和时间到参数中。

    lr_save_datetime(const char *format, int offset, const char *name);

    lr_save_datetime中使用偏移量

    lr_save_datetime(“Tomorrow is %B %d %Y", DATE_NOW+ONE_DAY, “nextDate");

    DATE_NOW+ONE_DAY:当前日期的偏移量

    如果现在的时间是:2008年二月27

    nextDate 中保存的时间为:Tomorrow is 二月 28 2008

    6lr_advance_param

    lr_advance_param (const char * param);

    其中参数用双引号,但不用括号。

    7lr_eval_string

    lr_eval_string("{parameter_name}");

    返回指定参数的当前字符串值。

    检索参数值,可以使用来下面的函数打印该输出到输出信息中。

    lr_output_message 或者lr_error_message

    8lr_get_attrib_string

    lr_get_attrib_string (const char * argument);

    二.特定协议的函数

    这类函数跟录制的协议类型有关系。

    Web协议:以web为前缀

    lrd是数据库相关的函数,lrswindow socket协议的函数。

    web_reg_save_param(const char *ParamName,LB,RB,ORD,SaveLen,SaveOffset, LAST);

    例子:

    web_reg_save_param("flight_name", "LB=Select your departure ", "RB="", LAST);

    web_reg_find:

    web_reg_find(“Text=Welcome”, SaveCount, LAST);

     

Open Toolbar