我的空间,欢迎进入………… loney_wxl@hotmail.com

发布新日志

  • 利用LR测试程序基类的性能

    2006-12-08 14:11:48

    在VUSERCLASS中写方法,在METHOD中写参数调用,等于参数化了。

    VuserClass代码如下 :

    using System;
    using System.Collections;
    using System.Diagnostics;
    using System.EnterpriseServices;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Tcp;
    using System.Data;
    using System.Web;
    using System.Reflection;

    using Common;
    using Proxy;
    using DAT;
    using ShangXin;
    using ShangXin.Data;
    using ShangXinInterface;
    namespace LRQueryCustomer
    {
     ///


     /// Summary descrīption for VuserClass.
     ///

     [ClassInterface(ClassInterfaceType.AutoDual)]
     public class VuserClass
     { 
      public static string ifCanCreatePuDongOrderWithBiz = "";
      Proxy.LoginProxy loginProxy;
      Method methodLR = new Method();
      LoadRunner.LrApi lr;

      public VuserClass()
      {
       // LoadRunner Standard API Interface ::             DO NOT REMOVE!!!
       lr = new LoadRunner.LrApi();
      }

      // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      public int Initialize()
      {
      try
       {
       RemotingConfiguration.Configure(@"D:\Escalade liunx\CODE_20051020100023\Code\OAERP\ShangXin.OAERP.App\bin\Debug\App.exe.config");

       lr.start_transaction("init");
       lr.start_transaction("GetLoginByLoginNameAndPassword");
       loginProxy = new LoginProxy();
       LoginData loginData = loginProxy.GetLoginByLoginNameAndPassword("administrator","");
       lr.end_transaction("GetLoginByLoginNameAndPassword",lr.PASS);

       Proxy.EmployeeProxy employeeProxy = new EmployeeProxy();
       CertificationInfo CI = new CertificationInfo();
       Common.CertificationInfo ci= PersonalCertificationInfo.GetCertificationInfo();

       CI.LoginName = SXConvert.ToString(loginData.Rows[0][LoginData.LOGINNAME]);
       CI.Password = SXConvert.ToString(loginData.Rows[0][LoginData.PASSWORD]);
       CI.EmployeeId = SXConvert.ToInt32(loginData.Rows[0][LoginData.EMPLOYEEID]);
       CI.EmployeeName = employeeProxy.GetEmployeeDataByPKID(SXConvert.ToInt32(loginData.Rows[0][LoginData.EMPLOYEEID])).Rows[0][EmployeeData.NAME].ToString();
       CI.RecordCount = SXConvert.ToInt32(loginData.Rows[0][LoginData.RECORDCOUNT]);

       lr.start_transaction("GetAllAuthsByLoginId");
       int loginID = SXConvert.ToInt32(loginData.Rows[0][LoginData.PKID]);
       AuthData ad = loginProxy.GetAllAuthsByLoginId(loginID);
       methodLR.SetAuth(ad,CI);
       lr.end_transaction("GetAllAuthsByLoginId",lr.PASS);

       lr.start_transaction("GetGroupsByLoginID");
       GroupData groupData = loginProxy.GetGroupsByLoginID(loginID);
       methodLR.GetGroupAuth(groupData,CI);
       lr.end_transaction("GetGroupsByLoginID",lr.PASS);

       lr.start_transaction("AddToCurrentEmployee");
       if (AuthenticationManager.CheckAuthentication(CI,EnumAuthority.AuthLoginSystem))
       {
        methodLR.AddToCurrentEmployee(ci,CI);
        lr.end_transaction("AddToCurrentEmployee",lr.PASS);
        DataRow BizDR = new SystemParameterValueProxy().GetSystemParameterValueByParentCode(SystemParametersCode.CANCREATEPUDONGORDERWITHBIZ,Bools.TRUE).Rows[0];
        ifCanCreatePuDongOrderWithBiz = BizDR[SystemParameterValueData.OTHER1].ToString();
       }
       else
       {
        lr.end_transaction("AddToCurrentEmployee",lr.FAIL);
       }
      
       lr.end_transaction("init",lr.PASS);
      }
      catch(Exception ex)
      {
       string error = ex.Message;
      }
       return lr.PASS;

      }

      // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      public int Actions()
      {
       
       #region 查询客户
       //条件为空查询
       try
       {
        lr.start_transaction("GetCustomerCountByCondition");
        object[] param = {methodLR.GetQueryCustomerConditions()};

        Object ōbj = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method = obj.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt = (DataTable)method.Invoke(obj,param);
        int count = Convert.ToInt32(dt.Rows[0][0]);

        if(count>0)
         lr.end_transaction("GetCustomerCountByCondition",lr.PASS);
        else
         lr.end_transaction("GetCustomerCountByCondition",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //按客户编号查询
       try
       {
        lr.start_transaction("GetCustomerCountByCode");
        object[] param1 = {methodLR.GetQueryCustomerByCodeConditions()};

        Object obj1 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method1 = obj1.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt1 = (DataTable)method1.Invoke(obj1,param1);
        int count1 = Convert.ToInt32(dt1.Rows[0][0]);

        if(count1>0)
         lr.end_transaction("GetCustomerCountByCode",lr.PASS);
        else
         lr.end_transaction("GetCustomerCountByCode",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //按客户名称查询
       try
       {
        lr.start_transaction("GetCustomerCountByCustomerName");
        object[] param2 = {methodLR.GetQueryCustomerByCustomerName()};

        Object obj2 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method2 = obj2.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt2 = (DataTable)method2.Invoke(obj2,param2);
        int count2 = Convert.ToInt32(dt2.Rows[0][0]);

        if(count2>0)
         lr.end_transaction("GetCustomerCountByCustomerName",lr.PASS);
        else
         lr.end_transaction("GetCustomerCountByCustomerName",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //按客户类型查询
       try
       {
        lr.start_transaction("GetCustomerCountByCustomerTypeId");
        object[] param3 = {methodLR.GetQueryCustomerByCustomerTypeId()};

        Object obj3 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method3 = obj3.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt3 = (DataTable)method3.Invoke(obj3,param3);
        int count3 = Convert.ToInt32(dt3.Rows[0][0]);

        if(count3>0)
         lr.end_transaction("GetCustomerCountByCustomerTypeId",lr.PASS);
        else
         lr.end_transaction("GetCustomerCountByCustomerTypeId",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //按销售员查询
       try
       {
        lr.start_transaction("GetCustomerCountBySalesManId");
        object[] param4 = {methodLR.GetQueryCustomerBySalesManId()};

        Object obj4 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method4 = obj4.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt4 = (DataTable)method4.Invoke(obj4,param4);
        int count4 = Convert.ToInt32(dt4.Rows[0][0]);

        if(count4>0)
         lr.end_transaction("GetCustomerCountBySalesManId",lr.PASS);
        else
         lr.end_transaction("GetCustomerCountBySalesManId",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //按话务员查询
       try
       {
        lr.start_transaction("GetCustomerCountByTelephonistId");
        object[] param5 = {methodLR.GetQueryCustomerByTelephonistId()};

        Object obj5 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method5 = obj5.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt5 = (DataTable)method5.Invoke(obj5,param5);
        int count5 = Convert.ToInt32(dt5.Rows[0][0]);

        if(count5>0)
         lr.end_transaction("GetCustomerCountByTelephonistId",lr.PASS);
        else
         lr.end_transaction("GetCustomerCountByTelephonistId",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //按客户电话查询
       try
       {
        lr.start_transaction("GetQueryCustomerByTelephone");
        object[] param6 = {methodLR.GetQueryCustomerByTelephone()};

        Object obj6 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method6 = obj6.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt6 = (DataTable)method6.Invoke(obj6,param6);
        int count6 = Convert.ToInt32(dt6.Rows[0][0]);

        if(count6>0)
         lr.end_transaction("GetQueryCustomerByTelephone",lr.PASS);
        else
         lr.end_transaction("GetQueryCustomerByTelephone",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //按客户地址查询
       try
       {
        lr.start_transaction("GetQueryCustomerByAddress");
        object[] param7 = {methodLR.GetQueryCustomerByAddress()};

        Object obj7 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method7 = obj7.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt7 = (DataTable)method7.Invoke(obj7,param7);
        int count7 = Convert.ToInt32(dt7.Rows[0][0]);

        if(count7>0)
         lr.end_transaction("GetQueryCustomerByAddress",lr.PASS);
        else
         lr.end_transaction("GetQueryCustomerByAddress",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       //综合查询
       try
       {
        lr.start_transaction("GetQueryCustomerByAll");
        object[] param8 = {methodLR.GetQueryCustomerByAll()};

        Object obj8 = System.Activator.CreateInstance(typeof(Proxy.CustomerProxy));
        MethodInfo method8 = obj8.GetType().GetMethod("GetCustomerCountByCondition");
        DataTable dt8 = (DataTable)method8.Invoke(obj8,param8);
        int count8 = Convert.ToInt32(dt8.Rows[0][0]);

        if(count8>0)
         lr.end_transaction("GetQueryCustomerByAll",lr.PASS);
        else
         lr.end_transaction("GetQueryCustomerByAll",lr.FAIL);
       }
       catch(Exception ex)
       {
        string error = ex.Message;
       }

       #endregion      
     
       return lr.PASS;
      }

      // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      public int Terminate()
      {
       // TO DO: Add virtual user's termination routines

       return lr.PASS;
      }

     }
    }

    Method代码如下:

    using System;
    using Common;
    using Proxy;
    using DAT;
    using ShangXin;
    using ShangXin.Data;
    using ShangXinInterface;
    using System.Collections;
    using System.Data;

    namespace LRQueryCustomer
    {
     ///


     /// Method 的摘要说明。
     ///

     public class Method
     { 
      Proxy.LoginProxy loginProxy = new LoginProxy();

      public Method()
      {
       //
       // TODO: 在此处添加构造函数逻辑
       //
      }
      public void SetAuth(AuthData auth,CertificationInfo ci)
      {
       for(int i=0;i   {
        ci.AddAuthority((EnumAuthority)(Enum.Parse(typeof(EnumAuthority),auth.Rows[i]["PKID"].ToString())));
       }
      }

      
      public void GetGroupAuth(GroupData groupData,CertificationInfo ci)
      {
       try
       {
        //判断组记录是否为空
        if (groupData.Rows.Count > 0)
        {
         for(int i=0; i     {
          //根据组,获取对应的权限信息,并加载到该用户的权限列表中
          int groupID = SXConvert.ToInt32(groupData.Rows[i][GroupData.PKID]);
          AuthData Groupad = loginProxy.GetGroupAuthByGroupId(groupID);
         
          //加载权限
          if (Groupad.Rows.Count > 0)
          {
           SetAuth(Groupad,ci);
           ci.AddGroup(groupID);
          }

          int parentGroupID = loginProxy.GetParentGroupByGroupID(groupID);

          if (parentGroupID > 0)
          {
           GroupData subGroupData = loginProxy.GetGroupByPKID(parentGroupID);

           //循环加载
           GetGroupAuth(subGroupData,ci);
          }
         }
        }
       }
       catch(Exception exp)
       {
        throw new Exception(exp.Message);
       }
      }
       public void AddToCurrentEmployee(CertificationInfo ci,CertificationInfo CI)
       {
        //先清空当前用户的权限列表
        ci.ClearAuthority();

        //增加基本属性与权限列表
        ci.LoginName = CI.LoginName;
        ci.Password = CI.Password;
        ci.EmployeeId = CI.EmployeeId;
        ci.EmployeeName = CI.EmployeeName;
        ci.RecordCount = CI.RecordCount;

        for(int i=0;i    {
         ci.AddAuthority((EnumAuthority)CI.Authority[i]);
        }

        for(int i=0;i    {
         ci.AddGroup((int)CI.Group[i]);
        }
       }

      #region 查询客户
      //条件为空查询
      public Hashtable GetQueryCustomerConditions()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "";//客户编码
       int salesManId = -1;//销售员
       int employeeId = 64;//
       string customerName = "";//客户名称
       int telePhinstId = -1;//话务员   
       string telephone="";//客户电话
       string address="";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }

      //按客户编号查询
      public Hashtable GetQueryCustomerByCodeConditions()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "31450";//客户编码
       int salesManId = -1;//销售员
       int employeeId = 64;//
       string customerName = "";//客户名称
       int telePhinstId = -1;//话务员   
       string telephone="";//客户电话
       string address="";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }

      //按客户名称查询
      public Hashtable GetQueryCustomerByCustomerName()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "";//客户编码
       int salesManId = -1;//销售员
       int employeeId = 64;//
       string customerName = "一本万利公司第31450分公司";//客户名称
       int telePhinstId = -1;//话务员   
       string telephone="";//客户电话
       string address="";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }

      //按客户类型查询
      public Hashtable GetQueryCustomerByCustomerTypeId()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = 2;//客户类型
       string code = "";//客户编码
       int salesManId = -1;//销售员
       int employeeId = 64;//
       string customerName = "";//客户名称
       string telePhinstId ="" ;//话务员   
       int telephone=-1;//客户电话
       string address="";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);
       
       return conditions;

      }

      //按销售员查询
      public Hashtable GetQueryCustomerBySalesManId()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "";//客户编码
       int salesManId = 314;//销售员
       int employeeId = 529;//
       string customerName = "";//客户名称
       int telePhinstId = -1;//话务员   
       string telephone="";//客户电话
       string address="";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }

      //按话务员查询
      public Hashtable GetQueryCustomerByTelephonistId()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "";//客户编码
       int salesManId = -1;//销售员
       int employeeId = 64;//
       string customerName = "";//客户名称
       int telePhinstId = 23;//话务员   
       string telephone="";//客户电话
       string address="";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }

      //按客户电话
      public Hashtable GetQueryCustomerByTelephone()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "";//客户编码
       int salesManId = -1;//销售员
       int employeeId = 64;//
       string customerName = "";//客户名称
       int telePhinstId = 23;//话务员   
       string telephone="88888888";//客户电话
       string address="";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }

      //按客户地址
      public Hashtable GetQueryCustomerByAddress()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "";//客户编码
       int salesManId = -1;//销售员
       int employeeId = 64;//
       string customerName = "";//客户名称
       int telePhinstId = 23;//话务员   
       string telephone="";//客户电话
       string address="天堂区幸福大道第31450号";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }
      //综合查询
      public Hashtable GetQueryCustomerByAll()
      {
       Hashtable conditions = new Hashtable();
       int parentId = -1;//上一级公司
       int customerTypeId = -1;//客户类型
       string code = "005305";//客户编码
       int salesManId =-1 ;//销售员
       int employeeId = 64;//
       string customerName = "一本万利公司第120分公司";//客户名称
       int telePhinstId =-1;//话务员   
       string telephone="88888888";//客户电话
       string address="天堂区幸福大道第120号";//客户地址
       
       conditions.Add("PARENTID",parentId);
       conditions.Add("CUSTOMERTYPEID",customerTypeId);
       conditions.Add("CODE",code);
       conditions.Add("SALESMANID",salesManId);
       conditions.Add("EMPLOYEEID",employeeId);
       conditions.Add("CUSTOMERNAME",customerName);
       conditions.Add("TELEPHINSTID",telePhinstId);
       conditions.Add("TELEPHONE",telephone);
       conditions.Add("ADDRESS",address);

       return conditions;

      }
      #endregion
     }
    }


  • LR虚拟用户登陆服务器后掉线现象的原因

    2006-12-08 14:09:54

    此程序用SOCKETS录制的,利用  
    for (i=0;i<=100;i++)
      {
      lrs_send("socket2", "buf29", LrsLastArg);
    lr_think_time(100);
    }
        return 0;
    来不断的与服务器端交互。此程序的目的是实现登陆服务器成功,并停留在服务器上很长一段时间(如几天时间)而不掉线就可以。
    原脚本如下:
    /*********************************************************************
    * Created by Mercury Interactive Windows Sockets Recorder
    *
    * Created on: Tue Dec 05 10:02:56
    *********************************************************************/

    #include "lrs.h"


    Action()
    {    int i;
        lrs_create_socket("socket0", "TCP", "RemoteHost=172.16.4.4:6998",  LrsLastArg);

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

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

        lrs_close_socket("socket0");

        lrs_create_socket("socket1", "TCP", "RemoteHost=172.16.4.4:6998",  LrsLastArg);

        lrs_send("socket1", "buf2", LrsLastArg);

        lrs_receive("socket1", "buf3", LrsLastArg);

        lrs_close_socket("socket1");

        lrs_create_socket("socket2", "TCP", "RemoteHost=172.16.4.4:6998",  LrsLastArg);

        lrs_send("socket2", "buf4", LrsLastArg);

    /*   lrs_receive("socket2", "buf5", LrsLastArg);

        lrs_create_socket("socket3", "UDP", "LocalHost=10000",  LrsLastArg);

        lrs_send("socket3", "buf6", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf7", LrsLastArg);

        lrs_send("socket3", "buf8", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf9", LrsLastArg);

        lrs_send("socket3", "buf10", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf11", LrsLastArg);

        lrs_send("socket3", "buf12", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf13", LrsLastArg);

        lrs_send("socket3", "buf14", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf15", LrsLastArg);

        lrs_receive("socket2", "buf16", LrsLastArg);

        lrs_send("socket3", "buf17", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf18", LrsLastArg);

        lrs_send("socket3", "buf19", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf20", LrsLastArg);

        lrs_send("socket3", "buf21", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf22", LrsLastArg);

        lrs_send("socket3", "buf23", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf24", LrsLastArg);

        lrs_send("socket2", "buf25", LrsLastArg);

        lrs_send("socket3", "buf26", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf27", LrsLastArg);

        lrs_receive("socket2", "buf28", LrsLastArg);

        lrs_send("socket2", "buf29", LrsLastArg);

        lrs_send("socket3", "buf30", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf31", LrsLastArg);

        lrs_send("socket2", "buf32", LrsLastArg);

        lrs_send("socket3", "buf33", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf34", LrsLastArg);

        lrs_send("socket3", "buf35", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf36", LrsLastArg);

        lrs_send("socket2", "buf37", LrsLastArg);

        lrs_send("socket3", "buf38", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf39", LrsLastArg);

        lrs_send("socket3", "buf40", "TargetSocket=172.16.4.4:10000", LrsLastArg);

        lrs_receive("socket3", "buf41", LrsLastArg);

        lrs_receive("socket2", "buf42", LrsLastArg);

        lrs_send("socket2", "buf43", LrsLastArg);
    */
      for (i=0;i<=100;i++)
      {
      lrs_send("socket2", "buf29", LrsLastArg);
    lr_think_time(100);
    }
        return 0;
    }

    data.ws文件如下:
    ;WSRData 2 1

    send  buf0 7
            "\xff\x01\x01\x00\xff\x01\x01"

    recv  buf1 20
            "\xff\xcd\x0e\x00\xff\xcd\x00\x00"
            "04.03.21.00"
            "\x00"

    send  buf2 44
            "\xff\x00"
            "&"
            "\x00\xff\xcd\x02"
            "<test5>"
            "\x00\xff\xff\xff"
            "霉竪鉧萲"
            "\x00\x00\x00\x00"
            "燘1"
            "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\xf8\x12\x00"
            "l"
            "\xe9"

    recv  buf3 72
            "\xff"
            "虰"
            "\x00\xff\xcd\x00\x00"
            "\""
            "\x00\x00\x00"
            "test"
            "\x00"
            "w鉧萲"
            "\x00\x00\x00\x00"
            "燘1"
            "\x00\x00\x00\x00\x00\xc8\x00"
            "\b"
            "\x00\x18\xf8"
            "#"
            "\x00\x00\x00"
            "lr"
            "\x00\xfe\x12\x00"
            "栎"
            "\x12\x00"
            "屯屯屯屯屯屯"
            "\xc9\x00\x00\x00"
            "屯"

    send  buf4 54
            "\xff"
            "60"
            "\x00\xff\xcd\x03\x00\x00\x00"
            "#"
            "\x00\x00\x00"
            "<test5>"
            "\x00"
            "梯"
            "\x12\x00"
            "0撊k"
            "\x15\x03\xff\xff\xda\x02"
            "\b"
            "\x00\x05"
            "1"
            "\x00\x00\x00\x00\x00\x00"
            "斑"
            "\x12\x00"
            "羹"
            "\x12\x00"
            "栎"
            "\x12\x00"

    recv  buf5 60
            "\xff\xcd"
            "6"
            "\x00\xff\xcd\x00\x00\x00"
            "烫"
            "\xcc"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x02\xcc\x10"
            "'"
            "\x10"
            "'"
            "\x01"
            "泰"
            "\x01\x00\x00"
            "<test5>"
            "\x00"
            "梯"
            "\x12\x00"
            "0撊k"
            "\x15\x03\xff\xff\xda\x02"
            "\b"
            "\x00\x05\x02\x00\x00\x00\x00\x00\x00"

    send  buf6 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf7 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf8 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf9 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf10 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf11 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf12 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf13 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf14 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf15 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    recv  buf16 8
            "\xff\xcd\x02\x00\xff\xcd"
            ",\b"

    send  buf17 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf18 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf19 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf20 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf21 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf22 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf23 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf24 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf25 12
            "\xff"
            "6"
            "\x06\x00\xff\xcd\x01"
            "\b"
            "\x01\x01\x01\x00"

    send  buf26 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf27 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    recv  buf28 8
            "\xff\xcd\x02\x00\xff\xcd"
            ",\b"

    send  buf29 8
            "\xff"
            "6"
            "\x02\x00\xff\xcd"
            ",\b"

    send  buf30 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf31 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf32 8
            "\xff"
            "6"
            "\x02\x00\xff\xcd"
            ",\b"

    send  buf33 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf34 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf35 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf36 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf37 8
            "\xff"
            "6"
            "\x02\x00\xff\xcd"
            ",\b"

    send  buf38 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf39 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    send  buf40 13
            "\x01"
            "#"
            "\x00\x00\x00\xa9\x01\x00\x00\x00\x00\x00\x00"

    recv  buf41 7
            "\x01\xa9\x01\x00\x00\x01\x00"

    recv  buf42 8
            "\xff\xcd\x02\x00\xff\xcd"
            ",\b"

    send  buf43 8
            "\xff"
            "6"
            "\x02\x00\xff\xcd"
            ",\b"


    -1
    大家觉得最可能的原因是什么而导致自动掉线现象???
  • 测试工程师工作流程概论

    2006-12-08 14:08:10

    测试工程师工作流程概论
    作者: 崔启亮  来源: 本地化测试网
    测试工程师的工作流程,与公司的整体工作流程,项目的测试要求等因素相关。本文主要讨论测试工程师的一般工作流程。

        做好测试准备

        1) 明确测试任务的范围

        测试文档通常包括测试目的、测试环境、测试方法、测试用例、测试工具等。测试工程师首先要通读文档,对整个测试要求形成整体认识,明确测试目的,以及测试要求和测试重点,明确软件测试方法和使用的测试工具。

        2) 明确测试时间

        明确测试周期和测试时间进度。如果是多人合作完成一个软件,则要首先明确属于自己的测试内容、根据测试内容和测试周期,估算自己每日应该完成的工作量。此外由于软件测试是群体协作的测试活动,需要明确哪些测试内容要与其他测试工程师协作才能完成。

        3) 设置测试环境

        根据测试文档要求,设置测试需要的软件和硬件环境,包括操作系统,要测试的软件和其他必要的测试工具软件等。所有这些完成后,分别运行,查看是否能正确运行,保证符合测试文档要求的测试环境。

        4) 学习被测试软件

        对于不太熟悉的软件,可以通过阅读软件自身的教程和帮助文件,学习本软件的一般操作方法,也可以参照相关的书籍资料等。另外,向熟悉测试软件的其他同事请教软件使用方法,也是学习软件的一条捷径。对软件使用越熟练,测试过程越顺利,测试效果越理想。

        5) 确认完全理解测试任务

        软件测试最重要的要求就是确实明确了测试任务和要求,这包括正确理解了测试文档,确认可以按照测试进度要求,完成测试。对于测试工具要正确安装,熟练使用。如果有任何不明白之处,向软件测试负责人询问。切忌凭自己的理解和主观推测,自行其事。当然,真正测试中,往往会遇到各种新的小疑难问题,也需要及时向测试负责人请教,以保证测试顺利进行。

        执行软件测试任务

        1) 按照测试文档要求,逐项认真测试

        根据测试文档测试要求,按照测试步骤,逐项进行。通过运行软件,观察测试结果,与软件需求说明书的内容进行比较,找出软件错误。对于需要调用测试用例的测试,保证正确地调用了测试用例,注意观察和分析测试结果。某些不容易重复的错误,需要反复测试,总结重复该错误所需要的测试步骤,直到确认可以重复出现为止。

        2) 记录发现的错误,填写软件问题报告

        为了纠正软件中的错误,测试工程师要正确记录发现的错误,将错误再现的步骤写入测试报告中,测试报告是程序测试的重要组成部分,正确书写测试报告是对测试工程师的基本要求。采用软件缺陷数据库管理测试中发现的软件缺陷,每一条错误作为数据库的一条记录,方便记录、修改、查询。

        3) 填写测试进度表和必要的测试内容记录表

        每天将测试内容写入测试进度表文档,可以使测试负责人了解测试进度,控制测试周期内测试的连续性,增强测试过程控制性,保证测试的正常进行。测试记录要准确完整,实事求是,必要时插入测试注释,解释测试中的特殊问题。测试进度表是评价测试质量和工作内容的重要凭证,对于测试后发现的测试错误和失误,可以通过检查测试记录,寻找产生错误的原因。

        4) 测试中发现疑难及时请教

        测试是一个动态的过程,可能由于自己的错误操作或者测试文档内容的错误,使得测试过程中出现自己不能解释的现象或结果,出现与测试要求不符合的情形,这时可能需要与其他测试者协商或求助,如果问题仍然不能解决,应该及时请教,听取意见和建议,必要时反复讨论直到问题全面解决。

        全面检查测试结果

        1) 对照测试文档要求,检查测试内容是否完整

        测试完成后,要对照测试文档检查测试是否全部完成,保证没有丢失测试内容。如果某些内容,由于测试环境的要求不满足,或者由于测试时间短没有进行,则要写入测试进度表文档。

        2) 检验书写的软件问题报告的记录,使之确切、规范

        正确书写测试记录是保证迅速定位软件错误,加快改正错误的必要前提。专业规范的软件记录报告是体现公司测试水平和专业实力的外在体现。认真检查书写的每条记录是否符合规范,格式、步骤、内容一一检查,必要时补充或删减。

        上述三个阶段,相互联系紧密,其中准备是基础,测试是重点,检查是保证,应该根据测试的软件特点合理安排。

  • 测试工具全集

    2006-12-07

    通用功能自动化测试工具

    厂商   工具名称
    Mercury Winrunner
    Mercury Quicktest pro
    Mercury XRunner
    Compuware QARun
    Compuware WebCheck
    Compuware TestPartner
    Parasoft WebKing
    IBM Rational Robot
    IBM Rational Visual Test
    IBM Rational Functional Tester
    Segue SilkTest
    Segue SilkTest International
    Empirix e-Tester
    Radview WebFT
    AutomatedQA TestComplete
    Seapine QA Wizard
    RedStone Software EggPlant
    Microsoft Visual Studio Test Edition
    Minq PureTest
    Autotester Autotester
    Original Software Testbench400
    VEReCOMM TestExpert
    Qronus TestRunner
    Telelogic TTCN suite
    Centerline QC/Replay
    AutoTester Web
    Software Research eValid
    OCLC WebART
    开源 MaxQ
    开源 WebInject
    开源 Marathon 
    性能测试/监控工具

    厂商   工具名称
    Mercury LoadRunner
    Mercury SiteScope
    Mercury Topaz
    Compuware QaLoad
    Quest PerformaSure/benchmark
    Segue Silkperformer
    Segue Silkperformer Lite
    Segue SilkCentralTM Performance Manager
    Empirix e-Load
    IBM Rational Robot
    IBM Rational Performance Tester
    RadView WebLoad
    Microsoft Web applicaton stress tool
    Microsoft Application center test
    Minq PureLoad
    Metron Athene APR
    facilita ForeCast
    Cyrano Impact/Impact for CBT
    Lawrence Berkeley Laboratory sniffer
    开源 Jmeter
    开源 openSTA
    开源 Siege
    开源 StressMark
    开源 DBMonster 
    白盒测试/代码分析工具

    厂商   工具名称
    Parasoft Jtest
    Parasoft C++test
    Parasoft SOA test
    Parasoft .test
    Parasoft Codewizard
    Parasoft Insure++
    Parasoft DataRecon
    Compuware Numega devpartner studio
    Compuware DevPartnerJavaEdition
    Compuware BoundsChecker
    Compuware SmartCheck
    Compuware DBPartner
    Empirix Bean-test
    AutomatedQA AQtime
    AutomatedQA QESatJava
    Unitware Visual Unit
    Gimpel Software PC-lint
    Macabe Macabe
    Borland Optimizeit Suite
    Quest Software JProbe Suite
    Quest Software Application assurance suite
    Quest Software Sql optimizer
    ej-technologies JProfiler
    cyrano workbench
    TeleLogic Logiscope
    TeleLogic rulecheck
    Macabe Macabe
    Segue SilkPerformer Component Test Edition 
    IBM rational Purifyplus
    IBM rational Rational Test Realtime
    开源 junit
    开源 cactus
    开源 Hansel
    开源 TestNG
    开源 StrutsTestCase
    开源 JFCUnit
    开源 Httpunit
    开源 Dunit
    开源 cppunit
    开源 Nunit
    开源 Xunit
    开源 JTR
    Linux平台工具 MallocDebug
    Linux平台工具 Valgrind
    Linux平台工具 Kcachegrind
    Linux平台工具 dmalloc
    Linux平台工具 ElectricFence
    Linux平台工具 LeakTracer
    Linux平台工具 memprof
    Linux平台工具 ccmalloc
    Linux平台工具 mprof
    Linux平台工具 yamd
    Linux平台工具 njamd
    Linux平台工具 mpatrol 
    嵌入式系统测试工具

    厂商   工具名称
    Metrowerks codetest
    IPL Cantata/cantana++
    Reflex Technology IceMaster
    Reflex Technology System test
    DDC-I scorecast
    testquest Testquest
    ATTOL UniText
    Vector software vectorcast
    qronus testrunner
    telelogic Logiscope
    RT-Builder 
    测试管理工具

    厂商   工具名称
    Mercury TestDirector(QualityCenter)
    Compuware QADirector
    worksoft certify
    aimware Product manager
    segue SilkCentral Test Manager
    telelogic Doors
    empirix e-manager
    IBM Rational testmanager
    RadView TestView Manager
    T-Plan Professional
    testlink  

    缺陷管理工具

    厂商   工具名称
    Mercury TestDirector(QualityCenter)
    IBM Rational ClearQuest
    Compuware TrackRecord
    Seapine TestTrack pro
    McCabe TrueTrack
    Techexcel Devtrack 
    IBM Lotus Notes
    Segue SilkCentral Issue Manager
    Merant PVCS Tracker
    Remedy AR System
    LealSoft URTrack
    缺陷管理系统BMS
    Clarion
    Hansky Butterfly
    开源 Bugzilla
    开源 Mantis
    开源 JIRA
    开源 BugFree 
    配置管理工具

    厂商   工具名称
    IBM Rational ClearCase
    Merant PVCS Version Manager
    Diamond VCS
    Computer Associates AllFusion Harvest Change Manager/CCC Harvest
    Borland StarTeam
    MKS Source Integrity Enterprise and Integrity Manager
    Serena ChangeMan Professional
    Perforce Perforce
    McCabe TRUEchange
    Telelogic SYNERGY CM
    Microsoft VSS
    JBCM
    Hansky Firefly
    开源 CVS
    开源 subversion
    开源 SCCS
    开源 RCS
  • LoadRunner学习笔记

    2006-12-07

    LoadRunner学习笔记

    事务(Transaction)是这样一个点,我们为了衡量某个action的性能,需要在action的开始和结束位置插入这样一个范围,这就定义了一个transaction,LoadRunner 运行到该事务的开始点时,LoadRunner 就会开始计时,直到运行到该事务的结束点,计时结束。这个事务的运行时间在结果中会有反映。所以 LR 的事务添加操作就是把测试所需要关注的操作定义成事务告诉 LR,这个是我想要重点检测性能的操作。LR就会在运行过程中记录事务内操作的响应事件等性能

    数据。并在 Analysis中以报告的形式给出统计结果。

    lr_start_transaction(”SubmitBookData”);

    /*中间代码部分*/

    lr_end_transaction(”SubmitBookData”, LR_AUTO);

    2.1.2 集合点(Rendezvous) 

    集合点:是一个并发访问的点,在测试计划中,可能会要求系统能够承受1000人同时提交数据,在LoadRunner中可以通过在提交数据操作前面加入集合点,这样当虚拟用户运行到提交数据的集合点时,LoadRunner 就会检查同时有多少用户运行到集合点,如果不到1000人,LoadRunner就会命令已经到集合点的用户在此等待,当在集合点等待的用户达到1000 人时,LoadRunner 命令1000 人同时去提交数据,并发访问的目的。 

    注意:集合点经常和事务结合起来使用,常放在事务的前面,集合点只能插入到Action 部分,vuser_init和vuser_end 中不能插入集合点。集合点函数如下,参数不能加空格:lr_rendezvous(”SumitQueryData”); 加入集合点之后,在后面运行过程中可以看到VU的状态,会等待集合。 

    2.1.4 IP Spoofer(IP 欺骗) 

    LoadRunner允许运行的虚拟用户使用不同的IP 访问同一网站,这种技术称为“IP 欺骗”。 

    启用该选项后,场景中运行的虚拟用户将模拟从不同的IP 地址发送请求。该选项非常的有用。注意:IP Spoofer 在连接Load Generators 之前启用。要使用IP 欺骗,各个Load Generator 机器必须使用固定的IP,不能使用动态IP(即DHCP)。 

    IP Wizard工具,添加一个局域网内的IP段。添加后重启,在Win2k下使用Ipconfig/all查看到很多虚拟的IP,最后要在Controller里面选择enable ip spoofer. 

    2.1.5(Text/Image)检查和 contents check 点 

    对于查询类的脚本,一定要添加检查点,以保证在测试时结果的正确性.因为LR只要检测到网页的响应,就认为是pass而并不管当前网页内容的正确性.在进行压力测试时,为了检查Web服务器返回的网页是否正确,VuGen允许我们插入Text/Imag 检查点,这些检查点验证网页上是否存在指定的Text或者Image,还可以测试在比较大的压力测试环境中,被测的网站功能是否保持正确。检查点的含义和WinRunner 中的检查点功能基本上一致,这里就不再说了.

    比如登录,我要测试200人同时登录, 

    但是我的login.jsp里面没有正确的关闭数据库的连接, 

    导致登录100人后,建立了100个数据库连接, 

    第101人一个人登录的时候,由于超出数据库连接的最大数, 

    所以,jsp程序抛出了一个数据库异常。 

    但是页面的走向是正确的,所以loadrunner会认为程序是正确执行的,但是事实却并非如此。 

    2.1.6 LR 脚本复用问题 

    LR的测试脚本有很好的复用性,参数化后的脚本,在应用没什么大的变化的情况下,一直是可以用的。甚至你在A服务器录制的脚本,如果做测试的时候,需要转移到B服务器上,你只需要用查找替换的功能将A服务器的IP地址换成B服务

    2.1.7 理解 Correlation(关联)

    关联是用来解决脚本中存在的动态数据问题的.在7.8中,当你回放一次后,LR会自动录找你录制的时候和回放时候的差别,找出动态数据,并作成参数。

    理解web_reg_save_param函数, 

    int web_reg_save_param (const char *ParamName, , LAST);

    第一部分:参数名字,用双引号括起,逗号分开; 

    第二部分:List of Attributes,包括:LB、RB、RelFrameID、Ord、Search、SaveOffset、

    SaveLen等, 

    第三部分:LAST,结束标志。

    左边界,右边界到底是个什么概念? 

    LB是左边界,要查找的字符串左面的边界值,即位于查找字符串的最左边的字符串,RB是右边界,要查找的字符串右面的边界值,即位于查找字符串的最右边的字符串,比如说吧,程

    Search是指查找范围,就是说在哪里查找这些值,可以取这样几个值,我们一般设为ALL,

    Body等即可。 

    Headers (Search only the headers), 

    Body (search only Body data, not headers), 

    Noresource (search only the html body, excluding all headers and resources), 

    ALL (search Body and headers). The default value is ALL. 

    RelFrameID: The hierarchy level of the HTML page relative to the requested URL.

    一般取1

    ORD: This parameter, also known as Instance, indicates the ordinal or instance of 

    the match. 一般取 1 

    一般把系统的那些都关掉,定义自己的,只是有的时候,它不能自动关联,就

    干脆手工作了。需要关联的地方:一般是在有主键,不允许记录重复,和一些主程序中传递过来的参数,在后面要用到等情况才使用关联的,你可以先执行一遍,如果有些地方不允许重复,参数值无效,就会出错的,根据错误提示你可以判断出来,就知道需要关联了。一般需要关联的不多,我现在遇到的就是进程号,以及表的主键。

    以下是一个例子讲解LR,呵呵!

    2. 1. 8 以录制 Web(Http/Html)协议为例讲述一下 LR 的脚本的录制 

    LR的脚本是C语言代码,LR有自己的一整套函数接口,可以供外部调用,在VUGen里面敲Lr_就可以看到了。Web(Http/Html)脚本本身分INIT,ACTION,END三部分,各部分的解释:INIT部分可以理解为初始部分,ACTION可以理解为事务部分,也是测试的主体,END是退出结束。重复的时候,仅重复action部分。我们一般把登录部分放在init,退出放到end,只会执行一次,或者有的时候,各部分反复的次数不一样,分成多个action,可以单独设定反复次数。(如果需要在登陆操作设集合点,那么登陆操作也要放到Action 中,因为vuser_init 中不能添加集合点) 

    脚本里面有 2 个函数,解释一下:1.几个函数的解释: 

    1) int web_url (const char *Name, const char * url, 

    [EXTRARES, ,] LAST ; 

    这个函数 load 指定的web 页面 . *Name:页面的name; url:页面的url,Resource:指示the URL 是否是一个资源。0,不是,1, RecContentType:录制脚本过程中,Header 响应的类型,e.g. text/html, 

    application/x- javascrīpt Referer – 参考 web 页的 the URL Snapshot - snapshot 文件名(扩展名inf), correlation 的时候要的。 Mode – 录制的级别: HTML or HTTP Last- 属性列表的结束标志。


    名词方面的解释    迭代(Iterate)设计,或者我们称之为增量(Incremental)设计的思想和XP提倡的Evolutionary Design有异曲同工之妙。注意:1、 参数类型:在创建参数的时候,我选择了参数类型为File。参数类型共有9 种,现在来简单介绍一下所有的参数类型以及意义。1.1、  DateTime:在需要输入日期/时间的地方,可以用 DateTime 类型来替代。其属性设置也很简单,选择一种格式即可。当然也可以定制格式。1.2、  Group Name:很少用到。在实际运行中,LoadRunner 使用该虚拟用户所在的Vuser Group 来代替。但是在 VuGen 中运行时,Group Name将会是None。1.3、  Load Generator Name :在实际运行中, LoadRunner  使用该虚拟用户所 在LoadGenerator  的机器名来代替。1.4、  Iteration Number :在实际运行中,LoadRunner 使用该测试脚本当前循环的次数来代替。1.5、  Random Number:随机数。很简单。在属性设置中可以设置产生随机数的范围。1.6、  Unique Number:唯一的数。在属性设置中可以设置第一个数以及递增的数的大小。注意:使用该参数类型必须注意可以接受的最大数。例如:某个文本框能接受的最大数为99。当使用该参数类型时,设置第一个数为 1,递增的数为1,但100  个虚拟用户同时运行时,第100  个虚拟用户输入的将是 100,这样脚本运行将会出错。这里说的递增意思是各个用户取第一个值的递增数,每个用户相邻的两次循环之间的差值为 1。举例说明:假如起始数为 1,递增为 5,那么第一个用户第一次循环取值 1,第二次循环取值 2;第二个用户第一次循环取值为 6,第二次为 7;依次类推。1.7、  Vuser ID:设置比较简单。在实际运行中,LoadRunner 使用该虚拟用户的 ID  来代替,该 ID  是由 Controller 来控制的。但是在 VuGen 中运行时,Vuser ID  将会是 –1。1.8、  File:需要在属性设置中编辑文件,添加内容,也可以从现成的数据库中取数据1.9、  User Defined Function:从用户开发的 dll 文件提取数据。

    1、 负载生成器: 

    负载生成器是用来模拟生成虚拟用户的。 

    根据经验,每生成一个虚拟用户,需要花费负载生成器大约 2M 的内存空间。通常运行 controller的主机很少用作负载生成器。负载生成器的工作多由其他装有 LR Agent的PC 机来担任。如果负载生成器内存的使用率大于了 70%,负载生成器就会变成系统的瓶颈,导致性能测试成绩下降。这种问题需要添加负载生成器来解决。一台 512M内存的 PC 机大约可以生成 80 个左右的负载,而一台 256M 内存的 PC 机大约可以生成50到 60 个左右的负载。 

    2、 运行[时间]在加压完成后: 

    当“运行[时间]在加压完成后”设置了以后,原本定义的运行时设置中的迭代次数就失效了。或者说加压 “持续时间”的优先级要高于“运行时设置”。比如当一个脚本设置了运行时设置中的迭代次数为 10 次,在“持续时间”中设置加压持续时间为 30分钟。当真正运行时,脚本迭代10 次后仅花费了20分钟,但是持续时间设了30 分钟,因此它不能停下来,还会继续迭代。到最后脚本实际迭代的次数就不止 10次了。


    LR 对服务器资源的监视

    LR只能监视它支持的服务器的资源,它支持大部分常见的服务器。 

    System Resource:包括windows平台,Unix平台等 

    Web Server:包括Apache、IIS、Sun的iplanet等 

    Application server:包括Weblogic、WebSphere等 

    Database server:包括DB2,Oracle,Sql server,Sybase等 

    Java: ejb,J2ee等,需要一个ejbdetector.jar文件 

    1.对Windows(Win2k server)的监视: 

    对windows的监视相对比较简单,监视前首先需要用有管理员权限的帐号连接被监

    server,例如:net use \\qa-test /user:donny ,输入密码。然后就可以添加计数器,

    比较常用的计数器有: 

    Memory:Available Mbytes 物理内存的可用数(单位 Mbytes)至少要有10% 的物理内存值 

    Processor:%Processor Time CPU 使用率。这是查看处理器饱和状况的最佳计数器。显示所有 CPU 的线程处理时间。如果一个或多个处理器的该数值持续超过 90%,则表示此测试的负载对于目前的硬件过于沉重。为多处理器服务器添加该计数器的 0 到 x 个实例。 

    Processor Queue Length:是指处理列队中的线程数,小于2。处理器瓶颈会导致该值持续大于2。

    Context Switches/sec:如果切换次数到5000*CPU个数和10000*CPU个数中,说明它忙于切换线程 

    Network Interface:Bytes Total/sec 为发送和接收字节的速率,包括帧字符在内。判断网络连接速度是否是瓶颈,可以用该计数器的值和目前网络的带宽比较。 

    SQL Server2000:%Processor Time,CPU 使用率 

    General Statistics,Logins/sec,这是每秒登录到 SQL Server 的计数。 

    SQL Statistics: Batch Requests/sec,每秒收到的 Transact-SQL 命令批数。这一统计信息受所有约束(如I/O、用户数、高速缓存大小、请求每秒收到的 Transact-SQL 命令批数。这一统计信息受所有约束(如I/O、用户数、高速缓存大小、请求的复杂程度等)影响。

    批请求数值高意味着吞吐量很好。

    2.对Unix(Linux等)的监视,需要配置相应的服务器端,可以查看帮助文件,这里就只举

    一个例子了。 

    1) LoadRunner 如何监控Apache,需要修改apache的配置文件httpd.conf.


    SetHandler server-status 

    Order deny,allow 

    Allow from all 

    Allow from .your-domain.com 


    把这节加在httpd.conf里面, restart apache即可。

    页面分解 

    如果某个transaction的时间过长,为了分析问题出在哪里?就可以利用页面分解了,它可

    以把每个页面分解成:

    DNS解析时间:浏览器访问一个网站的时候,一般用的是域名,需要dns服务器把这个域名解析为IP,这个过程就是域名解析时间,如果我们在局域网内直接使用IP访问的话,就没有这个时间了。 

    Connection:解析出Web Server 的IP地址后,浏览器请求被送到了Web Server,然后浏览器和Web Server 之间需要建立一个初始化HTTP连接,服务器端需要做2件事:一是接收请求,二是分配进程,建立该连接的过程就是connection时间。 

    First Buffer:建立连接后,从Web Server 发出第一个数据包,经过网络传输到客户端,浏览器成功接受到第一字节的时间就是First Buffer。这个度量时间不仅可以表示Web Server 的延迟时间,还可以表示出网络的反应时间。 

    Receive:从浏览器接收到第一个字节起,直到成功收到最后一个字节,下载完成止,这段时间就是receive时间。 

    其他的时间还有SSL Handshaking(SSL 握手协议,用到该协议的页面比较少)、

    ClientTime(请求在客户端浏览器延迟的时间,可能是由于客户端浏览器的think time 或者客户端其他方面引起的延迟)、Error Time(从发送了一个HTTP 请求,到Web Server发送回一个HTTP 错误信息,需要的时间)

    为了确认问题缘由到底是服务器还是网络,选择“Time to First Buffer(缓冲器) Breakdown”发现network时间比Server时间要高的多,从而确定问题是network引起的。

     

  • SQL Server性能分析

    2006-12-07

    SQL Server性能分析
    当您怀疑计算机硬件是影响SQL Server运行性能的主要原因时,可以通过SQL Server Performance Monitor监视相应硬件的负载,以证实您的猜测并找出系统瓶颈。下文将介绍一些常用的分析对象及其参数。
    Memory: Page Faults / sec
      如果该值偶尔走高,表明当时有线程竞争内存。如果持续很高,则内存可能是瓶颈。
    Process: Working Set
      SQL Server的该参数应该非常接近分配给SQL Server的内存值。在SQL Server设定中,如果将”set working set size”置为0, 则Windows NT会决定SQL Server的工作集的大小。如果将”set working set size”置为1,则强制工作集大小为SQLServer的分配内存大小。一般情况下,最好不要改变”set working set size”的缺省值。 
    Process:%Processor Time
      如果该参数值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。
    Processor:%Privileged Time
      如果该参数值和”Physical Disk”参数值一直很高,表明I/O有问题。可考虑更换更快的硬盘系统。另外设置Tempdb in RAM,减低”max async IO”,”max lazy writer IO”等措施都会降低该值。
    Processor:%User Time
      表示耗费CPU的数据库操作,如排序,执行aggregate functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水平分割大表格等方法来降低该值。
    Physical Disk:Avg.Disk Queue Length
      该值应不超过磁盘数的1.5~2倍。要提高性能,可增加磁盘。
      注意:一个Raid Disk实际有多个磁盘。
    SQLServer:Cache Hit Ratio
    该值越高越好。如果持续低于80%,应考虑增加内存。 注意该参数值是从SQL Server启动后,就一直累加记数,所以运行经过一段时间后,该值将不能反映系统当前值。

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

    2006-12-07

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

    Inetinfotongue.gifrivate 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&#8482; 如何使用: 内存存储数据页、内部数据结构和过程高速缓存;计数器在 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&#8482; 如何使用内存存储对象,如存储过程、特殊和准备好的 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 wink.gif (平均闩等待时间(毫秒)) 一个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)
  • [翻译]LoadRunner与Winsock协议

    2006-12-07

    翻译]LoadRunner与Winsock协议(一)在开始讨论winsocket解决方案之前,我们先讨论一下各种协议是如何工作.从前面的简介可以了解到很多的高级协议,例如FTP,HTTP协议等.以及所有基于window的应用(例如IE,WS-FTP)底层都是在Winsocket层上通信,因此任何高级协议的底层都是用Winsocket通信。什么时候在LR中选择Winsocket协议呢?你要先了解LR是怎么样工作的:LR捕捉API请求然后再把它们回放。所以当你在创建LR WEB脚本的时候,VUGEN捕捉从IE出去的所有的HTTP请求。除此之外lr还支持其他很多协议,例如Oracle,ODBC等。在选择不同协议录制脚本的时候,LR是依靠hooks捕捉正确的API请求。所以既然大部分网络协议都是架构在winsocket协议之上的,那对于lr不支持的协议,我们都可以在winsocket层上录制脚本。所以当找不到合适协议的时候,可以选择winsocket来录制。录制WinSock协议脚本!Lr录制新的虚拟用户脚本,选择winsock协议在web虚拟用户脚本中录制的是URL信息,所以VUGEN启动流览器并运行就可以了,但选择Winsocket录制的时候,可能会是各种形式的应用,并不简简单单就是浏览器,所以在开始的时候我们不需要指定应用的地址。下面的例子我们选择winsock来录制web应用,正如上面说的我们开始要指定ie的地址。因为本来lr是支持http协议的,所以这个例子并无具体的意义,只是为了使例子简单。

    [翻译]LoadRunner与Winsock协议(二)
    winsock脚本典型代码?

    lrs_create_socket(”socket0″, “UDP”, “LocalHost=0″, “RemoteHost=doors:2084″, LrsLastArg);

    lrs_create_socket(”socket1″, “TCP”, “LocalHost=0″, “RemoteHost=www2.yahoo.com:80″, LrsLastArg);

    lrs_send(”socket0″, “buf0″, LrsLastArg);

    lrs_receive(”socket0″, “buf1″, LrsLastArg);

    lrs_send(”socket1″, “buf2″, LrsLastArg);

    lrs_send(”socket0″, “buf3″, LrsLastArg);

    lrs_receive(”socket0″, “buf4″, LrsLastArg);



    这是访问雅虎的一个应用,正如我们看到的,winsock先打开一个winsocket连接,然后收发包。我们发现录制的脚本中比web脚本(三个文件)多一个文件。

    第四个文件是data.ws,它里面记载了在action里面收发所有包的内容下面是一个data.ws的例子。

    send buf0

    “!”

    recv buf1 1

    “!”

    send buf2

    “GET / HTTP/1.1\r\n”

    “Accept: */*\r\n”

    “Accept-Language: en-us\r\n”

    “Accept-Encoding: gzip, deflate\r\n”

    “User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n”

    “Host: www.yahoo.com\r\n”

    “Connection: Keep-Alive\r\n”

    “Cookie: B=5oj83bst12l6m&b=2; Y=v=1&n=8lln5lmi3f8g1&l=6ef8c0d34b0/o&p=m2a2s”

    “qa4110004&r=3f&lg=us&intl=us; T=z=4TVE6A4ZqE6A9dIIpt30.NQNTYGNDE3NTYwM081&”

    “a=AAE&sk=DAAEwinHlDtEm/&d=c2wBTWpFQk16WXdNakUzTkRneQFhAUFBRQF6egE0VFZFNkFn”

    “V0E-; I=i1=010g1q1u24252e2i2k2p2r494a4g4m4q55565b5g6g6t6u7172737678797a7f7″

    “g7k7n7o888f8k8p8q989c9f9i9k9l9n9qacanapb0b3bdbfbhblbqbrbuc0c1c4cgcmcscteie”

    “jgr&ir=73\r\n”

    “\r\n”

    send buf3

    “!”

    recv buf4 1

    “!”

    recv buf5 2048

    “HTTP/1.0 200 OK\r\n”

    “Content-Length: 16030\r\n”

    “Content-Type: text/html\r\n”

    “\r\n”

    “ 

    buf2包含了发给www.yahoo.com的包,buf5包含了从server收到的回应。正如看到的winsock录制的脚本并不像web脚本那样具有可读性,因为winsock是我们最后的选择。在buf序列号的后面是buf的字节数。例如5号buffer后面的2048就是表示收到了2048个帧。

    注意:在很多buffer里面你会发现仅仅包含了一个“!”,这是一个网络常识,这个帧对于应用来说没有任何的作用,完全可以把这些桢清除掉,在data.ws清除这个帧是效果的,需要到action里把这些桢注释掉。譬如例子中收到和发出的buffer可以用//注释掉。这样可以使脚本运行得更快。下边的例子: buffers 0, 1, 3 和 4 可以注释掉:

    lrs_create_socket(”socket0″, “UDP”, “LocalHost=0″, “RemoteHost=doors:2084″, LrsLastArg);

    lrs_create_socket(”socket1″, “TCP”, “LocalHost=0″, “RemoteHost=www2.yahoo.com:80″, LrsLastArg);

    // lrs_send(”socket0″, “buf0″, LrsLastArg);

    // lrs_receive(”socket0″, “buf1″, LrsLastArg);

    lrs_send(”socket1″, “buf2″, LrsLastArg);

    // lrs_send(”socket0″, “buf3″, LrsLastArg);

    // lrs_receive(”socket0″, “buf4″, LrsLastArg);

    lrs_receive(”socket1″, “buf5″, LrsLastArg);

    lrs_send(”socket0″, “buf6″, LrsLastArg);

    [翻译]LoadRunner与Winsock协议(三)
    创建脚本步骤:

    1. VuGen录制脚本

    2.增强脚本

    3.参数化

    4.关联脚本

    5.设置运行参数

    6.运行脚本

    1. VuGen录制脚本


    按照之前章节说的步骤创建脚本,录下来的就是基本脚本,可以先把“!”的buffer注释掉。

    练习:

    创建一个简单的winsock脚本,可以选择MI公司的网站,把录下来的脚本命名为winsocket_1,再用Http协议方式创建一个Web脚本,把脚本保存为WebWinsock_1.请不要更改session_id把两种脚本比较,当你登陆的时候,可以收到一个“welcome,jojo….”的消息。既然所有的消息都放在data.ws文件里,那么data.ws里面应该能找到这条消息。

    1.1) 在几号bufffer里面包含“welcome,jojo”?怎样判断这是收到的帧而不是发出的帧?还有着个字符串正如显示的那样或者他是html的一个标签。

    仔细查看脚本,在data.ws文件中寻找MSO=SIDxxxxxxxxx,XXXXXX是9位数的号码 ,他表示自从January 1 st,1970以来流逝的所有的秒时间,cookie和session_id都是根据时间来生成的,所以脚本里面的9位数也就直接和脚本运行时间挂钩,所以我们要把这个数改成我们每次运行脚本的确切时间,首先把这个值更换成参数,在c里面有一个Time()的函数。他返回的就是自从January 1 st,1970以来流逝的所有的秒时间,在脚本的开始用这个函数获取时间值,然后把刚才创建的参数指向这个值。然后在data.ws里面替换所有的id,这样每次脚本运行都能获得正确的id。

    1.2)把修改了参数的脚本运行一遍,在脚本的运行日志里面寻找”incorrectly”。会找到”You’ve reached this page incorrectly”这条消息,运行web脚本也会发现类似的消息。其中发生了什么呢?

    注意:在data.ws文件中收到的buffer内容在每次运行时不会改变,录制脚本时data.ws文件被创建并且回放过程中也不会改变?所以lr录制的脚本种buffer不是很重要,LR用发送包的数据发出请求,然后对比发送请求的数据包和脚本里面包存的数据,这里lr只判断数据包大小,而不是具体内容。如果收到的数据包包括“rob”,而server响应是“bob”,lr也会认为脚本运行成功。但如果server回复的是robot”,这样lr就会因为收到包的大小不对而认为脚本执行失败。另一种情况时lr期望收到500bytes大小的包,但是前10秒只收到了100bytes,这时r会认为超时判断脚本运行失败,可以通过lrs_set_recv_timeout 函数来设定超时时间。

    那么反面一种情况是,你不想接受所有的数据包,只是想收到包的前100bytes,可以通过函数ltr_receive_ex 来任意设定想要收到的字节。

    2.增强脚本

    在脚本中添加事务,集合点和控制语句等增强脚本,和web脚本不同的是winsock脚本可读性很差,所以要在录制脚本时添加注释,事务和集合点等。如果在脚本中有逻辑需求,那么插入逻辑语句 (通用声明不适应Winsock_1脚本).

    3.脚本参数化

    把脚本中变化的值参数化,只要用参数把这些值替换掉就可以,使用不同参数重复业务流程,例如在上面的例子里面jojo/bean就可以参数化成为userIDs/passwords

    4.关联脚本

    关联目的是为了让你在一个并发中用到一个商业流程的结果,在web脚本中有这样的过程,从web脚本中sessionid关系到后面的流程能不能运行,winsock脚本有同样的问题。所以需要捕获到session id然后把它关联起来,举个例子从下面的脚本中获取PID(lr函数的例子):

    “\r”

    “\x0 blah blah blah “

    “\r\n blah blah blah “

    “PID TT STAT TIME COMMAND\r\n PID 28469 q2″

    ” S 0:01 -tcsh (tcsh)\r\n”

    在一个典型的web脚本中,你用web_create_html_param函数,用“PID“ 和“q2”定义边界扑获数据。

    在Winsock脚本中,用lrs_save_param函数从静态数据或收到的数据包中截获数据,看下面的例子:

    lrs_receive(”socket2″, “buf47″, LrsLastArg);

    lrs_save_param(”socket2″, NULL, “param1″, 67, 5);

    和web_create_html_param函数不同的是lrs_save_param在请求之后进行,这个例子中,第一行代码是接收到47号包。lrs_save_param函数的参数意义如下:

    socket2: 从socket2中扑获数据

    NULL: null参数意思是从最后一个buffer里截取,在这儿就是指buf47,如果你从其它的buf里面来获取数据,则你必须要指明buf的号码了

    param1:命名的参数值

    67:位移(下面截解释)

    5:捕获的长度

    位移:从buffer的开始多少位去捕获参数的值,在下面的例子里面,PID是从buf47开始往后67bytes来截取的,我们怎么确定这个值?

    在data.ws中选取需要截取参数的地方然后按F7键,这样会弹出一个窗体。如下图:

    在左边的列,你将看到符合这部分数据的偏移量,中间四行是用EBCDIC加密的数据包。最右边,是没有经过加密的数据。所以你应该看第五行包含PID的真实的数据,,很容易就可以根据64+3得出位偏移为67。

    (现在我们解释一下问什么添加这些多余的东西到数据包中,让它适合我的例子呢?)

    注意:在socket脚本中没有提供web_find函数。只有通过编程来找到你要截取的脚本。

    5.run-time的设置

    配置Run-Time可以控制脚本运行过程中的虚拟用户行为,包括loop,log和Time信息等设置

    6.VuGen运行脚本.

    保存并用VuGen运行脚本验证脚本是否正确

    搞定WinSock!

  • loadRunner的winsock协议错误编码解析II

    2006-12-07

    1 0 0 4 2—W S A E N O P R O TO O P T

    协议选项错误。表明在g e t s o c k o p t或s e t s o c k o p t调用中,指定的套接字选项或级别不明、未

    获支持或者无效。

    1 0 0 4 3——W S A E P R O TO N O S U P P O RT

    不支持的协议。系统中没有安装请求的协议或没有相应的实施方案。比如,如果系统中

    没有安装T C P / I P,而试着建立T C P或U D P套接字时,就会产生这个错误。

    1 0 0 4 4—W S A E S O C K T N O S U P P O RT

    不支持的套接字类型。对指定的地址家族来说,没有相应的具体套接字类型支持。比如,

    在向一个不支持原始套接字的协议请求建立一个S O C K _ R AW套接字类型时,就会产生这个错

    误。

    1 0 0 4 5—W S A E O P N O T S U P P

    不支持的操作。表明针对指定的对象,试图采取的操作未获支持。通常,如果试着在一

    个不支持调用Wi n s o c k函数的套接字上调用了Wi n s o c k时,就会产生这个错误。比如,在一个

    数据报套接字上调用a c c e p t或W S A A c c e p t函数时,就会产生这样的错误。

    1 0 0 4 6—W S A E P F N O S U P P O RT

    不支持的协议家族。请求的协议家族不存在,或系统内尚未安装。多数情况下,这个错

    误可与W S A E A F N O S U P P O RT互换(两者等价);后者出现得更为频繁。

    1 0 0 4 7—W S A E A F N O S U P P O RT

    地址家族不支持请求的操作。对套接字类型不支持的操作来说,在试着执行它时,就会

    出现这个错误。比如,在类型为S O C K _ S T R E A M的一个套接字上调用s e n d t o或W S A S e n d To函

    数时,就会产生这个错误。另外,在调用s o c k e t或W S A S o c k e t函数的时候,若同时请求了一个

    无效的地址家族、套接字类型及协议组合,也会产生这个错误。 

    1 0 0 4 8—W S A E A D D R I N U S E

    地址正在使用。正常情况下,每个套接字只允许使用一个套接字地址(例如,一个I P套

    接字地址由本地I P地址及端口号组成)。这个错误一般和b i n d、c o n n e c t和W S A C o n n e c t这三个

    函数有关。可在s e t s o c k o p t函数中设置套接字选项S O _ R E U S E A D D R,允许多个套接字访问同

    一个本地I P地址及端口号(详情见第9章)。

    1 0 0 4 9—W S A E A D D R N O TAVA I L

    不能分配请求的地址。A P I调用中指定的地址对那个函数来说无效时,就会产生这样的错

    误。例如,若在b i n d调用中指定一个I P地址,但却没有对应的本地I P接口,便会产生这样的错

    误。另外,通过c o n n e c t、W S A C o n n e c t、s e n d t o、W S A S e n d To和W S A J o i n L e a f这四个函数为

    准备连接的远程计算机指定端口0时,也会产生这样的错误。

    1 0 0 5 0—W S A E N E T D O W N

    网络断开。试图采取一项操作时,却发现网络连接中断。这可能是由于网络堆栈的错误,

    网络接口的故障,或者本地网络的问题造成的。

    1 0 0 5 1—W S A E N E T U N R E A C H

    网络不可抵达。试图采取一项操作时,却发现目标网络不可抵达(不可访问)。这意味着

    本地主机不知道如何抵达一个远程主机。换言之,目前没有已知的路由可抵达那个目标主机。

    1 0 0 5 2—W S A E N E T R E S E T

    网络重设时断开了连接。由于“保持活动”操作检测到一个错误,造成网络连接的中断。

    若在一个已经无效的连接之上,通过s e t s o c k o p t函数设置S O _ K E E PA L I V E选项,也会出现这样

    的错误。

    1 0 0 5 3—W S A E C O N N A B O RT E D

    软件造成连接取消。由于软件错误,造成一个已经建立的连接被取消。典型情况下,这

    意味着连接是由于协议或超时错误而被取消的。

    1 0 0 5 4—W S A E C O N N R E S E T

    连接被对方重设。一个已经建立的连接被远程主机强行关闭。若远程主机上的进程异常

    中止运行(由于内存冲突或硬件故障),或者针对套接字执行了一次强行关闭,便会产生这样

    的错误。针对强行关闭的情况,可用S O _ L I N G E R套接字选项和s e t s o c k o p t来配置一个套接字

    (欲知详情,请参阅第9章)。

    1 0 0 5 5—W S A E N O B U F S

    没有缓冲区空间。由于系统缺少足够的缓冲区空间,请求的操作不能执行。

    1 0 0 5 6—W S A E I S C O N N

    套接字已经连接。表明在一个已建立连接的套接字上,试图再建立一个连接。要注意的

    是,数据报和数据流套接字均有可能出现这样的错误。使用数据报套接字时,假如事先已通

    过c o n n e c t或W S A C o n n e c t调用,为数据报通信关联了一个端点的地址,那么以后试图再次调

    用s e n d t o或W S A S e n d To,便会产生这样的错误。

    1 0 0 5 7—W S A E N O T C O N N

    套接字尚未连接。若在一个尚未建立连接的“面向连接”套接字上发出数据收发请求,

    便会产生这样的错误。

    1 0 0 5 8—W S A E S H U T D O W N

    套接字关闭后不能发送。表明已通过对s h u t d o w n的一次调用,部分关闭了套接字,但事后又请求进行数据的收发操作。要注意的是,这种错误只会在已经关闭的那个数据流动方向

    上才会发生。举个例子来说,完成数据发送后,若调用s h u t d o w n,那么以后任何数据发送调

    用都会产生这样的错误。

    1 0 0 6 0—W S A E T I M E D O U T

    连接超时。若发出了一个连接请求,但经过规定的时间,远程计算机仍未作出正确的响

    应(或根本没有任何响应),便会发生这样的错误。要想收到这样的错误,通常需要先在套接

    字上设置好S O _ S N D T I M E O和S O _ R C V T I M E O选项,然后调用c o n n e c t及W S A C o n n e c t函数。

    要想了解在套接字上设置S O _ S N D T I M E O和S O _ R C V T I M E O选项的详情,可参考第9章。

    1 0 0 6 1—W S A E C O N N R E F U S E D

    连接被拒。由于被目标机器拒绝,连接无法建立。这通常是由于在远程机器上,没有任

    何应用程序可在那个地址之上,为连接提供服务。

    1 0 0 6 4—W S A E H O S T D O W N

    主机关闭。这个错误指出由于目标主机关闭,造成操作失败。然而,应用程序此时更有

    可能收到的是一条W S A E T I M E D O U T(连接超时)错误,因为对方关机的情况通常是在试图

    建立一个连接的时候发生的。1 0 0 6 5—W S A E H O S T U N R E A C H

    没有到主机的路由。应用程序试图访问一个不可抵达的主机。该错误类似于

    W S A E N E T U N R E A C H。

    1 0 0 6 7—W S A E P R O C L I M

    进程过多。有些Wi n s o c k服务提供者对能够同时访问它们的进程数量进行了限制。

    1 0 0 9 1—W S A S Y S N O T R E A D Y

    网络子系统不可用。调用W S A S t a r t u p时,若提供者不能正常工作(由于提供服务的基层

    系统不可用),便会返回这种错误。

    1 0 0 9 2—W S AV E R N O T S U P P O RT E D

    Wi n s o c k . d l l版本有误。表明不支持请求的Wi n s o c k提供者版本。

    1 0 0 9 3—W S A N O T I N I T I A L I S E D

    Wi n s o c k尚未初始化。尚未成功完成对W S A S t a r t u p的一次调用。

    1 0 1 0 1—W S A E D I S C O N

    正在从容关闭。这个错误是由W S A R e c v和W S A R e c v F r o m返回的,指出远程主机已初始

    化了一次从容关闭操作。该错误是在像AT M这样的“面向消息”协议上发生的。

    1 0 1 0 2—W S A E N O M O R E

    找不到更多的记录。这个错误自W S A L o o k u p S e r v i c e N e x t函数返回,指出已经没有留下更

    多的记录。这个错误通常可与W S A _ E _ N O _ M O R E互换使用。在应用程序中,应同时检查这个

    错误以及W S A _ E _ N O _ M O R E。

    1 0 1 0 3—W S A E C A N C E L L E D

    操作被取消。这个错误指出当W S A L o o k u p S e r v i c e N e x t调用仍在处理期间,发出了对

    W S A L o o k u p S e r v i c e E n d(服务中止)的一个调用。此时, W S A L o o k u p S e r v i c e N e x t便会返回这

    个错误。这个错误代码可与W S A _ E _ C A N C E L L E D互换使用。作为应用程序,应同时检查这

    个错误以及W S A _ E _ C A N C E L L E D。

    1 0 1 0 4—W S A E I N VA L I D P R O C TA B L E

    进程调用表无效。该错误通常是在进程表包含了无效条目的情况下,由一个服务提供者

    返回的。欲知服务提供者的详情,可参考第1 4章。

    1 0 1 0 5—W S A E I N VA L I D P R O V I D E R

    无效的服务提供者。这个错误同服务提供者关联在一起,在提供者不能建立正确的

    Wi n s o c k版本,从而无法正常工作的前提下产生。

    1 0 1 0 6—W S A E P R O V I D E R FA I L E D I N I T

    提供者初始化失败。这个错误同服务提供者关联在一起,通常见于提供者不能载入需要

    的D L L时。

    1 0 1 0 7—W S A S Y S C A L L FA I L U R E

    系统调用失败。表明绝对不应失败的一个系统调用却令人遗憾地失败了。

    1 0 1 0 8—W S A S E RV I C E _ N O T _ F O U N D

    找不到这样的服务。这个错误通常与注册和名字解析函数相关,在查询服务时产生(第

    1 0章对这些函数进行了详尽解释)。该错误表明,在给定的名字空间内,找不到请求的服务。

    1 0 1 0 9—W S AT Y P E _ N O T _ F O U N D

    找不到类的类型。该错误也与注册及名字解析函数关联在一起,在处理服务类( S e r v i c e

    C l a s s)时发生。若注册好一个服
  • 冒烟测试与随机测试

    2006-12-08 13:22:56

    软件测试的种类何其多也,每种测试都有其要达到的目的和实现手段。本文将介绍两种不太普遍的测试类型-冒烟测试与随机测试。

    冒烟测试

    冒烟测试(smoke testing),据说是微软起的名字。在《微软项目求生法则》一书第14章“构建过程”关于冒烟测试,就是开发人员在个人版本的软件上执行目前的冒烟测试项目,确定新的程序代码不出故障。

    冒烟测试的名称可以理解为该种测试耗时短,仅用一袋烟功夫足够了。也有人认为是形象地类比新电路板功基本功能检查。任何新电路板焊好后,先通电检查,如果存在设计缺陷,电路板可能会短路,板子冒烟了。

    冒烟测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本功能正常,可以进行后续的正式测试工作。冒烟测试的执行者是版本编译人员。

    在一般软件公司,软件在编写过程中,内部需要编译多个版本(Builds),但是只有有限的几个版本需要执行正式测试(根据项目开发计划),这些需要执行的中间测试版本,在刚刚编译出来后,软件编译人员需要进行基本性能确认测试,例如是否可以正确安装/卸载,主要功能是否实现,是否存在严重死机或数据严重丢失等Bug。如果通过了该测试,则可以根据正式测试文档进行正式测试。否则,就需要重新编译版本,再次执行版本可接收确认测试,直到成功。

    新版本的基本功能确认检查的测试,有的公司成为版本健康检查(Build Sanity Check)。对于编译的本地化软件新版本,除了进行上面提到的各种测试检查,还要检查是否在新的本地化版本中正确包含了全部应该本地化的文件。可以通过采用文件和目录结构比较工具,首先比较源语言版本和本地化版本的文件和目录中的文件数目、文件名称和文件日期等,这个过程称为版本镜像检查(Build Image Check)。其次,分别安装源语言版本和本地化版本,比较安装后的文件和目录结构中的文件数目、文件名称和文件日期等,这个过程称为版本安装检查(Build Installing Check)。

    随机测试

    在软件测试中除了根据测试样例和测试说明书进行测试外,还需要进行随机测试(Ad-hoc testing),主要是根据测试者的经验对软件进行功能和性能抽查。随机测试是根据测试说明书执行样例测试的重要补充手段,是保证测试覆盖完整性的有效方式和过程。

    随机测试主要是对被测软件的一些重要功能进行复测,也包括测试那些当前的测试样例(TestCase)没有覆盖到的部分。另外,对于软件更新和新增加的功能要重点测试。重点对一些特殊点情况点、特殊的使用环境、并发性、进行检查。尤其对以前测试发现的重大Bug,进行再次测试,可以结合回归测试(Regressive testing)一起进行。

    理论上,每一个被测软件版本都需要执行随机测试,尤其对于最后的将要发布的版本更要重视随机测试。随机测试最好由具有丰富测试经验的熟悉被测软件的测试人员进行测试。对于被测试的软件越熟悉,执行随机测试越容易。只有不断的积累测试经验,包括具体的测试执行和对缺陷跟踪记录的分析,不断总结,才能提高。
  • LoadRunner函数介绍

    2006-12-08 11:34:29

    WEB函数列表:

    web_custom_request
    允许您使用 HTTP 支持的任何方法来创建自定义 HTTP 请求

    web_image
    在定义的图像上模拟鼠标单击

    web_link
    在定义的文本链接上模拟鼠标单击

    web_submit_data
    执行“无条件”或“无上下文”的表单

    web_submit_form
    模拟表单的提交

    web_url
    加载由“URL”属性指定的 URL

    web_set_certificate
    使 Vuser 使用在 Internet Explorer 注册表中列出的特定证书

    web_set_certificate_ex
    指定证书和密钥文件的位置和格式信息

    web_set_user
    指定 Web 服务器的登录字符串和密码,用于 Web 服务器上已验证用户身份的区域

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

    web_find
    在 HTML 页内搜索指定的文本字符串

    web_global_verification
    在所有后面的 HTTP 请求中搜索文本字符串

    web_image_check
    验证指定的图像是否存在于 HTML页内

    web_reg_find
    在后面的 HTTP 请求中注册对 HTML源或原始缓冲区中文本字符串的搜索

    web_disable_keep_alive
    禁用 Keep-Alive HTTP 连接

    web_enable_keep_alive
    启用 Keep-Alive HTTP 连接

    web_set_connections_limit
    设置 Vuser 在运行脚本时可以同时打开连接的最大数目

    web_concurrent_end
    标记并发组的结束

    web_concurrent_start
    标记并发组的开始

    web_add_cookie
    添加新的 Cookie 或修改现有的 Cookie

    web_cleanup_cookies
    删除当前由 Vuser 存储的所有 Cookie

    web_remove_cookie
    删除指定的 Cookie

    web_create_html_param
    将 HTML 页上的动态信息保存到参数中。(LR 6.5 及更低版本)

    web_create_html_param_ex
    基于包含在 HTML 页内的动态信息创建参数(使用嵌入边界)(LR 6.5 及更低版本)。

    web_reg_save_param
    基于包含在 HTML 页内的动态信息创建参数(不使用嵌入边界)

    web_set_max_html_param_len
    设置已检索的动态 HTML 信息的最大长度

    web_add_filter
    设置在下载时包括或排除 URL 的条件

    web_add_auto_filter
    设置在下载时包括或排除 URL 的条件

    web_remove_auto_filter
    禁用对下载内容的筛选

    web_add_auto_header
    向所有后面的 HTTP 请求中添加自定义标头

    web_add_header
    向下一个 HTTP 请求中添加自定义标头

    web_cleanup_auto_headers
    停止向后面的 HTTP 请求中添加自定义标头

    web_remove_auto_header
    停止向后面的 HTTP 请求中添加特定的标头

    web_revert_auto_header
    停止向后面的 HTTP 请求中添加特定的标头,但是生成隐性标头

    web_save_header
    将请求和响应标头保存到变量中

    web_set_proxy
    指定将所有后面的 HTTP 请求定向到指定的代理服务器

    web_set_proxy_bypass
    指定 Vuser 直接访问(即不通过指定的代理服务器访问)的服务器列表

    web_set_proxy_bypass_local
    指定 Vuser 对于本地 (Intranet) 地址是否应该避开代理服务器

    web_set_secure_proxy
    指定将所有后面的 HTTP 请求定向到服务器

    web_set_max_retries
    设置操作步骤的最大重试次数

    web_set_timeout
    指定 Vuser 等待执行指定任务的最长时间

    web_convert_param
    将 HTML 参数转换成 URL 或纯文本

    web_get_int_property
    返回有关上一个 HTTP 请求的特定信息

    web_report_data_point
    指定数据点并将其添加到测试结果中

    web_set_option
    在非 HTML 资源的编码、重定向和下载区域中设置 Web 选项

    web_set_sockets_option
    设置套接字的选项

我的存档

数据统计

  • 访问量: 6448
  • 日志数: 5
  • 图片数: 2
  • 建立时间: 2006-12-08
  • 更新时间: 2006-12-08

RSS订阅

Open Toolbar