性能测试工作室:http://www.cnblogs.com/preftest 个人博客: http://hi.baidu.com/higkoo

发布新日志

  • 典型压力测试方案 分享

    2008-09-30 12:14:16

    性能测试,目的就是为了测试系统是否达到预期指标。
      比如:
        1. 能保证5千用户同时在线。
        2. 2百用户同时登录响应时间不超过8秒。
        3. 1周内能处理完成3千份表单。
        4. 在1年后是否上述指标的对比。
        5. ……
      需求因各人而异,万变不离其中。无非就是很多人去做很多事情,不同系统的处理和业务不尽相同。我们要做的,就是要分析系统运行过程中可能会出现的各种情况。然后,逐个去验证系统是否能应对这些情况。
      抛开业务、逻辑,把整个过程简化:
      图中“动作块”为与服务器交互的一个时间段,应用在具体业务里可以是一个用户的整个登录过程,也可以是某一个动作的响应过程。
      “吞吐量”图中定义为单位时间内完成“动作块”的数量。
      整个曲线描述了一段用户(动作)加压的过程,可以是一个系统的真实场景的一部分,也可以是测试过程的一个场景。
      图中可以看出,随动作块的不断增多,动作块持续的时间不断变长。
    那么,怎么衡量这个系统的性能呢?上图说明了以下三点:
      A. 当动作块为一个动作时,动作块的长度即为响应时间,响应时间为一个衡量标准。
      B. 吞吐量曲线图中没有划出来,吞吐量就是衡量系统处理能力的重要指标。
      C. 并发数也是系统的一个处理能力,是为了保证系统能正常运行不被压垮。

      得出这三个指标后,与系统的需求进行对比。如果各项指标都远超预期值,那么恭喜你,系统性能非常棒。
    手势-棒
      相反,如果这三个指标有(都)不能达到的,那么不多说,赶紧去调优吧。
    难过
      还存在一种情况需要进一步分析的,各指标和预期值高出不多。
    委屈
    譬如:按最大吞吐量计算,系统有能力在规定的时间处理完规定的事情;系统能承受最大并发用户数。
       但是,用户数最多的时候是否吞吐量也是最大呢?如果不是,差别有多远?
       为什么要问这个问题?满足了还不够吗?
    惊恐 当然不行!若大用户量会导致吞吐量下降明显,那么可能会导致系统在指定时间不能完成任务喔。
       这时,存在风险!建议先调优。此时需要对系统的真实运行情况进行评估:
       * 若业务经常会集中处理(波峰波谷交替),那么系统真实运行时是达不到最大处理能力的。高风险!
       * 若业务处理基本平缓(波动不明显),偶尔出现波峰,那么OK。低风险。
       * 若情况比较复杂,应结合高压力下的吞吐量进行计算结合实际情况下给结论或建议。
       * 若情况不清楚,那么风险也是很大的,还是尽量搞清楚吧。否则就不要下结论了,描述一下在指定条件的反应。

       以上是我个人的心得体会,若有不正确的地方,欢迎批评指正。
    微笑
       也欢迎大家勇跃留言,发表自己的看法和意见。 握手
  • [论坛] 求此流程的最少测试路径

    2008-03-28 09:06:19

    附件是一个业务流程图,图片说明:
    1、正常流程是A到B到C,某些情况不需要经过B,直接从A到C。
    2、如果过程中含有B,从C点就只能返回到B点,即只能ACA而没有ABCA流程。
    3、E和F的返回点都是D。
    4、当F点的数据达到某种情况时需要经过G点,否则直接结束。


    右图按照“数圈法”有10个圈,V(G)=10?

    如果按照节点法,从A到G中有个if判断,共8个节点,那么V(G)=9?

    哪个正确?说说你的思路和答案吧!

    按节点法,就要注意虚线部分喔:

    如果有虚线部分和没有虚线部分结果有何区别?

  • [论坛] Windows XP x64之初体验

    2008-03-01 12:07:28

       前不久,一时心血来潮下载了一个64位WinXP操作系统,想感受一下64位。
     传说64位有快一些,能不图个新鲜吗? 谄媚 
      犯困 刚开始用迅雷下载了一个英文版本,安装的时候才发现是“评估版”,而且误操作将我的80G硬盘给格式化了。睡觉 
     本机是40G+80G硬盘,40G为主盘。我想把系统装到80G上,然后选择了80G硬盘上的一个分区,安装的时候选择格式化此分区安装,居然把我80G整个硬盘给格式化了,分区全部没有了,奇怪! 疑惑 
     然后我又进32位操作系统重新分区,下载了一个64位Win2003系统。再安装又把我的80G硬盘给格式化了,而且分区又一次没有了,不过这次系统是成功的安装上去了。但是传说中的驱动问题出现了,我装不上驱动,最重要的是网卡驱动! 难过 
     最后我决定还是安装64位WinXP,下载了一个英文版本,这回可以正式版本。安装的时候都有问题:激活码不能用。我去网上抄了N多激活码,终于还是被我找到可以用的了。 微笑 
     在主板的官方网上下载了64位的主板驱动,安装完成后,成功安装驱动(摄像头驱动装不上)。速度感觉是很快,不过啥软件还没有装。
     启动硬盘里所有32位程序,都出错,乱码!原来是英文系统在作怪,找到64位系统的汉化包,下载之。安装了汉化包后,界面都汉化了,应用程序也可以打开了。可是出现了一个致使问题,全部不能连接网络。查看网络设置都是正确了! 吃惊 
     无意中发现,64位系统里开始菜单里有两个IE(Internet Explorer),一个是Internet Explorer 32位,另一个是Internet Explorer 64位。
     神奇的事情又发生了,用“Internet Explorer 64位”打开网页,可以连接且正常显示;用Internet Explorer 32位不能连接网络;用32位其它浏览器都不能连接网络;QQ/MSN等都不能检测到网络;都提示网关验证失败。 心碎 
     就这样,都快到凌晨了,我需要休息了……
     今早我写下了这一刻。 耍酷 

  • [论坛] ChildObject的使用方法(上传程序)

    2008-02-18 15:41:30

    打开 ChildObject.htm 出现一表单录入页面。
    Page页面上有很多WebEdit
    想直接使用Page的ChildObject方法,获取页面上的所有WebEdit然后操作。

    思路:
    使用childObject方法,查找某页面上的所有WebEdit元素,然后给所有WebEdit赋值。

    对着QTP帮助,使用ChildObject总提示“类型不匹配”。

    ChildObject.rar
    (2008-02-18 14:53:55, Size: 1.74 kB, Downloads: 88)

  • [论坛] 发现QTP对象之WebElement的一个Bug

    2008-01-08 14:52:06

    网页里有多个WebElement对象,删除Index的识别属性,剩下innertext和html tag属性。

    使用 WebElement("按钮1").SetTOPropert "innertext","按钮2"
    结果 WebElement("按钮1").click 还是点到了“按钮1”上面,即使在对象库里修改按钮1的属性,结果也是一样。

    打开对象库来验证这个问题:
    使用“Highlight”来验证,仅修改"innertext"属性是不够的,必须把对象的名称也修改成“按钮2”才有效。

    QTP的Bug?

    之初我还不相信,当前版本8.2,赶紧安装了QTP9.0及QTP9.2,问题重现!

    可以拿这个做试验: 测试程序.rar http://bbs.51testing.com/attachment.php?aid=37774
  • [论坛] 图片与文字分离,如何设计重用性会好一点?

    2008-01-07 10:56:29

    如附图所示,某一Web程序,点击左边的菜单出现对应页面。

    左边的菜单的顺序是手动配置的,是一图片加上文字说明,图片为连接,文字为显示说明。

    普通的文字链接,可在脚本中修改对象库属性来实现脚本重用。

    现在的问题是:工具识别的是图片的次序(index),而我们是想让工具去点击文字上的按钮。

    如果仅用index来识别,那么脚本的重用性就很差了,改变了菜单的顺序,脚本就必须改写!

    怎样让工具去点击我想要的按钮呢?  
    (附件《测试程序》为HTML文件)

    Info.jpg

    测试程序.rar
    (2008-01-07 10:54:47, Size: 156 kB, Downloads: 888)

  • [论坛] 网易的性能问题?

    2007-12-25 09:24:49

    今早习惯性的打开http://news.163.com发现部分网页显示错误:

    CODE:

    Internal Server Error

    The server encountered an internal error or
    misconfiguration and was unable to complete
    your request.

    Please contact the server administrator,
    [no address given] and inform them of the time the error occurred,
    and anything you might have done that may have
    caused the error.

    More information about this error may be available
    in the server error log.
    大家讨论一下: 你认为这是网站的性能问题么?
  • [论坛] QTP调用VB6生成的DLL实例

    2007-11-24 10:08:33

  • [论坛] QTP调用WindowsAPI实例集

    2007-11-24 10:07:33

    QTP调用WindowsAPI实例集 ,解压后用IE打开。
    http://www.51testing.com/batch.download.php?aid=7447

    [ 本帖最后由 higkoo 于 2007-11-12 21:20 编辑 ]

    QTP调用WindowsAPI实例集.rar
    (2007-11-10 12:19:13, Size: 7.34 kB, Downloads: 249)

  • [论坛] QTP调用VS2005生成的DLL

    2007-11-24 10:07:00

    QTP调用VS2005生成的DLL ,解压后用IE打开。
    http://www.51testing.com/batch.download.php?aid=7446

    [ 本帖最后由 higkoo 于 2007-11-12 21:22 编辑 ]

    QTP调用VS2005生成的DLL.rar
    (2007-11-10 12:25:33, Size: 794 kB, Downloads: 30)

  • [论坛] QTP动作参数传递实例

    2007-11-24 10:06:23

    发掉了一个,关于QTP的Action之间参数传递的例子。

    http://bbs.51testing.com/attachment.php?aid=34990


    发此贴的源由:http://bbs.51testing.com/thread-96622-1-1.html

    本是我以前的学习笔记,本来是用文件保存在我的邮箱里,前不久翻出来,就一个个的发到论坛上了。

    却被2#、3#、6# 的朋友如此说教,真是心寒啊   

    [ 本帖最后由 higkoo 于 2007-11-22 16:50 编辑 ]

    QTP动作参数.rar
    (2007-11-11 20:42:43, Size: 220 kB, Downloads: 81)



    info.JPG
  • [论坛] QTP8.2中文帮助(F1)

    2007-11-24 10:05:08

    上传QTP中文帮助文件  共二个文件

    [ 本帖最后由 higkoo 于 2007-8-20 11:25 编辑 ]

    Info.JPG

    help.part2.rar
    (2007-08-20 09:35:32, Size: 484 kB, Downloads: 281)

  • [论坛] QTP脚本维护的方法

    2007-11-24 10:03:30

    项目过程中,我们往往会录制很多操作。
    很多操作是一样的,我们可以设置为可重用脚本。
      操作很相似,但略有不同,我们可以给动作设置参数,或修改副本。
       遇到QTP无法识别或识别错误的,可以尝试低级录制或模拟录制。
        对于已知错误,我们可以做成虚拟对象抒以识别,记录到测试结果中。


    我现在遇到一个很严峻的问题:
    我录制了很多通用脚本,现在程序的标题改了
        JavaWindow("程序原名称") 改为 JavaWindow("程序现名称")

    脚本全部运行失败,因为对象库里根本就没有JavaWindow("程序现名称")。

    而且其它对象都是基于JavaWindow("程序原名称")的,窗体的识别是靠它的title属性。
    于是我用

                    JavaWindow("程序现名称").SetTOProperty "title","程序原名称"

    脚本还是运行失败

    如果要修改对象库里的属性,那可是个大工程啊!sdlkfj4

         有没好的解决方案?sdlkfj7


    1.JPG
  • 一睹Windows Server 2008 RC0

    2007-11-21 13:02:25

    一睹Windows Server 2008 RC0
  • 结婚仪式

    2007-11-01 22:37:21

  • LoadRunner之Block

    2007-10-26 08:58:34

     

    如何在一个脚本中实现不同事务不同次数的循环呢?
    案例:假如你想在一个脚本中,实现登录执行1次,查询执行2次,插入执行3次,怎么办?录3个脚本?每个事务分别在脚本中复制N次?
    当然不用,LR早就想到了你的需求,下面让我们隆重推出Block。
    位置:
    Run-time Settings--General--Run Logic
    操作:
    1.将你所要考察的事务设置在不同的Action内。
    2.在Run Logic中的Run中删掉默认的Action。
    3.在Run中插入Block。
    4.在插入的Block中再插入我们要考察的Action。
    5.设置Block的properties。这里有两种选择,Sequential和Random。如果选择Sequential,在下面的Iteration中直接填入数值,那么Block中的Action都会按输入的次数执行。如果选择Random,下面的properties还可以设置Block内各Action执行的百分比。
    按照我们前面的案例,我们只需要设置3个Block,每个Block中分别插入一个Action,设置执行次数分别为1,2,3就可以了。
  • [论坛] 引用 web_reg_save_param 获得的值 动态生成数据

    2007-10-16 16:43:58

    代码:

    QUOTE:

    int a;
    char b[15],c[15];

    //保存所有一级机构的OrgID
    web_reg_save_param ("NewOrgID",
    "LB/BIN=orgID=",
    "RB/BIN=&module",
    "ORD=All",
    LAST);

    web_url("orgAction.struts",
    //这里可以获取一个XML文件,从中读取许多NewOrgID
    LAST);

    a = atoi(lr_eval_string ("{NewOrgID_count}"));
    itoa(a,c,10);//将a变为字符串存到c里面
    strcat(c,"}");
    strcpy(b,"{NewOrgID_");
    strcat(b,c);//将b和c连接起来
    lr_save_string (b,"A");

    lr_output_message ("a=%d,b=%s,c=%s,A=%s",a,b,c,lr_eval_string ("{A}"));
    lr_output_message ("{NewOrgID_30}=%s",lr_eval_string ("{NewOrgID_30}")
    lr_output_message ("Count: %d ,b: %s",atoi(lr_eval_string ("{NewOrgID_count}")),b);

    //新增子机构
    web_submit_data("orgAction.struts_1",
    //这里添加新的子机构,要用到NewOrgID
    LAST);

    输出:

    QUOTE:

    DepartMange.c(70): a=30,b={NewOrgID_30},c=30},A={NewOrgID_30}
    DepartMange.c(71): {NewOrgID_30}= FAA91FB17BB93F538A091330129F8323
    DepartMange.c(72): Count: 30 ,b: {NewOrgID_30}

    问题:

    QUOTE:

    已经读到了30个数据,取最后一个数据A是数据,且A={NewOrgID_30}。
    但是lr_eval_string ("{NewOrgID_30}"与lr_eval_string ("{A}")结果不一样。
    30在这里是已知的,运行后就是动态的,所以要使用参数A来传递。



    scrīpt.rar
    (2007-10-16 15:02:32, Size: 1.66 kB, Downloads: 888)

    问题解决:

    请在文本框输入文字

    int i,j;
    char *MyID[90],m[40];


    for (i=10;i<100;i++) {

     lr_save_int (i,"m");

     web_submit_data(
      "Value={m}");

    }

    web_reg_save_param("IDS",
         "LB=value=\"",
         "RB=\"",
         "ORD=All",
         LAST);

     web_url("GetTree")

    j=atoi(lr_eval_string ("{IDS_count}"));
    lr_output_message ("j=%d",j);
    if (j>90) { j=90;}
    for (i=1;i<=j;i++) {
     sprintf(m,"{IDS_%d}",i);
     MyID[i-1]=lr_eval_string (m);
     lr_output_message ("i=%d,j=%d,m=%s,MyID[%d]=,%s",i,j,m,i-1,MyID[i-1]);
    }

    for (i=0;i<j;i++) {
     lr_save_string (MyID[i],"SubID");
     lr_output_message ("SubID=%s",lr_eval_string ("{SubID}"));

     web_submit_data(
      "Value={SubID}");
    }

     

     

  • [论坛] 树结构的数据,批量做数据的方法

    2007-09-19 23:03:27

    LoadRunner的关联很头疼,下图所示。

    动态生成数据,动态数据的捕捉一直是个难题。

    以下阐明思路: 


    #define ID0 RootIDString;   //ID0为根节点的ID,已知或可获取。
    char *a[10];  //用于保存一级节点的ID。
    char *b[10][20]; //用于保存二级节点的ID。
    char *c[200];  //临时转化用。
    int m,n,i,j;  //临时变量

    for (m=1;m<11;m++)           //获取第一层树节点的ID并存在a数组里。
    {
     submit("ID0","ID0"); //生成根节点的子节点,即一级节点。
     lr_save_int(m,"Order"); //生成m个节点,ID就取第m个。
     web_reg_save_param("FirstNode",
       "LB=LeftString",
       "RB=RightString",
       "ORD={Order}",
       LAST);
     GetRequest(FromServer); //生成一节结点后,可以获取一级ID的第一个页面。
     a[(m-1)]=lr_eval_string("{FirstNode}"); //将一级节点的ID存在数组a中。
    }

    for (m=1;m<11;m++)  //输出a数组,调试用。
    {
     lr_output_message("FirstNode %d : %s",m,a[(m-1)]);
    }

    for (n=1;n<11;n++)
    {
     lr_save_string(a[n-1],"ID1"); //将数组a保存到参数ID1中。
     for (i=1;i<21;i++)
     {
        submit("ID0","ID1");  //给一级节点加子节点,即添加二级节点。
        lr_save_int(i,"Order"); //生成i个节点,ID就取第i个。
        web_reg_save_param("SecondNode",
         "LB=",
         "RB=",
         "ORD={Order}",
         LAST);

        GetRequest(FromServer);  //获取二级节点的ID。

        b[(n-1)][i-1]=lr_eval_string("{SecondNode}"); //将二级节点的ID存在数组b中。
     }
    }

    m=0;//初始化
    for (i=0;i<10;i++)
    {
     for (j=0;j<20;j++)
     {
        c[m]=b[i][j];  //把二级节点的ID转存的数组c中。
     }
    }

    for (i=0;i<200;i++)   //给每个二级节点添加30个子节点。
    {
     lr_save_string(c[i],"ID2");  //将ID存到参数ID2中。

     for (j=0;j<30;j++)
     {
       submit("ID0","ID2"); //此循环可与上面循环重合。
     }
    }



    Info.Jpg

    Lr.c.doc
    (2007-09-19 23:01:48, Size: 1.49 kB, Downloads: 0)

  • LoadRunner {变量与参数} 的 {转化与输出}

    2007-08-27 17:13:26

    今天琢磨了一下LoadRunner的变量、参数的输出与相互转化的问题,写一例题:

    /********** 参数和变量传递 ***********/
    Variable( )
    {

         char * ip = lr_get_vuser_ip();//获取当前用户的IP地址,保存在IP变量里。
         char * gname = lr_get_host_name ();//获取当前用户的机器名,保存在GNAME变量里。

           if(ip)
    /* 参数转变量 */   //RunTime是已定义的参数,下文也可以直接调用
               lr_vuser_status_message("Ip地址: %s ,参数 : %s",ip,lr_eval_string("{RunTime}"));
           else
               lr_vuser_status_message("未启动IP欺骗……");

    /* 变量转参数 */   
        lr_save_string(gname, "GN" );//把变量IP存在“GN”参数里,下文可以直接用 {GN} 调用。

    /* 参数输出 */
      web_submit_data("StatusReporter",
         "Name=title", "Value={RunTime}", ENDITEM,
         "Name=content", "Value={GN}", ENDITEM,
         LAST);

    /* 变量输出 */
        lr_output_message("当前IP地址: %s ",ip);

        lr_think_time(2); //停顿两秒便于观察。

        return 0;
    }
    /*********************END***************************/

    这段代码,虽然很简单,但已含概了变量与参数的转化与输出。

  • LoadRunner批量录数日记一则

    2007-08-24 12:18:20

    做测试的,想偷点懒可真不容易。
    前不久,使用QTP做了脚本批量录数,由于程序业务复杂,自定义控件较多,使用QTP录数速度很浪费时间。

    想用LR直接向服务器SUBMIT数据包,初次尝试失败,无法定制参数类型,脚本如下:

     web_submit_data("info.struts",
      "Action=http://testserver:9016/first/info.struts",
      "Method=POST",
      "EncType=multipart/form-data",
      "RecContentType=text/html",
      "Referer=http://testserver:9016/first/info.struts?actionType=toCreatePage&start=null&count=null",
      "Snapshot=t53.inf",
      "Mode=HTTP", ITEMDATA,
      "Name=org.apache.struts.taglib.html.TOKEN", "Value=494979810de61a15f21e5bb6e91834ed", ENDITEM,
      "Name=actionType", "Value=createInfo", ENDITEM,
      "Name=type", "Value=0", ENDITEM,
      "Name=state", "Value=1", ENDITEM,
      "Name=subjectName", "Value=表格下载", ENDITEM,
      "Name=hint", "Value=", ENDITEM,
      "Name=title", "Value=表格下载 a1", ENDITEM,
      "Name=issueDate", "Value=2007-07-07 07:07:07", ENDITEM,
      "Name=newsType", "Value=HTML", ENDITEM,
      "Name=nt", "Value=HTML", ENDITEM,
      "Name=url", "Value=", ENDITEM,
      "Name=showStyle", "Value=", ENDITEM,
      "Name=content", "Value=表格下载 a1", ENDITEM,
      "Name=content", "Value=", ENDITEM,
      "Name=fileAttachment", "Value=E:\\Myfile.xls", "File=Yes", ENDITEM,
      LAST);


    录入同一类型,同样的内容
    "Name=org.apache.struts.taglib.html.TOKEN", "Value=494979810de61a15f21e5bb6e91834ed", ENDITEM,
    值都不一样,自动关联居然找不到关联。LR老是找到登录时的关联,每次都显示给我,郁闷!
    而且每次自动关联似乎都停在vuser_init  :(
    手动关联,在录制日志里居然找不到“494979810de61a15f21e5bb6e91834ed”。

    找程序员:“这个值就是为了验证是否重复提交数据”。查看JAVA代码有一段
      if checkToken=false ......
    顿时大悟,在LR的SUMBIT把"Name=org.apache.struts.taglib.html.TOKEN" 行给注释掉,
    添加这一行数据"Name=checkToken","Value=false",ENDITEM,

    执行参数化后的脚本,OK! 


    下一步,简化脚本,把所有无关的图片动画等资源下载动作都删掉,仅保留登录过程和SUBMIT。
    因为我不需要测试性能,仅录数而已,做个循环让Vuser即可以搞定批量录数,使用场景控制当然同样可以做到。

    天空突然一下子都亮了……

501/3123>
Open Toolbar