发布新日志

  • 【Oracle】:使用其他账户B查询另外用户A创建的表,B不能直接访问表

    2017-07-12 16:37:26

    【Oracle】:使用其他账户B查询另外用户A创建的表,B不能直接访问表,访问表时,需:A.表才能访问
     
    解决方法:
    要用A.表名进行查询,因此表属于A不属于B的

    或者你定义同义词才可不加owner(A)进行查询
    后话:由于程序代码中直接访问的表,切换账号B后,就不能访问数据库表。为了代码中的数据库表名访问不会因为账号切换后,就导致代码不能用,可以使用同义词来解决,这样就不需要修改代码,保证代码的灵活性,其同义词的方法,可以查看本日志《Oracle同义词的创建及其作用》
  • 脚本:http接口调用2-post方式 ,form表单

    2017-04-19 10:08:20

    http方式的post请求,表单域以键值对的参数形式链接到接口URL,文件域以Form文件表单项的形式进行提交,实例代码:
    Action()
    {
     web_reg_save_param("response",
            "LB=",
            "RB=",
            "Search=Body",
            LAST);
    lr_start_transaction("face_Image");
        web_submit_data("OCRImage","Action=http://10.2.34.22:8080/rvsp-facen/client/compareImage",
        "Method=POST",
        "ENCTYPE=Multipart/form-data",
         ITEMDATA,
         "name=device","value=001",ENDITEM,        /*流水号*/
          "name=clientImage1","value={imagepath1}","File=Yes",ENDITEM,/*图片1*/
          "name=clientImage2","value={imagepath2}","File=Yes",ENDITEM,/*图片2*/
         LAST);
     lr_end_transaction("face_Image", LR_AUTO);
     lr_convert_string_encoding(lr_eval_string ("{response}"),LR_ENC_UTF8 ,LR_ENC_SYSTEM_LOCALE, "response_ok");
    lr_output_message("RESPONSE = %s",lr_eval_string("{response_ok}"));
     return 0;
    }
  • 脚本:http接口调用

    2017-04-19 10:06:16

    关于:对外提供的HTTP接口,http方式的post请求,json方式提交,实例代码编写:
    Action()
    {
     web_reg_save_param("response",
            "LB=",
            "RB=",
            "Search=Body",
            LAST);
    lr_start_transaction("FeatureComp");
     web_custom_request("web_custom_request",
        //"URL=http://10.2.34.70:6000/face/faceCompare.do",
        "URL=http://10.2.34.22:8080/rvsp-facen/faceRepo/icompareByIdTypeNo",
                    "Body={\"base64Img\":\"{NewParam}\",\"idType\":\"1\",\"idNo\":\"430381198101143025\",\"runningNo\":\"11\"}",
        "Method=POST",
        "Resource=0",
        "RecContentType=application/json",
        "Referer=",
        "Mode=HTML",
        "EncType=application/json",
        LAST);
      lr_end_transaction("FeatureComp", LR_AUTO);
     lr_convert_string_encoding(lr_eval_string ("{response}"),LR_ENC_UTF8 ,LR_ENC_SYSTEM_LOCALE, "response_ok");
      lr_output_message("RESPONSE = %s",lr_eval_string("{response_ok}"));
     return 0;
    }
  • LoadRunner调用Java程序—性能测试

    2015-05-22 11:45:27

  • 性能工具使用:资源监控工具Spotlight-使用说明

    2015-05-22 11:38:10

    几年前使用过此工具,发现用于监控远程服务器,非常方面而且快捷。当前再次用于配合压力测试进行资源监控,突然想起来了,以免生疏,在此记录!

     

      1、被监控服务器为Ubuntu server,先在服务器上创建一个用户,专门用于监控使用!

      因为远程监控服务器,需要获取服务器的资源,所以必须要有权限。使用文档明确说明,不能使用root用户,但是我用其他已存在的用户也不行,所以只能创建一个新用户,方便起见就用spotlight作为用户名,设置如下

      >> useradd spotlight

      >> passwd spotlight

      设置完密码就ok了。不错此处,有相关介绍说,要这个用户必须要有root权限才行,但这里我只是创建一个朋友同用户就能。如果创业具有root用户的权限,命令如下,同时建议密码稍微复杂一些

      >> useradd -g root -G root spotlight

      >> passwd spotlight

      设置完密码即可。

     

      2、需要在服务器有监控工具,如sysstat,ubuntu下直接安装即可

      >> apt-get install sysstat

      完成即可

     

      3、本地机器安装spotlight,创建监控信息如下

      进入Spotlight界面,进入File菜单点击Connect,进入如下界面,

      

      双击Add New connection,进入创建一个新的监控链接如下

      

      填充OK即可。

     

      4、监控信息如下:    

      

      监控信息一目了然。

     

      当然Spotlight还可以监控很多很资源,相关如下

      

      

      Spotlight是一款非常轻量级的远程监控工具,当前我们只是用来简单的监控linux服务器。

     

  • 转:内存泄露分析1

    2015-05-22 11:35:51

    性能测试之内存泄漏

      关于内存泄漏,相信大家都不陌生,压力测试中经常会出现,本人最近在做一个压力测试中就着实体会了一下,上来分享分享。

      内存泄露是指程序中间动态分配了内存,但是在程序结束时没有释放这部分内存,从而造成那一部分内存不可用的情况,重起计算机可以解决,但是也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起的。

    以发生的方式来分类,内存泄漏可以分为4类:
    1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
    2. 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
    3. 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
    4. 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
      本人最近就在对一个Http应用进行压力测试,发现被测试的对象进程在并发100时内存占用达到20%,当压力到达1000的时候,内存就持续上升,达到60%,最后压力结束后,内存仍旧停留在60%的使用率,然后重启了系统发现内存已经恢复了正常,于是在第二轮测试时再次不断加压,同时关注性能计数器中的如下指标

    Memory\ Available Bytes 是指剩余的可用物理内存,单位是兆字节(参考值:>=10%)。表明进程当前可使用的内存字节数。

    Memory\ Pages/sec 是表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁盘以释放工作集空间的页面数。

    Process\Private Bytes 是指当前进程中运行的私有内存,如果此内存不断攀升,表示当前存在的内存泄漏,一般情况如果资源合理利用的话,该指标值波动比较平稳。

    通过有效的监控以上计数器可以方便我们判断内存泄漏问题,同时需要开发人员配合进行内存查找,定位分析哪些程序存在内存泄漏。最后通过开发人员的调试,问题很快定位了,确实有程序没有释放内存,最后再次施压的结果是内存持续在一个值上下波动,一般参考值在20%左右,不过这个根据具体的内存空间来定,当然如果可以更小最好了,表明内存合理利用和分配。当然了,检测内存泄漏的方式很多,LoadRunner施压是可以结合响应时间的曲线图来监控也可。

      从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到。对于开发人员来说,熟悉java、C++等应该都了解,通常我们定义一些变量,或者实例化一些对象,比较常用就是new方法,然后通过delete方法进行销毁,如果定义的东西比较多了,也就是想一天申请的内存空间就多了,如果一旦没有合理的管理和消化,就会忘记最后做一些内存回收的处理,导致一些变量和实例对象没有处理掉,最后在程序运行一段时间之后就发现我们的内存不断在攀升,长时间下来积累了就占用了大量的内存空间,导致其他进程无法获取到内存资源,无法去处理其他应用,最后服务就shut down,等等之类情况都比较多见,不过这些也基本取决于开发人员的经验所致,在程序编写过程中合理的使用和管理内存是非常重要的,因为此类问题一般只有在性能测试中体现出来,功能测试是完全没有表现的迹象。

      其实,内存泄漏问题多半在压力测试中出现也是源于程序编写过程中没有规范化管理所导致,开发人员需要结合内存监测工具来有效监控自己的程序,这样才会避免这些个低级的瓶颈出现,所以说性能测试只是为程序提供优化建议,而不应该成为帮助开发人员调试程序的一种手段。

  • LR工具使用问题集锦

    2015-02-28 16:25:24

    1、LRcontroller中 ,想做一个集合点,我已经在脚本了加入了lr_rendezvous函数 为何controller中的rendezvous还是显示灰色不可使用?
    1)场景的设置选择的方式不对,如果选择的是 面向目标 的场景方法,集合点是不可用的 。新建场景的时候“Manual Scenario”下的check box不能选中,取消选中就好。
    2)另外一种是,没有虚拟用户数,也会是灰色的。
  • LR工具使用问题集锦

    2015-02-28 16:25:24

    1、LRcontroller中 ,想做一个集合点,我已经在脚本了加入了lr_rendezvous函数 为何controller中的rendezvous还是显示灰色不可使用?
    1)场景的设置选择的方式不对,如果选择的是 面向目标 的场景方法,集合点是不可用的 。新建场景的时候“Manual Scenario”下的check box不能选中,取消选中就好。
    2)另外一种是,没有虚拟用户数,也会是灰色的。
  • 日志

    2015-01-23 11:33:07

    LR日志输出  

    2013-01-16 23:21:40|  分类: 测试 |  标签: |举报 |字号 订阅

    转:http://blog.csdn.net/oeardi/article/details/5680557

    http://blog.csdn.net/oeardi/article/details/5715516

    在Windows环境下,日志文件output.txt保存在脚本目录中;在UNIX环境下,保存在标准输出中。

     

    【Vuser】——【Run Time Settings】——【General】——【Log】

     

    1、【Enable logging】启动日志功能;(建议运行场景进行负载测试时关闭此项)

    2、【Send messages only when an error occurs】仅发送出错时的日志,可设置缓存大小(默认1KB);

    3、【Always send message】发送所有日志;

    4、【Standard log】标准日志,脚本运行时发送函数信息;

    【Extended log】扩展日志:

    5、【Parameter substitution】脚本运行时,在【Replay log】显示参数信息、参数值;

    6、【Data returned by server】记录服务器返回的所有数据;

    7、【Advanced trace】多用于脚本调试,记录VU在运行期间发送的所有函数信息。

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

    【Replay log】显示的日志颜色:

    1、红色:错误信息;

    2、橙色:迭代信息;

    3、蓝色:事件信息;

    4、黑色:输出信息;

    5、绿色:字符信息。

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

    输出函数:

    1、lr_log_message()    // 输出信息,并记录到 output.txt 中

    2、lr_output_message()    // 输出信息,不记录到日志文件中

    3、lr_message()    // 输出信息,不记录到日志文件中

    4、lr_error_message()    // 输出信息,不记录到日志文件中

  • 关于EXTRARES的扩展说明—性能测试进阶指南 LoadRunner 11实战(第二版)

    2015-01-07 13:50:40

  • 谈谈LoadRunner中lr_load_dll函数的应用[转]

    2015-01-07 13:42:39

      

    2012-03-07 17:31:17|  分类: LoadRunner |  标签: |举报 |字号 订阅

    在用LoadRunner进行压力测试的过程中,我们常常会遇到这样的情况:被测对象软件的客户端操作界面使用浏览器或可执行程序界面,后台则调用通用或私有的动态链接库(*.dll)同服务器进行通讯和数据传输。这时候如果通过VuGen不能成功录制脚本的话,可以考虑LoadRunner中的一个特殊的函数lr_load_dll。
        下面我们以某收费系统测试为实例介绍一下该函数的应用:
        某收费系统采用“收费点—收费站—数据中心”的三层结构,通过开发方提供的专用动态链接库将生产数据由收费点上传至收费站和数据中心,收费点用户操作界面则是由开发方根据该高速公路管理部门的要求专门定制的应用程序,收费点用户操作界面调用动态链接库中的函数进行数据传输。由于动态链接库在数据传输时进行了处理,使用Winsock协议录制测试脚本则可能使调试工作复杂化。考虑到开发方能够提供明确的动态链接库函数说明,我们设计用lr_load_dll直接调用动态链接库的方式制作脚本。
        函数说明:
    动态链接库文件名称:CPGS_MID.dll
    函数名:Mid_Data_Transession
    实现目标:收费点上传传原始记录结算中心或收费站传原始记录
    调用函数:
    Mid_SetTarget  //设置目标节点
    Mid_UploadData //上载数据
    调用示例:
    Mid_Data_Transession ()
    {
    long reqid;  //变量定义
    char form[32];
    int iRet;
    char aBuf[1024]; //数据字串
    //输入参数赋值
    Mid_SetTarget(&02000,"IN_CENTER"); //设置数据传输目标及目标类型
    strcpy( aBuf, “上传记录对象” );  //设置上传记录对象
    iRet = Mid_UploadData (form,aBuf,reqid); //数据上载至
    if( iRet == -1000)       //判断上传结果
    {
       printf(“交易提交失败”);    //上传失败,反馈出错信息,并记录日志
       return -1;
      }
      return 0;
     }
    测试脚本中调用方式如下:


    谈谈LoadRunner中lr_load_dll函数的应用[转] - the_show_27@yeah - Autumn is fallen!

     


        这样就实现了在LoadRunner中调用动态链接库,之后进行并发场景设置等工作与正常压力测试方式一致。此外还需要注意的是,在调用一个动态链接库函数之前,需要LoadRunner能识别该动态链接库文件,即该文件是在系统缺省或声明路径下,能够被正常引用。
        总结:我们知道LoadRunner提供了功能强大的API集合,可以满足大多数性能测试的需求。但在某些特定情况下,这些API仍然有覆盖不到的地方,这就导致LoadRunner可能不便或者无法捕捉相应的数据信息。对这种情况,通过直接调用动态链接库函数向服务器加压可以简化测试脚本的制作过程,提高测试工作的效率,不失为一种理想的解决方案

  • LR:socket

    2015-01-03 18:58:59

        

    自行控制loadrunner的socket协议性能测试

    分类: 【性能测试】 188人阅读 评论(0) 收藏 举报
    [-]
    1. 一前言
    2. 二任务的提出
    3. 三实现方案讨论
    4. 四技术要点讲解
      1. 如何开始录制一个最简单的收发数据包脚本
      2. 写日志文件
      3. 一行一行读数据包文件
      4. 字符串转换为十六进制数据包
      5. 发送自己定义的数据包
      6. 接收数据包到自定义缓冲区
      7. 从自定义缓冲区读出数据
      8. 如何释放自定义缓冲区
      9. 如何根据数据包返回计算为十进制数
    5. 五小节

     

     

    摘要:通过实例讲解loadrunner中的socket协议性能测试的一种测试方法,如何不依赖loadrunner既定规则,自行控制收发数据包

    关键词:Loadrunnersocket,自行控制,收发数据包

     

    一.前言

     

    用过loadrunnersocket协议进行性能测试的同学都知道,只需要录制短短的几句命令,就可以实现socket的链接、收发数据包和关闭链接,一时大爽,不过紧跟着的就是没完没了的折磨。刚开始参数化数据包发送接收都行,慢慢的发现,很多情况下,收发数据包的长度和内容都是不可确定的,加上十六进制和ASCII,甚至协议和加密等等因素混合在一起,简直就是灾难。于是自行控制数据包收发成了可选项,虽然loadrunner提供了相关的函数,但是真的面对进制转换,面对没完没了的<memory violation : Exception ACCESS_VIOLATION received>,很多人只能另外寻找办法完成任务。

     

    本来想全面剖析loadrunnersocket协议性能测试,发现需要厘清的细节太多了,只能尽力讲清楚下面这个例子中遇到的各个知识点了。

     

     

     

    二.任务的提出

     

    这个性能测试是很常见的一种情况,前置机链接了各类不同的硬件设备客户端,各个硬件设备客户端使用了不同的协议,协议承载了大量的不同业务,不过数据包的基本结构相同,由首部、包体和校验码组成,既有TCP链接也有UDP链接,数据发送方式上都是使用的短链接,也就是链接上服务器,发送完数据就立刻关闭了链接。现在需要loadrunner模拟不同的硬件设备,测试前置机的并发能力。

     

     

    数据包结构:

     006.jpg

     

    系统架构:

    001.jpg

     

     

    三.实现方案讨论

     

    这个场景很常见,不过也比较复杂。

     

    如果采用传统的录制回放,需要先选择几种有代表性的硬件类型和重点业务,录制出脚本,可以想象需要录制的脚本有很多,如果进行参数化,必须要搞清楚各种协议,重新组包,这个工作量太大了。

     

     

    或者开发提供两个动态链接库,一个用来对各种协议实现编解码,另外一个包括了需要模拟的硬件类型的重点业务,第二个动态链接库调用第一个,在loadrunner中加载了动态链接库以后,直接调用相关的业务操作函数就可以了。这个够通用,不过开发谁有空搭理你呀。况且如果说这个,这篇文章就不用写了。

     

     

    那还有第三种方法,现在收发的数据包在前置机上有日志文件保存,可以将各种硬件类型发送的数据包日志文件分类搜集到,然后做两个脚本,一个TCP的,一个UDP的,逻辑都是同样的,打开数据表日志文件,读出数据包发送,将发送和接收到的数据包写入本地日志文件,这样就只需要编写两个脚本,拷贝出多份,每个脚本下放入不同的数据包文件模拟出不同的硬件类型。

     

    看起来这种方式最简单,再分析一下,是否可行。

     

    很多协议中会在链接上服务器后,服务器端提供一个唯一串返回,做为一次通讯的唯一标识,加入到后续的数据包中,这里协议倒是没有这个问题,要不每次发送数据包前,还得根据返回的唯一串来修改要发送的数据包,真是幸运。

     

    这样看来建立链接后,数据包可以不做任何修改就能发送出去。不过有些业务,例如增加业务,前置机接收到任务后,可能会写入表,如果已经存在可能会冲突,所以测试前需要清空数据库,只保留初始化数据。

     

    这样还有一个好处,测试的业务和实际生产的业务是完全一致的,无论种类还是比例。缺点是这里的数据包文件会不会不够大,发一会就发完了,看来还需要有个工具来生成足够多的数据包的文件。不过怎么说也是松散耦合了。

     

    经过确认,也没有出现某硬件的某个业务,混合使用TCPUDP的情况。

     

    看来这个方案没有太大的问题,就这样吧。

     

     

     

     

    四.技术要点讲解

     

    1. 如何开始录制一个最简单的收发数据包脚本

     

    开始录制脚本的时候,使用了一个绿色软件SocketTool.exe,在本机启动了一个TCP服务器端:

    002.jpg

     

     

    使用loadrunner录制windows application,启动一个新的SocketTool.exe,创建一个TCP Client,链接刚才启动的服务器,钩选上显示十六进制值,发送313233,别写空格进去,点击发送数据,然后再在服务器端发送点数据回客户端,最后客户端点击断开,脚本就录制完成了。

    003.jpg

     

    004.jpg

     

    脚本就四句:

    lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=server:60000", LrsLastArg);

    lrs_send("socket0", "buf0", LrsLastArg);

    lrs_receive("socket0", "buf1", LrsLastArg);

    lrs_close_socket("socket0");

     

    数据文件data.ws:

    ;WSRData 2 1

     

    send  buf0 3

             "123"

     

    recv  buf1 3

             "456"

     

    -1

     

    后面的脚本就在此基础上修改了。

     

     

     

    2. 写日志文件

     

    假设脚本并发了五个用户,如果都往一个日志文件里面写入内容,就可能出现各个用户日志交织在一起的情况,如果需要每个用户独立使用自己的日志文件,可以创建一个参数vurid

     

    005.jpg

     

    sprintf(cReqSeqNo,"%s%s20d459b3412a2b",cNow,);

     

     

    定义变量:

    char cLogFile[100]="\0";   //日志文件

    long filedeslog=0;         //日志文件句柄

     

    vuser_init中打开日志文件:

     

    sprintf(cLogFile,"lrsocket%s.log",lr_eval_string("{vurid}"));

    if((filedeslog = fopen(cLogFile, "a+")) == NULL)

    {

             lr_output_message("Open File Failed!");

             return -1;

    }

     

    //写入日志文件内容

    fwrite("\nopen file:", strlen("\nopen file:"), 1, filedeslog);

    fwrite(cFileName, strlen(cFileName), 1, filedeslog);

    fwrite("\n", 1, 1, filedeslog);

     

    vuser_end中关闭日志文件:

    fclose(filedeslog);

     

     

    3. 一行一行读数据包文件

    定义部分:

    char cFileName[100]="\0";  //数据包文件名

    long filedes=0;            //数据包文件句柄

    char cLine[2048]="\0";      //文件中一行

     

    读文件方法:

    sprintf(cFileName,"%s","data.txt");

    if((filedes = fopen(cFileName, "r")) == NULL)

    {

             lr_output_message("Open File Failed!");

             return -1;

    }

    while (!feof(filedes)) {

     

             fscanf(filedes, "%s", cLine);

             lr_output_message("read:%s", cLine);

    }

     

    fclose(filedes);

     

     

     

    4. 字符串转换为十六进制数据包

     

    定义:

    unsigned char cOut[1024]="\0";      //记录转换出来的数据包,发送出去的数据包

     

    在这里虽然表面是字符数组,不过请大家千万别把cOut[]当成字符串来处理,而应该理解为一个存放一系列十六进制数据的数组。这有什么区别吗?当然有。

     

    比如你现在要发出一个数据包16进制是:31 32 00 33 34,该数组中就该存储着(十进制)

    cOut[0]=49

    cOut[1]=50

    cOut[2]= 0

    cOut[3]=51

    cOut[4]=52

    发送数据包的时候就应该发送长度为5,如果处理为了字符串,发送strlen(cOut),可以想象,逢零就停止了,只发出去了前两个字节。接收的时候自然也不可以使用strcpy(cOut,BufVal),因为遇到零就会停止,如果包中有00字节,就会造成数据不完整。

     

     

    //进制转换

    m=0;

    memset(cOut,0,sizeof(cOut));

    for (k=0;k<strlen(cLine);k++) {

             if (k % 2==1) {

                       cTmp[0]=cLine[k-1];

                      cTmp[1]=cLine[k];

                       cTmp[2]=0;

                       sscanf(cTmp,"%x", &lngTrans);

                       cOut[m]=lngTrans;

                       m++;

             }

    }

     

    首先初始化cOut的所有字节为0;

    读取从文件中取出的一行;

    每遇到偶数字符,就读出来两个字符,放入cTmp字符串,使用sscanf(cTmp,"%x", &lngTrans);

    比如cTmp中存着”31”,理解为16进制转换出来,lngTrans=0x31;

    然后再把转换出来的数据放入cOut中,得到要发出的数据包

     

    如果想看看cOut里面存的内容:

    unsigned char *p;

     

    p=cOut;

    for (i=0;i<strlen(cLine)/2;i++) {

             lr_output_message("package ready:%x,%d,%x",p,*p,*p);

             p++;

    }

    loadrunner中不可以直接引用cOut[0]的方式打印值,需要使用指针。连指针的地址都打给你看了,这下够清楚了吧。

     

     

    5. 发送自己定义的数据包

     

    建立链接我就不写了,发送自己定义的数据包:

    lrs_set_send_buffer("socket0", (char *)cOut, strlen(cLine)/2 );

    lrs_send("socket0", "buf0", LrsLastArg);

     

    说明:

    1.         (char *)cOut 是因为函数的参数定义
    int lrs_set_send_buffer ( char *s_desc,char *buffer, int size );

    2.         strlen(cLine)/2不可写为strlen(cOut),一定要牢牢记住这里不是发送的字符串,而是一个二进制数据包;

     

     

     

    6. 接收数据包到自定义缓冲区

    代码:

    char *BufVal;              //记录接收到的数据包

    int intGetLen=0;           //记录接收数据包的长度

     

    lrs_receive_ex("socket0", "buf1", "NumberOfBytesToRecv=4", LrsLastArg);

    lrs_get_last_received_buffer("socket0",&BufVal, &intGetLen);

     

    说明:

    1.         intGetLen必须定义为int,而不可是long,为啥?函数定义决定的:
    int lrs_get_last_received_buffer ( char *s_desc, char **data,int *size );

    2.         "NumberOfBytesToRecv=4"此处loadrunner的帮助中例子写错了,当时我照着粘贴下来,死活报那个恐怖的<memory violation : Exception ACCESS_VIOLATION received>,后来仔细看了看,明白了,例子上NumberOfBytesToRecv前面多了一个空格,删除了就可以了;

    3.         定义接收数据包长度,这个参数只适应于TCP协议,UDP就不行了

     

     

    7. 从自定义缓冲区读出数据

     

    代码:

    char cGetLen[5]="\0";      //记录接收到的前四个字节

     

    memset(cGetLen,0,sizeof(cGetLen));

    for (j=0;j<intGetLen;j++) {

             sprintf(cT1,"%02x",(unsigned char)*BufVal);

             strcat(cGetLen,cT1);

             BufVal++;

    }       

     

     

    说明:

    1.         初始化接收数组cGetLen所有字节为0

    2.         (unsigned char)*BufValBufVal指向的值一个个字节读出,按照无符号数解读为16进制和十进制,如果不设定为无符号数,碰到诸如0xA0,转换成十进制字符串就不是”160”,会变成一个负值”-95”,高位被解读为了符号;

    3.         cGetLen不用定义为无符号的,他只是用来将16进制串转化为字符串写入日志用的,并不是存储的数据包

     

     

    8. 如何释放自定义缓冲区

     

    代码:

    for (j=0;j<intGetLen;j++) {

             BufVal--;

    }

    lrs_free_buffer(BufVal);

     

    用完了缓冲区BufVal后需要释放,否则BufVal不断的取得返回,就会越来越长,定位就变得麻烦,用起来不方便。最初释放的时候也是遭遇<memory violation : Exception ACCESS_VIOLATION received>。查看了例子,想了半天,终于明白了,我之前读取缓冲区操作了指针,而释放需要是初始的头指针,于是写了一段狗血的代码,通过循环,回到初始状态进行释放。-_-|||

     

     

     

     

    9. 如何根据数据包返回计算为十进制数

     

    接收数据的时候是分成两个步骤,首先取得四个字节,计算出后续数据包的长度,然后再指定长度进行接收。所以得到返回的四个字节后,需要计算出长度。这里我是一个字节一个字节转换为十进制的值,例如:

    0x11 0x22 0x33 0x44=0d17 0d34 0d51 0d68=256^3*17+256^2*34+256^1*51+256^0*68

     

    代码:

    定义:

    unsigned char cT2[3]="\0"; //记录接收到的10进制字符串

    long lngGetData=0;         //记录后续数据包长度

    int iByte=0;               //四个字节的单个字节的10进制数

    int iaR[4]={0,0,0,0};      //记录四个字节的十进制值

     

     

    for (j=0;j<intGetLen;j++) {

             sprintf(cT2,"%d",(unsigned char)*BufVal);

             iByte=atoi(cT2);

             iaR[j]=iByte;

             BufVal++;

    }

     

    lngGetData=iaR[0]*16777216+iaR[1]*65536+iaR[2]*256+iaR[3];

     

     

    通过atoiASCII码转换为int值,比如cT2=”160”atoi后就成了数值的160

     

     

     

    五.小节

     

    学多用少是一个大的战略原则,尽可能用最简单最适合的法子解决问题,loadrunnersocket测试本篇中没有提到如何和参数打交道的问题,也没有描述UDPTCP的细节差异,接收报文也只是长度数据两段式的收取,没有讲到不确定长度使用终止串的收取方法,一篇文章终归难以尽言,抛砖引玉,如有错漏,不吝赐教。

     

     

    代码和工具下载:

    http://download.csdn.net/detail/testingba/4305645


    转自:http://blog.csdn.net/testingba/article/details/7571911

  • LR:IP欺骗设置

    2015-01-03 17:10:41

    应用程序服务器和网络设备使用IP地址来识别客户端。应用程序服务器通常会对来自同一计算机的客户端信息进行高速缓存。网络路由器尝试对原信息和目标信息进行高速缓存

    以优化吞吐量。如果多个用户具有相同的IP地址,服务器和路由器都会尝试优化。由于同一Load Generator上的Vuser具有相同的IP地址,因此服务器和路由器优化不能反映真

    实情况。

    LoadRunner的多个IP地址功能使允许在单个Load Generator上的Vuser可以使用多个IP地址来识别。服务器和路由器将这些Vuser识别为不同的Load Generator,因此,测试更加贴近显示。

    可以使用LoadRunner的IP欺骗功能创建多个IP地址。只需将新IP地址添加到计算机一次,就可将这些地址用于所有场景。

    下面简要介绍在LoadRunner 中使用IP 欺骗的方法:

    1)设置虚拟IP地址

    注意:Load Generator 机器必须使用固定的IP,不能使用动态IP。

    第一步:打开:开始->程序->HPLoadrunner->tools->Ip wizard,如图所示:



    “增加新IP”选择第一项,“使用保存的文件增加IP”选择第二项,“释放已经设置的IP”选择第三项。

    点“下一步”,出现如图所示的界面:



    这里输入服务器的IP 地址,IP 向导将检查服务器的路由表是否需要更新,这里也可以不输

    入,直接点“下一步”,出现如图所示的界面:


    在这里可以使用Remove 按钮删除选定的虚拟IP,点Add 按钮添加IP,如图所示:


    这里根据输入的IP 的第一个值和数量,自动添加到虚拟IP 列表中,例如:192.168.139.41 5,则增加的虚拟IP 是:192.168.139.41、192.168.139.42、192.168.139.43、192.168.139.44、192.168.139.45.点OK 按钮后如图所示:


    点“完成”按钮,如图所示:


    使用Save as…可以将本次增加的IP 保存成.ips 文件,下次再使用时就可以直接选择此文件了。 点“OK”按钮后完成虚拟IP 设置。设置的虚拟IP 都生效了,此时使用ping 命令会发现都能ping 通。确认虚拟IP 是否都生效的方是:在运行中输入cmd,在命令窗口录入ipconfig,然后就能看到已经生效的所有IP。

    2)使用虚拟IP

    在Controller 中,选择 Scenario->Enable IPSpoofer,设置允许使用IP 欺骗。如图所示:


    “查看虚拟IP”是否实现也可以在脚本中使用lr_get_vuser_ip 函数来得到当前虚拟用户

    的IP 地址,在脚本中加入如下语句:

    Action()

    {

    char *ip;

    ip = lr_get_vuser_ip();

    if( ip )

    lr_message("The IP address is %s" , ip);

    else

    lr_message("IP spoofing disabled");

    return 0;

    }

    在controller中,使用vuser—>showvuser log功能,可以查看user的IP地址。当user数超过虚拟IP数时,有的userIP相同。

    3)使用虚拟IP做完测试后,需要释放所有虚拟IP

    打开IP Wizard,释放所有虚拟IP。重新启动计算机,这样虚拟IP 地址就释放了,否则将占

    有路由表中的IP 地址,别人使用这些IP 地址时将发生冲突。

  • LR的日志详解

    2015-01-03 17:08:39

  • 转测试职业规划

    2013-02-01 13:42:29

  • testNG学习笔记-依赖项的作用

    2012-11-24 14:09:07

    今天拿Webdriver写的备份软件:新建任务和删除任务,用testNG格式来运行,把addtask和Deltask分别用@test来标识,其loginpage部分用@beforeclass标识,driver.close部分用@Afterclass标识。其.xml文件为自动生成,在calss中自动配置了这个testNG类名。
    刚开始执行时,两个test,总是执行完第一个test:addtask,就不会去执行第2个test:Deltask
    最后找原因,在第2个test中把执行的页面,用导航命令再加载一次,从新定位数据,再执行删除,加入前面的这些操作后
    再执行整个testNG,发现只执行第二个test:Deltask方法,第一个不执行。
    后来在网上找,对标识@test的方法,会认为是并行执行的方法,没有先后先后顺序,可并行执行。
    我在Deltask方法的的注释标签中加入依赖项,写法: @Test(dependsOnMethods = "addTask") 
    再整个testNG类执行,这样可以按顺序来跑,完成测试流程的功能。
    参考:http://blog.csdn.net/dm_vincent/article/details/7664761
  • 2.Webdriver中关于driver.navigate().to()和driver.get()使用的区别

    2012-11-23 10:09:59

    最近用一个实际的web项目在学习Webdriver,关于新建一个备份任务的过程,先是有一个父页上button弹开一个子页,总共有4个子页,必须前一个页上的必填信息录完,才能在这个页面触发下一个子页。
     
    如果在baseUrl1第一个子页录完信息,第一个子页有重命名校验和必填项校验。
     
    进入baseUrl2第2个子页,用driver.navigate().to(baseUrl2),直接跳转到第2个页,不受第一个子页的约束,直接导航到第2个页面的输入。
     
    这样会导致什么问题,第一个子页的信息是没有经过校验就进入下一个子页。这样,除了上面的重命名没有校验外,另外信息是否已经进入后台保存也是没有管的,而是直接在前台操作上直接进入下一个页面的操作,导致后台有可能数据丢失的情况,webdriver只管了前台界面的操作。
     
    怎么避免后台数据丢失呢,那么就不能用:driver.navigate().to(baseUrl2)方法,这种方法太危险,不管实际的页面逻辑。
    改用:driver.get(driver.getCurrentUrl()),这样通过实际的页面逻辑来获取URL结果,原理是当页面校验在前、后台通过后,点击“下一步”触发第二个子页时,会给出第二个子页的URL地址;如果页面校验在前、后台没有通过,那么就触发不了第二个页面,也就获得不了第二个页的URL地址,那么用driver.getCurrentUrl(),就获得不了最新页面的地址,也就无法跳转到第2个页面。如此,用driver.get(driver.getCurrentUrl())这样操作就保证跟页面的逻辑对应起来。也就不会脚本运行完成后,出现备份任务有时生成有时没有生成的情况。
    调整到后面的子页,也是用相同的方法:driver.get(driver.getCurrentUrl());
    但到第4个子页调整到父页时就不能用这个方法,因为driver.getCurrentUrl()这个获取不到父页的URL地址。只能再用一下driver.navigate().to(fatherURl),用这个方法,只要保证最后一个子页信息录入不存在丢失情况,就不影响备份任务单据的生成了。
  • webdriver报不可见元素异常方法总结

    2012-11-23 10:03:20

    最近一直在学Selenium相关东西,学到webdriver这块,出现报不可见元素异常方法异常,后来网上找了好多相关资料都没搞定,也没看明白,最后发现是xpath中写了calss属性有问题。现在把学习到的方法和实际解决的方法总结一下,留个记号。
     

    1.       关于存在不可见属性的元素,对元素操作时,出现报如下异常的情况及处理办法:

     

    Exception in thread "main" org.openqa.selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with Command duration or timeout: 31 milliseconds

     

    首先,得排除是否是定位的xpath路径有问题,如果是用xpath定位,其中用@class属性来定位,也会报这个错误(特别是class中含有复合类的定位)。下面用备份软件删除任务的弹出div区中的确认按钮定位为例:

    WebElement cf_button=driver.findElement(By.xpath("//div[@class='ui-dialog-buttonset']"));

    用上面的class定位,也是有问题的。用下面的路径也是有问题的,都会报上面提到的异常内容。

    Xpath=//div[@class=ui-dialog-buttonpane ui-widget-content ui-helper-clearfix]/div/button

    这个xpath中的class属于复合类。

    如果用下面的定位,就不会报这个异常:

    WebElement  cf_button=driver.findElement(By.xpath("//div[4]/div[3]/div[1]/button"));

    上面的元素定位,可通过元素对象的方法isDisplayed()检测元素是否可显示的,如果得到不可显示,操作该元素时会报上面提到的异常,检测语句如下:

        if(!(cf_button.isDisplayed())){System.out.println("Element is not displayed!"); };

    2种情况:就是元素的样式或父级及以上元素含有不可显示属性,以致在有些浏览器中(FirefoxDriver)不能操作,但在正常的浏览器中它是可见和可用的。那么需要检查元素是否具备如下特性:

    • visibility != hidden
    • display != none (is also checked against every parent element)
    • opacity != 0 (in rc2 this is no longer checked for clicking an element)
    • height and width are both > 0
    • for an input, the attribute type != hidden

    如果有不符上面的特性之一,那么就用js脚本来处理,这个解决方案的原英文附在下面:

    Element is not currently visible

    I am using Selenium 2.0b3 Java API with FirefoxDriver. When I fill a form, checkboxes are added to the page depending the forms inputs. I to simulate a click on those checkboxes using selenium. The element are visible and usable in a regular browser but, selenium asserts that the elements are not visible.

    "Element is not currently visible and so may not be interacted with"

    Can I force selenium to ignore the non-visible state of the elements? How can I force selenium to interact with the non visible element?

      

    Selenium determines an element is visible or not by the following criteria (use a DOM inspector to determine what css applies to your element, make sure you look at computed style):

    • visibility != hidden
    • display != none (is also checked against every parent element)
    • opacity != 0 (in rc2 this is no longer checked for clicking an element)
    • height and width are both > 0
    • for an input, the attribute type != hidden

    Your element is matching one of those criteria. If you do not have the ability to change the styling of the element, here is how you can forcefully do it with javascript. (going to assume WebDriver since you said Selenium2 API):

    ((JavascriptExecutor)driver).executeScript("arguments[0].checked = true;", inputElement);

    But that won't fire a javascript. event, if you depend on the change event for that input you'll have to fire it too (many ways to do that, easiest to use whatever javascript. library is loaded on that page).

    3种情况是:估计意思是就是选取元素的时候,可能存在两个相同的,但一次只会用一个,这两个区别就有一个样式的属性是不可见的,这个时候选取元素时要去掉不可见属性,如下例子:

    WebElement label = driver.findElement(By.xpath("//

    label[text()='User Name:' and not(contains(@style,'display:

    none'))]"));

    这个源版的这种情况下的解决方案附在下面:

    can think of two reasons the element you are attempting to interact

    with is invisible. The first reason is that some fields might be

    invisible until you fill in other fields. For example, many

    registration forms have a submit button which is not visible until the

    user has filled in all the required fields. WebDriver is designed to

    simulate a human interacting with the web page. Are you filling out

    the page exactly the same way a human would? Maybe you filled in all

    the fields but your automation is faster than a human. So it tries to

    click the submit button before the web page can change it to visible.

    You can use things like http://darrellgrainger.blogspot.ca/2012/01/waitforelement.html

    to help slow down the automation.

     

    The second reason the element might be invisible is you have located

    an invisible element rather than the element you thought you wanted.

    For example, I worked on a web page which had a radio button for new

    user versus sign in. If you clicked new user, the form. for registering

    a new user appeared. If you clicked existing user, the form. for

    signing in appeared. Both forms existed in the DOM but only one was

    visible at a time. Both forms had:

     

     

        <label for="foo29_blah_nix17">User Name:</label>

    <input id="foo29_blah_nix17" />

     

     

    (the for/id values would be different). So if I used:

     

     

        String username = "darrell";

        WebElement label = driver.findElement(By.xpath("//

    label[text()='User Name:']"));

        String inputID = label.getAttribute("for");

        WebElement input = driver.findElement(By.id(inputID));

        input.sendKeys(username);

     

     

    it might find the invisible label. In these cases, I need to use an

    xpath which finds the visible label element. If the element is

    invisible because style='display: none' then I'd use:

     

     

        WebElement label = driver.findElement(By.xpath("//

    label[text()='User Name:' and not(contains(@style,'display:

    none'))]"));

     

     

    You'll have to figure out if you have problem #1 or #2. If you have

    problem #2, you will have to figure out the exact solution. My

    solution is just one of many possible examples and might not be

    exactly your problem.

    4种情况:一般是编写脚本流程没有严格按照手工的步骤来进行,导致选取到非流程中的不可显示元素,进行操作,以致报上面提到的异常,这种情况在第3种情况的首段有所描述。

  • 转----------myeclipse的Help菜单下找不到SoftWare Updates菜单的解决

    2012-11-03 23:13:06

    eclipse或者myeclipse的Help菜单下找不到SoftWare Updates菜单的解决

    (2010-12-20 16:33:19)
    标签:

    杂谈

    参考:http://joycepro.javaeye.com/blog/731029(90%)

    摘要:在非经典版的eclipse及其上层IDE环境中,help >> software updates菜单项默认是不显示的。但在添加Android等插件时,会用着不顺手,只好采用手工添加。经百度查找,发现有一个可行的方法,就是通过设置把这个经典菜单项显示出来,非常快捷有效。

    正文

  • ---续零件流

    2011-08-23 22:07:17

    三、这段时间项目的情况是: 目前处于需求和设计进行转换的过程,同时又在反证需求的正确性。

    项目总监在上周在给测试的例会中,对测试明确提出了,我现在需要的是你对你测的模块,重点测试的是那个部分?怎么对你负责的模块去进行测试,即测试策略?另外,测试需求将考虑有从不同的角度,将采用什么的缺陷去分析它?(包括对非功能性需求,采用ODC分析方法。)

    开发:对已完成的用列图、结构图跟客户进行评审,一部分测试在开发的demo,也在相继跟客户进行评审。在与客户交谈中,往往与其他小组同步修改的地方,开发人员往往说,等我做到这个地方再告诉他们这个地方怎么来做。或在交谈中有新的东西沉淀下来的东西,并没有在一定的规范管理结构管理起来。比如我们需要有个专门的文档体系记录这些信息,并按信息的性质分类进行记录。根据这个文档,开发者和需求维护者分别校验和更新自己的作业。

    另外,开发还有一个问题,就是目前对自己设计的东西还没有考虑非功能性的需求在里面,如里面用的最多的性能、并发。另外,其它相关的,比如容错性、运行环境等因素。

    测试:我们这个小组的测试在各个客户评审会议中穿梭,除对本身负责的核心业务部分需要非常熟悉外,还需跟本小组需求交界的其他小组模块的业务也需要熟悉。人家在评审,我还在了解业务,只能这样了;另外,看到相关小组的测试负责人没有在评审团坐桩,或是成为最多疑问的评审者,而往往成为了Demo的制作负责人。这是个不好的情况。

    测试还有一个情况,是合适的测试经理迟迟不到位,目前从中选出的测试经理无意于这个岗位。

    根据上面的情况,我只能从项目的测试及质量安全来分析,存在如下一些的不足:

    1、从角色来说,存在的不足:

    首先说测试经理岗,目前处于模糊状态,到设计阶段了还没有明确的项目经理来组织工作,这是个非常大的问题。按照现在项目状况,测试对整个与自己相关的需求理解还未成体系,甚至有的测试对自己负责的模块的细节都不是很清楚,还在负责demo的事,测试团队没有一个统一规划目标及执行。从这些方面都可以反映出测试经理在项目一开始就应该进入项目,把握项目的整体需求,组建团队,对需求分阶段进行理解和消化,并对在需求评审方面有一定的建树;在开发人员在设计完成后(这里包含DEMO、设计的各种图、数据结构模型、设计文档),评阅理解设计,在评审时,提出自己的评审意见,并有一定建树。测试在这些评审充分做完后,各个测试小组同时可出来一些相关文档:测试需求文档(包含非功能性需求)、自己相应模块的测试策略、所测模块存在的风险分析报告。还可进行测试用列编写准备方面的思考、需要的测试技术、考虑自己模块将使用哪些测试工具来辅助测试。这些工作都是需要做的,并测试经理来进行组织执行的。目前居然还有开发负责人调用测试来帮忙干活做Demo原型!现在消减测试的时间,就相当与消减质量的保障性,将来就会已几倍的时间来弥补。

    2、QA在哪里呢,这么大的一个项目,QA只是过段时间过来坐镇几次就可以了吗,就算身经百战QC出身的QA,你是否拿到了对应相应的文档来进行统一分析,我上面例举的这些文档至少存在没有,有没有提要求需要这些文档。再有,从零散的需求文档有没有进行管理和维护,相关的文档有没有同步更新,这些问题有没有发现呢?测试经理岗位没有运转的情况是否已提出?对开发或测试不合理做法和习惯是否有提出疑问。假如我是项目经理,我会要QA参与到项目中,这样更清楚项目的情况,就算不参与到项目中来,在不同阶段你要提出恰到点的问题来,因为只有对这些项目的问题情况进行监控,才能达到质量的监控。

    今天就到这,睡觉去拉~~~

     

     

231/212>
Open Toolbar