发布新日志

  • 软件可靠性测试及其实践

    2008-04-30 11:12:13

        软件可靠性工程是指为了满足软件的可靠性要求而进行的一系列设计、分析、测试工作。其中确定软件可靠性要求是软件可靠性工程中要解决的首要问题。软件可靠性要求可以包括定性定及量要求。

      软件可靠性测试是在软件生存周期的系统测试阶段提高软件可靠性水平的有效途径。各种测试方法、测试技术都能发现导致软件失效的软件中残存的缺陷,排除这些缺陷后,一般来讲一定会实现软件可靠性的增长,但是排除这些缺陷对可靠性的提高的作用却是不一样的。其中,软件可靠性测试能最有效地发现对可靠性影响大的缺陷,因此可以有效地提高软件的可靠性水平。

      软件可靠性测试也是评估软件可靠性水平,验证软件产品是否达到软件可靠性要求的重要且有效的途径。

      1 软件可靠性测试概念

      “测试”一般是指“为了发现程序中的错误而执行程序的过程”。但是在不同的开发阶段、对于不同的人员,测试的意义、目的及其采用的方法是有差别的。在软件开发的测试阶段,测试的主要目的是开发人员通过运行程序来发现程序中存在的缺陷、错误。而在产品交付、验收阶段,测试主要用来验证软件产品是否达到用户的要求。或者说,对于开发人员,测试是发现缺陷的一种途径、手段,而对于用户,测试则是验收产品的一种手段。根据测试用例选取原则的不同,测试可分为黑盒测试方法和白盒测试方法两大类。黑盒测试方法是指按照软件需求生成测试用例对软件进行测试的方法,黑盒测试不关心程序是如何实现的;而白盒测试方法则是指根据程序的结构生成测试用例对软件进行测试的方法。

      软件可靠性测试是指为了保证和验证软件的可靠性要求而对软件进行的测试。其采用的是按照软件运行剖面(对软件实际使用情况的统计规律的描述)对软件进行随机测试的测试方法。通过软件可靠性测试可以达到以下目的:

      (1) 有效地发现程序中影响软件可靠性的缺陷,从而实现可靠性增长:软件可靠性是指“在规定的时间内,规定的条件下,软件不引起系统失效的能力,其概率度量称为软件可靠度。”软件的“规定的条件”主要包括相对不变的条件和相对变化的条件,相对不变的条件如计算机及其操作系统;相对变化的条件是指输入的分布,用软件的运行剖面来描述。按照软件的运行剖面对软件进行测试一般先暴露在使用中发生概率高的缺陷,然后是发生概率低的缺陷。而高发生概率的缺陷是影响产品可靠性的主要缺陷,通过排除这些缺陷可以有效地实现软件可靠性的增长。

      (2) 验证软件可靠性满足一定的要求:通过对软件可靠性测试中观测到的失效情况进行分析,可以验证软件可靠性的定量要求是否得到满足。

      (3) 估计、预计软件可靠性水平:通过对软件可靠性测试中观测到的失效数据进行分析,可以评估当前软件可靠性的水平,预测未来可能达到的水平,从而为开发管理提供决策依据。软件可靠性测试中暴露的缺陷既可以是影响功能需求的缺陷也可以是影响性能需求的缺陷。软件可靠性测试方法从概念上讲是一种黑盒测试方法,因为它是面向需求、面向使用的测试,它不需要了解程序的结构以及如何实现等问题。

      软件可靠性测试通常是在系统测试、验收、交付阶段进行,它主要是在实验室内仿真环境下进行,也可以根据需要和可能在用户现场进行。

      2 软件可靠性测试过程

      2.1 软件可靠性测试活动

      软件可靠性测试的一般过程如图1所示。主要活动包括:测试数据、测试环境的准备,测试运行,可靠性数据收集,可靠性数据分析和失效纠正。

      (1) 构造运行剖面:软件的运行剖面“是指对系统使用条件的定义。即系统的输入值用其按时间的分布或按它们在可能输入范围内的出现概率的分布来定义”。粗略地说,运行剖面是用来描述软件的实际使用情况的。运行剖面是否能代表、刻画软件的实际使用取决于可靠性工程人员对软件的系统模式、功能、任务需求及相应的输入激励的分析,取决于他们对用户使用这些系统模式、功能、任务的概率的了解。运行剖面构造的质量将对测试、分析的结果是否可信产生最直接的影响。

      (2) 选取测试用例:软件可靠性测试采用的是按照运行剖面对软件进行可靠性测试的方法。因此,可靠性测试所用的测试用例是根据运行剖面随机选取得到的。

  • QALoad优秀的性能测试工具

    2008-03-04 09:24:19

     

        QALoad是客户/服务器系统、企业资源配置(ERP)和电子商务应用的自动化负载测试工具。
    QALoad是QACenter性能版的一部分,它通过可重复的、真实的测试能够彻底地度量应用的可扩展性和性能。QACenter汇集完整的跨企业的自动测试产品,专为提高软件质量而设计。QACenter可以在整个开发生命周期、跨越多种平台、自动执行测试任务。

      在投产准备时期,QALoad可以模拟成百上千的用户并发执行关键业务而完成对应用程序的测试,并针对所发现问题对系统性能进行优化,确保应用的成功部署。

      预测系统性能
      当应用升级或者新应用部署时,负载测试能帮助确定系统是否能按计划处理用户负载。QALoad并不需调用最终用户及其设备,它能够仿真数以千计的用户进行商业交易。通过QALoad,用户可以预知业务量接近投产后真实水平时,端对端的响应时间,以便满足投产后的服务水平要求。

      通过重复测试寻找瓶颈问题
      QALoad录制/回放能力提供了一种可重复的方法来验证负载下的应用性能,可以很容易地模拟数千个用户,并执行和运行测试。利用QALoad反复测试可以充分地测试与容量相关的问题,快速确认性能瓶颈并进行优化和调整。

      从控制中心管理全局负载测试
      QALoad Conductor工具为定义、管理和执行负载测试提供了一个中心控制点。Conductor通过执行测试脚本,管理无数的虚拟用户。Conductor可以自动识别网络中可进行负载测试的机器,并在这些机器之间自动分布工作量,以避免网段超载。从Conductor自动启动和配置远程用户,跨国机构可以进行全球负载测试。在测试过程中,Conductor还可以在负载测试期间收集有关性能和时间的统计数据。

      验证应用的可扩展性
      出于高可扩展性的设计考虑,QALoad包括了远程存储虚拟用户响应时间并在测试结束后或其他特定时间下载这些资料的功能。这种方法可以增加测试能力,减少进行大型负载测试时的网络资源耗费。QALoad采用轮询法采集响应时间,在无需影响测试或增加测试投资的条件下,就可了解测试中究竟出现了什么情况。

      在利用QALoad进行测试时,可以有选择地改变硬件或软件的配置,并改变测试步调和负载量。QALoad系统的NetLoad 模块帮助建立所需的额外网络流量来模拟真实的产品负载。借助于“NetLoad”,可以在大环境下分配虚拟用户,更好地规划投产环境中如何让这些应用更好地工作。

      6-3QALoad 引入了"flash"为电子商务应用软件作容量测试。flash测试允许在测试期间增加大量的虚拟用户,来确定压力对底层部件和基础结构的影响。flash测试也可以证明应用投产后其响应时间将不会降低至服务级以下。

      快速创建仿真的负载测试
      准确仿真复杂业务的进行,对于预测电子商务应用软件的功能至关重要。运用QA Load,可以迅速创造出一些实际的安装测试方案,而不需要手工编写脚本或有关应用中间软件的详细知识和和协议。

      对结合了多种传输协议的应用软件进行负载测试是一个巨大的挑战。为了准确仿真这些应用软件产生的流量,QALoad可以捕获多种协议并在同一测试过程中执行它们。基于浏览器的应用经常打开与服务器的多个连接以缩短网页下载时间,导致服务器的额外流量。QALoad能准确地仿真除浏览器与服务器之间的交互,包括多重联结,使负载更加准确。

      另外,这些应用软件常常包含一些在测试方案中必须申明的动态信息。运用QALoad的ActiveData特征,可以定义脚本参数以帮助确保应用测试脚本的成功执行。

      例如,对一些安全或非安全的web应用软件,ActiveData自动转化为动态信息,如cookies;包括动态Active Serve Page cookies、动态URL名称、服务器导向、动态框架或者其它时期的特定信息。ActiveData for web有助于保证测试脚本与Web应用在测试过程中保持同步。
    ActiveData每次自动查找和提出需要的变更建议,使测试脚本正确执行。在脚本执行过程中,脚本中的信息可以被产生的正确信息自动替代。

  • 用webload进行web application性能测试

    2008-01-24 16:19:14

    一、webload是什么?
    webload是RadView公司推出的一个性能测试和分析工具,它让web应用程序开发者自动执行压力测试;webload通过模拟真实用户的操作,生成压力负载来测试web的性能
    用户创建的是基于java scrīpt的测试脚本,称为议程agenda,用它来模拟客户的行为,通过执行该脚本来衡量web应用程序在真实环境下的性能
    当前最高版本是6.0
    webload提供巡航控制器cruise control的功能,利用巡航控制器,可以预定义web应用程序应该满足的性能指标,然后测试系统是否满足这些需求指标;cruise control能够自动把负载加到web应用程序,并将在此负荷下能够访问程序的客户数量生成报告
    webload能够在测试会话执行期间对监测的系统性能生成实时的报告,这些测试结果通过一个易读的图形界面显示出来,并可以导出到excel和其他文件里

     

    二、webload结构


      
    三、Webload6.0安装
    下载地址:
    http://www.radview.com/

    四、Webload的通信设置
    配置SNMP协议使多个压力机之间互相通信:
    在win2000里进入[控制面板]->[添加删除程序]->[添加删除windows组件]
    选择[管理和监控工具],[下一步]后选择windows安装文件路径,[完成]
    TestTalk:
    TestTalk在测试会话里监测压力机间的信息传递,如果通信不成功则报错
    TestTalk自动安装,测试执行时在后台自动运行,注意不要将它关闭

    五、Webload程序组成
    Agenda Authoring Tool for Explorer (SSL)
    Visual AAT
    WebLOAD Console
    WebLOAD REPORTER
    Tools:TestTalk 和Performance Measurements Manager 等

    六、Webload性能测试工作流
    计划一个压力会话load session
    创建测试议程agenda
    创建压力模板load templates
    运行压力模板load templates
    输入测试报告并分析测试结果

    七、如何计划一个压力会话load session
    what application are you going to test?
    What functionality do you want to test — what actions will the users perform?
    How many Virtual Clients you want to simulate?
    How long your test will run?
    What are acceptable results? Acceptable results are defined by your test objective. For example,you can verify:
    Acceptable user response times
    Reliability by running stress tests
    Performance degradation after updates
    What resources are required for performing the test?

    八、创建测试议程agenda

    用WebLoad Visual AAT创建测试议程agenda:
    打开Visual Agenda Authoring Tool
    选择[Create a new project],并[确定]


     
    创建测试议程agenda
    设置清除浏览器的cache和cookie:
    选择[tools]->[default project options]->[IE playback settings]
    选择[clear cache]和[clear cookie]
    点击[ok]
    目的:防止记录脚本时将IE的相关信息保存到cache或cookie里引起不必要的麻烦.

    创建测试议程agenda
    点击[start record]按钮,弹出提示,点击ok
    自动打开一个IE,手工输入要测试的地址,进入系统
    在测试系统里完成一系列操作
    点击[stop record]停止录制,一个agenda脚本创建完毕;保存脚本

    九、创建压力模板load templates
    用WebLOAD Console创建load templates-将一系列压力事件定义到一个压力会话load session里:
    1)用webload wizard创建一个简单的压力模板
    2)用Cruise Control Wizard创建一个预期性能参数的压力测试模板
    3)用webload console手工创建压力模板
    说明:打开webload console时提示选择用哪个方式

    十、用webload wizard创建压力模板

    之前的准备工作,需要定义:
    运行的Agenda(s)
    用来生成负载的压力机
    虚拟客户端的个数
    压力测试进度表(用webRM创建)
    另外,还可以设置agenda选项,比如模拟浏览器的类型、连接速度、回放休眠时间等选项。
    用webload wizard创建压力模板
    进入webload console,选择该种方式创建压力模板:


     

    选择一个agenda或者混合型:
    lSingle Agendas:创建只有一个agenda脚本的压力模板
    lMix of Agendas:多个agenda脚本,模拟用户不同活动


     

    选择single agenda:


     

    选择Mix方式:可选择一个已有的mix文件,也可新建一个mix。


     
    选择新建一个mix时:



    上述三种方式【下一步】后,到达选择主机窗口:


     

    压力会话的进度设置:有两种设置方式,一个是手工分配每个压力机的压力;另一个是自动均匀分配每个压力机的压力。


     
    手工分配每个压力机的压力:


     
    Load profiler设置:共有八种进度模型,详细参照附录一


     
    自动均匀分配每个压力机的压力:可手工添加、删除、复制来设置进度;也可通过load profiler来设置,具体操作同手工分配压力的方式。

     

    【下一步】点击后,可立即执行测试,也可不立刻执行,点击【完成】;对于创建完的压力模板,可以:
    编辑压力模板
    通过菜单【reports】-【integrated report】-【new report】来查看webload默认生成的报告
    通过菜单【session control】-【modify host selection】来修改主机设置
    通过菜单【session control】-【modify schedule】修改压力进度表


    十一、创建一个预期性能参数的压力测试模板
    很多时候,我们不知道应用系统到底要多少用户访问;但是我们知道系统的性能应该满足什么样的指标是合适的;例如希望应用服务器的响应时间不超过3秒,webload会得到该目标下的最佳性能状况。
    打开webload console,选择用cruise control wizard创建模板:


     
    进入选择single agenda或mix方式添加脚本,之后选择压力机和探测客户机,这些操作和前一种方式相同;然后进入测试目标定义窗口:


     
    点击【add goal】按钮弹出所有可以添加的测量参数:


     
    添加一个或多个测量参数:


     
    为了达到测量参数目标,设置每次增加虚拟用户的速度:


     
    定义当测量目标参数达到时webload状态:


     
    点击【完成并运行】按钮,开始运行压力模板,并得到实时跟踪的测试结果:


     
    十二、手工创建压力模板
    打开webload console首页,选择【create a new template manually】,开始手工创建压力模板;该种方式的工作流如下,具体操作同前,这里不赘述:


     
    十三、运行压力模板load templates
    每种方式创建的压力模板都可以自动运行,也可以保存起来,或修改之后,通过如下方式运行:
    在webload console菜单栏里选择【session control】-【start session】
    在webload console工具栏里选择start session按钮


    十四、输出测试报告并分析测试结果
    实时查看测试结果:
    在chat view页面右键单击任何一个点查看实际值
    点击工具栏【dashboard】按钮查看整个测试中的关键参数
    点击工具栏【openstatistics】按钮统计整个测试中的详细参数,点击某个参数值可查看更详细信息
    点击工具栏【data drilling】按钮查看每个被测web页面的传输性能参数,点击可查看更详细信息


    创建集成报告:
    选择菜单栏【report】-【integrated report】-【new report】
    点击【rename】创建新的报告
    从参数树里选择本次测试中,想要生成报告的选项
    点击【ok】,报告显示出来

    用webload reporter分析测试结果
    打开webload reporter
    在这里,有整个测试过程中想要的各个分析工具,点击任何一个即动态生成该类型的报告,已做分析
    点击菜单栏【publish】,可以从中选择将生成的报告以其他方式导出
    关闭webload reporter
    Webload reporter界面


     
    十五、性能测量管理器PMM介绍
    Webload通过Performance Measurements Manager (PMM)
    来检测服务器端的性能,webload通过收集服务器端的有效数据,提供一个完全图形化的web应用程序的性能报告;用PMM,我们可以监测服务器的:
    Application Server Resources
    Database Resources
    System Resources
    Web Server Resources
    Stream Technology Resources
    Other Resources

    十六、性能测量管理器PMM操作
    三种方式打开PMM:
    在webload console菜单里【Session Control】-【Performance Measurements Manager】
    在开始菜单里Start | Programs | WebLOAD 6.0 | Tools |Performance Measurements Manager
    一般我们在创建load templates时,会有一个按钮进入PMM界面,我们重点介绍这种方法的操作

    PMM主界面:点击【add data source】


     
    开始选择数据源,选择数据源的主机:



    如果连接成功,会显示如下的数据源参数,在此选择我们想要测试的参数,点击【完成】:



    然后自动跳回PMM主界面,在此会看见如下的数据源参数代码,点击主界面的【close and update】,这些数据源参数会在load templates完成后自动出现在报告里:


     
    Webload的PMM在设置weblogic、iplanet、oracle等服务器的测量参数前,都要在该服务器端进行一定的设置,使其成为SNMP的代理服务器;具体设置步骤见用户手册372页。
    附录loader profile进度模型参数讲解
    1.Linear:
    Total time in minutes — 压力测试总时间(分)
    Starting Load Size — 初始压力个数
    Concluding Load Size — 结束时压力大小
    2. Random:
    Min. Load Size —最小压力大小
    Max. Load Size — 最大压力大小
    附录loader profile进度模型参数讲解
    Incrementing Intervals:
    Base Load Size — 初始压力大小(方波最小值)
    Time Between Each Interval-T1 — 加压持续的时间
    Time of Each Interval-T2-间隔时间
    Load to Increase Each Interval-每次加压加的压力个数
    Incrementing Intervals (time calculate):同上
    附录loader profile进度模型参数讲解
    Step Increments:Time of each Interval — 每次间隔的时间
    Load to increase each interval — 每个间隔增加的压力个数
    Ramp Up:
    Max Load Size — 最大压力数
    Ramp UpTime — 为了到达最大压力持续的增加时间
    Time to Run Max Load Size — 在最大压力时运行的时间
    Ramp Down Time — 从最大压力降到最小过程持续的时间
  • 运用LOADRUNNER .NET ADD-IN 写的性能测试脚本

    2007-12-20 15:30:53

    运用LOADRUNNER .NET ADD-IN 写的性能测试脚本

    运用LOADRUNNER .NET ADD-IN 写的性能测试脚本 using System;
    using System.Runtime.InteropServices;
    using System.Data.OleDb;
    using System.Data;
    namespace LoadRunnerUser1
    {
    /// <summary>
    /// Summary descrīption for VuserClass.
    /// </summary>
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class VuserClass
    {
      LoadRunner.LrApi lr;
      public VuserClass()
      {
       // LoadRunner Standard API Interface ::     DO NOT REMOVE!!!
       lr = new LoadRunner.LrApi();
       
      }
      // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      public int Initialize()
      {
       // TO DO: Add virtual user's initialization routines
       lr.message("Initialize部分,我只执行一次哦!");
       return lr.PASS;
      }
      // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      public int Actions()
      {
       // TO DO: Add virtual user's business process actions
       lr.message("Actions部分,我可以重复执行(在设置迭代情况下)!");
       try
       {
        //设置连接字符串开始
        string strC;
        [email=strConnection+=@]strConnection+=@"Data[/email] Source=C:\\test.mdb";
        //设置连接字符串结束
        //插入一个集合点开始
        lr.rendezvous("集合点");
        //插入一个集合点结束
        //事务开始
        lr.start_transaction("SQL语句性能");
        //建立OleDbConnection和OleDbCommand,并指定要运行的Sql语句开始
        System.Data.OleDb.OleDbConnection  conn=new
            System.Data.OleDb.OleDbConnection(strConnection);
        System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand();
        cmd.Connection = conn;   
        cmd.CommandText = "select * from testdb";
        //建立OleDbConnection和OleDbCommand,并指定要运行的Sql语句结束
        //插入一个日志开始
        lr.log_message("LOG: Sql语句开始执行了,Sql="+cmd.CommandText);
        //插入一个日志结束
        //将查询结果填充到DataTable开始
        DataTable dt = new DataTable();
       
        System.Data.OleDb.OleDbDataAdapter ōleDA = new
            System.Data.OleDb.OleDbDataAdapter();
        oleDA.SelectCommand = cmd;
        oleDA.Fill(dt);
        //将查询结果填充到DataTable结束
        //插入一个日志开始
        lr.log_message("LOG: Sql语句执行完成,Sql="+cmd.CommandText);
        //插入一个日志结束
        //取得结果集的记录数
        int iCountRec=Convert.ToInt32(dt.Rows.Count.ToString());
        conn.Close();//关闭连接
        //如果记录数大于0,完整这个事务,否则标识事务失败
        if(iCountRec>0)
         lr.end_transaction("SQL语句性能",lr.PASS);
        else
         lr.end_transaction("SQL语句性能",lr.FAIL);
        //再来一个参数化的示例开始
         lr.output_message("Welcome "+lr.eval_string("<username>")+"!");
        //再来一个参数化的示例结束
        //Thinktime 的应用,就是模拟手工操作的延时,在这里我们延时3秒钟
          lr.think_time(3);
       }
       catch(Exception ex)
       {
        conn.Close();//关闭连接
        string error = ex.Message;
       }
       return lr.PASS;
      }
      // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      public int Terminate()
      {
       // TO DO: Add virtual user's termination routines
       lr.message("Terminate部分,我只执行一次哦!");
       return lr.PASS;
      }
    }
    }

  • LR高级技巧实战

    2007-12-07 18:03:17

     

    1.概述
            在山东BOSS性能压力 测试 过程中,发现脚本对于整个压力测试过程的重要性,一个压力测试脚本录制和编辑修改得怎么样直接影响后面压力测试的执行。通常情况下,脚本应尽可能的精简,就像写代码一样。针对BOSS系统的特点, 个人 认为把单一业务录制成一个Action,并在脚本中添加Transaction,Find检查(可以采用URL-based scrīpt 方式录制并事先设定),Rendezvous,参数化等基本元素,然而有时我们会发现光有这些基本元素还不能满足我们的要求。比如在Controller中运行我们的脚本时,一旦压力过大或某种原因导致某一业务失败,而此时我们很想尽快地找出错误的原因。当然此时我们第一想到的是,查找 日志 ,但是有时发现查找日志很不方便,因此我们希望寻求一种更快捷的方式,希望能直接从Controller的Errors错误中找到出错的服务号码、在第几次Iteration的哪个Transaction出错。实现的方式,当然是通过简单的编程来调用错误日志里的信息,另外本文中还简单介绍了关于 LoadRunner 工具使用的一些常用注意事项、脚本处理技巧和一些常用性能参数的分析及 性能测试 中机器瓶颈的定义和查看机器瓶颈的相关命令。
            下面再具体的一一介绍。

    2.一个规范的性能测试脚本就像一段规范的程序代码一样,需要基本的说明信息:
    在下面要介绍的脚本中,我把这些信息以注释的形式放在vuser_init最前面:
    /*
    @corporation:Copyright By *** Technologies CO.,LTD. All Rights Reserved.
    @Athour:XuLinLin
    @Date:2005-09-18
    @Name:异地缴费压力测试脚本
    @Parameter:BOSSURL,LogName,PhoneNum,iteration,FanHui
    @Data:BOSSURL:BOSSURL.dat; //由于BOSS压力测试前台展现环境多,故将地址也参数化。
    LogName:LogName.dat; //登录用操作员,选择具备异地缴费权限的操作员,这里选择的是德州操作员300个。
    PhoneNum:PhoneNum.dat; //用于异地缴费的服务号码,这里选择的是烟台的正常在用的标准全球通号码3000个。
    iteration:iteration.dat; //用于压力测试出错时,打印出错所在的循环次数。
    @Descrīption:此脚本用于测试异地缴费的性能及稳定性,选用德州的操作员对烟台的标准全球通号码进行异地缴费,目标是
    通过vuser模仿真实操作员进行异地缴费,达到验证或测试系统性能和稳定性的目的。
    @Notes:脚本的录制使用的是LoadRunner8.0的VU,采用的是URL-based scrīpt方式,需要特别注意的是Recording Options(按Ctrl+F7)
    的Advanced 选项里的Surport Charset一般情况默认为不选,除非字符集合采用的是国际标准才选中UTF-8选项,否则会出现汉字乱码现象。
    */

    3.通常情况下,任何业务必须在登陆成功后才能做,所以有必要对登陆成功与否进行判断:
    下面我从脚本中取出相关部分进行简单介绍:
    vuser_init()
    {
    int status; //定义变量用于判断登陆是否成功
    web_reg_find("Text="山东移动BOSS"",
    LAST);
    …….
    …….
    web_submit_data("reguserAction.do", //登陆提交数据Action。
    "Action="http://{BOSSURL}/boss/reguserAction.do"",
    "Method="POST"",
    "RecContentType="text/html"",
    "Referer="http://{BOSSURL}/boss/index.jsp"",
    "Snapshot="t12.inf"",
    "Mode="HTTP"",
    ITEMDATA,
    "Name="logname"", "Value="{LogName}"", ENDITEM,
    "Name="password"", "Value=", ENDITEM,
    LAST);
    status = web_submit_data("reguserAction.do", // 取成功与否标志
    "Action="http://{BOSSURL}/boss/reguserAction.do"",
    "Method="POST"",
    "RecContentType="text/html"",
    "Referer="http://{BOSSURL}/boss/index.jsp"",
    "Snapshot="t12.inf"",
    "Mode="HTTP"",
    ITEMDATA,
    "Name="logname"", "Value="{LogName}"", ENDITEM,
    "Name="password"", "Value=", ENDITEM,
    LAST);

    if (status ="=" LR_FAIL) //一旦登陆失败,脚本给出提示报错信息。
    {
    lr_error_message("错误信息: %s", "不能正常登陆!");
    return -1;
    }
    }

    4.事务的定义,很简单,也很有必要,尽量是每个定义的事物符合逻辑和小。
    在下面的脚本中,在异地缴费这一业务中定义了两个Transaction:准备异地缴费数据和提交异地缴费,见如下脚本代码:
    lr_start_transaction("准备异地缴费数据");


    web_set_max_html_param_len("4096");
    ……….
    web_submit_data("chargeacc.do",
    "Action="http://{BOSSURL}/boss/charge/commonbusiness/acccharge/chargeacc.do?act=queryaccount"",
    "Method="POST"",
    "RecContentType="text/html"",
    "Referer="http://{BOSSURL}/boss/charge/commonbusiness/acccharge/acccharge.jsp?act=first"",
    "Snapshot="t74.inf"",
    "Mode="HTTP"",
    ITEMDATA,
    "Name="isconfirm"", "Value="no"", ENDITEM,
    "Name="chargetype"", "Value="telnumber"", ENDITEM,
    "Name="telnumber"", "Value="{PhoneNum}"", ENDITEM,
    "Name="nowfee"", "Value="0.0"", ENDITEM,
    "Name="factfee"", "Value=", ENDITEM,
    "Name="totalfee"", "Value="0.0"", ENDITEM,
    LAST);
    lr_end_transaction("准备异地缴费数据", LR_AUTO);

    5.增强脚本,对脚本进行简单的编程。
    增强脚本,对脚本进行简单的编程,为性能或压力测试提供方便,这也是写
    本文的宗旨,下面对此做简单的介绍:
            5.1首先,定义成功与否的判断标志或字符串。
            在此,我把判断成功与否的标志定义在异地缴费Action 最前面,具体定义如下:char fanhuiflag[30]="操作业务数据成功!";
    但是大家可能会问,字符串"操作业务数据成功!"从何处而来,可以肯定的不能凭空想象,成功标志可从两三种方式来取得:
    第一种:也是最简单的一种,直接从脚本中取得,具体操作是以View Tree 方式找到相关的界面,然后从Server Response的Snapshot的Body里去取。见下面的 图片
    注:Snapshot在录制前要将Recording Options>Advanced里的Save snapshot resources locally 选项选中。

     


            第二种方式,从脚本代码中去取,即取find函数中相关字符串,具体做法是,找到在提交事件前的web_reg_find函数,然后从中取相关字符串。
    web_reg_find("Text="---------操作业务数据成功!--------"",
    LAST);
    值得注意的是要有web_reg_find函数,可以在录制前选中Recording Options>Advanced里的Generate web_reg_find functions for page titles 选项。


            第三种方式,从本地的snapshot里去取,具体操作,首先找到提交数据事件相关脚本,找到snapshot文件的名称,然后从本地的data文件里去找这个snapshot文件,然后丛中找到我们需要的字符串。
    web_reg_find("Text="---------操作业务数据成功!--------"",
    LAST);
    …….
    web_submit_data("chargeacc.do_3",
    "Action="http://{BOSSURL}/boss/charge/commonbusiness/acccharge/chargeacc.do?act=submit&atype=commitdata"",
    "Method="POST"",
    "RecContentType="text/html"",
    "Referer="http://{BOSSURL}/boss/charge/commonbusiness/acccharge/chargeacc.do?act=querycustomer"",
    "Snapshot="t129.inf"",
    "Mode="HTTP"",
    ITEMDATA,
    "Name="isconfirm"", "Value="no"", ENDITEM,
    "Name="chargetype"", "Value="telnumber"", ENDITEM,
    "Name="telnumber"", "Value=", ENDITEM,
    "Name="nowfee"", "Value="8.8"", ENDITEM,
    "Name="factfee"", "Value="0.00"", ENDITEM,
    "Name="totalfee"", "Value="8.8"", ENDITEM,
    "Name="accountno"", "Value="{WCSParam_Diff1}"", ENDITEM,
    "Name="factpay"", "Value="8.8"", ENDITEM,
    "Name="grantpercent"", "Value=", ENDITEM,
    "Name="grantfee"", "Value="0"", ENDITEM,
    "Name="takecash"", "Value="8.8"", ENDITEM,
    "Name="zero"", "Value="0"", ENDITEM,
    "Name="paytype"", "Value="Cash"", ENDITEM,
    "Name="remark"", "Value=", ENDITEM,
    "Name="invoice"", "Value="joininvoice"", ENDITEM,
    LAST);

            5.2设置和保存判断成功与否的参数,这也是最关键的地方。
    有一点大家都很清楚,业务成功返回的字符串和失败返回的字符串是不同的,我们所要做的是将返回的字符串做为参数保存下来,然后拿这个参数和我们事先定义好的成功的标志做比较,有两种方式可以设置和保存这一参数,下面简单介绍:
    第一种方式也是最准确的方式,是以View Tree 方式找到相关的界面,然后从Server Response的Snapshot的Body里的成功的返回标志,然后对其进行Create Parameter,这样LoadRunner会自动在脚本中添加web_reg_save_param函数,具体如下:
    // [WCSPARAM WCSParam_Text2 24 操作业务数据成功!_Text2] Parameter {WCSParam_Text2} created by Correlation Studio
    web_reg_save_param("WCSParam_Text2",
    "LB="---------"",
    "RB="-"",
    "Ord="1"",
    "RelFrameId="1"",
    "Search="Body"",
    LAST);

     

            第二种方式是在提交事件前添加web_reg_save_param函数,具体操作是在提交事件前右击鼠标选择Insert Before 选项,然后在弹出的对话框中选择Services里的web_reg_save_param选项,单击OK按纽,然后在弹出的对话框中输入相关的数据。

     


            5.3 编写相关判断代码段。
            在已经定义好判断字符串和设置和保存好成功与否的标志字符串参数后,编写相关判断代码段,这也是最关键的地方,具体代码段如下:
    if (strcmp(fanhuiflag,lr_eval_string("{WCSParam_Text2}"))!="0)
    {
    lr_error_message("消息: %s,在第 %s 次循环时出错,出错号码:%s", "提交异地缴费数据失败!", lr_eval_string("{iteration}"), lr_eval_string("{PhoneNum}"));
    }
    简单解释如下:
    fanhuiflag:前面已经定义好的成功标志字符串的数组名,当然前面也可以用指针来实现,这里不做介绍。
    WCSParam_Text2:为实现设置和保存好的成功与否返回的字符串的参数;
    PhoneNum:服务号码的参数化,具体为电话号码。关于参数化,这里不做分析和解释部分。
    Iteration:为了定位具体的循环而设置的参数。
    Strcmp函数:LoadRunner自带的字符串比较函数,相等时返回0
    lr_eval_string函数:LoadRunner自带求字符串函数,函数格式为
    char * lr_eval_string (const char * instring );
    (另一种判断方式:先事先定义好int rc="1;" char *fanhuiflag="操作业务数据成功!";然后在定义事务的结尾进行判断: rc="strcmp(str_tip,lr_eval_string(""{re_str_tip}"));
    if(rc="=0)"
    {
    lr_end_transaction("异地缴费_提交", LR_PASS);
    }
    else
    {
    lr_error_message("异地缴费_提交失败,号码为:%s",lr_eval_string("{msisdn}"));
    lr_end_transaction("异地缴费_提交", LR_FAIL);
    }
    //lr_end_transaction("异地缴费_提交",LR_AUTO);)

            5.4验证我们的需求是否实现
            下面简单介绍,整个验证过程,在确保脚本正确和测试环境正常的情况下,我们先在VU里验证下是否真正实现了我们想要的功能,为了方便,我特地将判断条件该为="=而不是!=,通过查看日志来检查。

            首先,选中菜单栏里的Run-time Settings子菜单,设置里面的Log选项,选中Enable Logging 和Always send messages 和Extended log 及Parameter substitution。
    设置Run Logic 里的Number of Iterations 为2,然后运行,并查看日志。可以得到如下的日志(只取了关键部分的):
    第一次循环关键部分:
    YiDiJiaoFei.c(598): Notify: Transaction "提交异地缴费数据" ended with "Fail" status (Duration: 4.8459 Wasted Time: 0.0060).
    YiDiJiaoFei.c(605): Notify: Parameter Substitution: parameter "WCSParam_Text2" = "操作业务数据成功!"
    YiDiJiaoFei.c(607): Notify: Next row for parameter iteration = 1 [table = iteration].
    YiDiJiaoFei.c(607): Notify: Parameter Substitution: parameter "iteration" = "1"
    YiDiJiaoFei.c(607): Notify: Parameter Substitution: parameter "PhoneNum" = "13953555588"
    YiDiJiaoFei.c(607): Error: 消息: 提交异地缴费数据失败!,在第 1 次循环时出错,出错号码:13953555588

    第二次循环关键部分:
    YiDiJiaoFei.c(598): Notify: Transaction "提交异地缴费数据" ended with "Fail" status (Duration: 4.2347 Wasted Time: 0.0064).
    YiDiJiaoFei.c(605): Notify: Parameter Substitution: parameter "WCSParam_Text2" = "操作业务数据成功!"
    YiDiJiaoFei.c(607): Notify: Next row for parameter iteration = 2 [table = iteration].
    YiDiJiaoFei.c(607): Notify: Parameter Substitution: parameter "iteration" = "2"
    YiDiJiaoFei.c(607): Notify: Parameter Substitution: parameter "PhoneNum" = "13953572390"
    YiDiJiaoFei.c(607): Error: 消息: 提交异地缴费数据失败!,在第 2 次循环时出错,出错号码:13953572390

            下面验证执行时,能正确找到出错的号码信息,将脚本加入到场景后,同样设置好Run-time Settings。

            设置结果保存路径等相关信息,按Start Scenario 执行场景,等出错是单击右上角的Errors,然后选中错误信息再按Details按纽查看错误信息。

    6.怎么样使多台产生vuser的测试机均匀地对被测试的系统施加压力?
    在测试的过程中,为了尽可能减少或者避免本身的测试机成为测试过程中的瓶颈,需要使用多台测试机产生vuser对被测试系统施加压力,下面对操作步骤做简单介绍:
            在默认模式下使用controller添加多台Generators机器时,不管你怎么加,最终能真正起作用的只有一台(10.19.180.2/3/4或localhost):

    为了让10.19.180.2/3/4机器同时能真正被添加进去,我们需要做以下几步工作:
    改变场景模式,将组模式()改变为百分比模式(percentage mode),具体做法是,选择Scenario菜单下的Convert Scenario to the Percentage Mode;

    然后,在已经添加好的Load Generators机器列表中同时选择你想选择的机器;

    最后,点OK按钮就可以得到我们所要的结果了。

    当然,如有必要我们还可以把场景模式改为Vuser Group Mode,具体做法如下:
    选择Scenario菜单下的Convert Scenario to the Vuser Group Mode;

    然后在弹出的对话框中,单击Yes按钮可以得到如下结果,

    到此为止,添加多台Load Generators测试机整个过程就完成了,其实很简单,关键是你发现了没有。

    7. 怎么样在关联时取列表的最后一个值(在测试重打发票取流水号时需要)?
    在压力测试脚本的关联过程中,我们有时可能需要关联最新的值(如最新的流水号,通常情况下,最新的流水号放在列表的最下方),所以找最新的流水号就是最列表最下方,如果保存在数组里,那就是找index值最大的那个元素。下面以重打发票(注:具体流程为先缴费,然后查询缴费历史,然后从缴费历史里找到最新的流水号,然后使用此流水号进行重打发票)为例对整个过程做详细的介绍:
    首先,在缴费历史里找到需要关联的流水号并关联之,具体做法如下,
    7.1以Tree View方式打开脚本并在对应事件的Page View里找到最新的流水号

            找到我们需要关联的流水号(这里为536dxwf0200051031000000)后,需要把它给关联,(因为返回的值是事后才知道的,且对于不同的电话号码,对应的返回值不同,所以对于这样的值是需要关联的。)具体做法是打开Server Response 页面并在Body里找到需要关联的流水号,然后选中此流水号并在右键弹出的菜单中使用Create Parameter关联之。

     


    7.2单击是(Y)按钮,对应的脚本中会增加如下内容。

            单击View scrīpt 图标以scrīpt模式查看关联情况。

    7.3到此为止脚本中多出如下代码段,下面对它做一定的分析:
    web_reg_find("Text="缴费历史查询"",
    LAST);
    // [WCSPARAM WCSParam_Text1 23 536dxwf0200051031000000] Parameter {WCSParam_Text1} created by Correlation Studio
    web_reg_save_param("WCSParam_Text1",
    "LB="formnum="",
    "RB=\"",
    "Ord=8",
    "RelFrameId=1",
    "Search=Body",
    LAST);
    //后面的内容为注释部分,说明流水号536dxwf0200051031000000已经关联并保存到WCSParam_Text1参数中。
            web_reg_save_param()为LoadRunner的保存参数所用的函数,其作用是将返回流水号保存到WCSParam_Text1参数中,以便使用不同的号码进行缴费历史查询出来的流水号能随着时间的变化流水号也跟着变化,而不是录制脚本时的536dxwf0200051031000000,这样可以避免在重打发票时不会报诸如此流水号不存在等类似错误信息。然而现在的问题是怎么将此流水号对应到重打发票对应的地方。另一个问题是,不是所有的号码缴费后查询到的流水号数量都和录制脚本时查询到的流水号相同,事实上每做一笔除查询类的操作都会有一个流水号。而我们关注的是怎么取到最新的缴费的流水号,下面详细介绍相关步骤。

    5.1 修改web_reg_save_param()函数相关部分,很简单,把"Ord="8"",改为"Ord=ALL",目的是找最TOP的那个参数值。

    5.2 光保存和取参数还不够,我们需要把参数能正确传递到重打发票对应的地方,为此我采取的做法如下:
            在缴费历史事件脚本最前面定义两个变量,目的是为了将流水号以字符串的形式保存在变量里(因为LoadRunner不支持在web_submit_data()函数里直接使用变量):具体做法是:
    char WCSParam_Text1Pram[50]; //保存取到的流水号
    char WCSParam_Text1PramVal[50]; //保存以"Value="流水号""取到的流水号。


            将关联好的流水号存到变量里,在此的做法是在对应的web_submit_data()函数后添加如下代码段:
    lr_message("WCSParam_text1:%s",lr_eval_string("{WCSParam_Text1}"));
    //打印出关联的参数WCSParam_Text1的值。
    sprintf(WCSParam_Text1Pram,"{WCSParam_Text1_%s}",lr_eval_string("{WCSParam_Text1_count}"));
    //把取到流水号保存到WCSParam_Text1Pram里,具体形式为
    sprintf(WCSParam_Text1PramVal,"Value="%s"",lr_eval_string(WCSParam_Text1Pram));
    //组合流水号和”Value=”并保存到WCSParam_Text1PramVal变量中。
    lr_message("The value argument is : %s", WCSParam_Text1PramVal);
    //打印出字符串变量WCSParam_Text1PramVal的值。

     

    5.3 找到重打发票中响应的流水号,并把其中的"Value="536dxwf0200051031000000""替换成WCSParam_Text1PramVal,在这里总共有两处。

     

            到此为止,流水号的关联已经基本上处理完毕,下面我们执行脚本,来验证我们想要的是不是真的有效。(注,参数化的问题在本文中不做具体介绍)为了看到明显的效果,我们需要将日志的处理做简单设置。

            然后执行脚本,查看相关执行日志,可以得到类似下面得消息。

     

    8.使用LoadRunner一些常用的注意事项:
    Note1:VuGen仅能录制 Windows平台上的会话,但是,录制的Vuser脚本既可以在Windows 平台上运行,也可以在 UNIX 平台上运行。
    通用 Vuser 函数和特定于协议的函数,它们共同构成了 LoadRunner API,并使Vuser能够直接与服务器通信。

    Note2:用于运行Vuser脚本的C解释器仅支持ANSI C语言。它不支持 Microsoft对ANSI C的任何扩展。
    通常情况下,可以将登录到服务器的活动录制到vuser_init部分中、将客户端活动录制到Actions部分中,并将注销过程录制到vuser_end部分中。

    Note3:只能向Action部分(而不是init或end 部分)添加集合。
    Note:不要从事务内部发送消息,因为这可能使事务执行时间变长,并扭曲事务结果。

    Note4:如果使用日志运行时设置修改脚本的调试级别,则 lr_message、lr_output_message 和 lr_log_message 函数的行为将不会更改,它们将继续发送消息。

    Note5:录制 Java Vuser 脚本时, Vuser 脚本中将不生成 lr_think_time 语句。

    Note6:VuGen 新建参数,但不会自动替换任何在脚本中选定的字符串。

    Note7:不要将参数命名为 unique,因为该名已被 VuGen 使用。

    Note8:如果在常规运行时设置文件夹中将“错误处理”设置为“出现错误时仍继续”,则错误消息仍将被发送到输出窗口。

    Note9:因为生成的服务器消息很长,而且日志记录会降低系统的运行速度,所以请仅为脚本中特定的代码块激活服务器消息日志记录功能。

    Note10:启用“出现错误时仍继续”功能时,将覆盖 0 严重级别;即使发生数据库错误,也将继续执行脚本。然而,如果禁用了“出现错误时仍继续”功能,但将严重级别指定为 1,则当发生数据库错误时仍将继续执行脚本。

    Note11:下列协议不是线程安全协议:Sybase-Ctlib、Sybase-Dblib、Informix、Tuxedo 和 PeopleSoft-Tuxedo。

    Note12:对于支持树视图的协议(如“视图”菜单所示),在树视图中运行 Vuser脚本时, VuGen 将从 Vuser 脚本中的第一个图标开始运行该脚本。

    Note13:要显示运行时查看器,必须安装 Microsoft Internet Explorer 4.0 或更高版本。
    Note:Vuser 生成“结果摘要”报告时,事务时间可能会增加。Vuser 可以仅在从 VuGen 运行时才生成“结果摘要”报告。使用 Controller 运行 Web Vuser 脚本时, Vuser 不能生成报告。

    Note14:当使用 Javascrīpt 和 VBscrīpt Vuser 时,在脚本中用到的 COM 对象必须完全的兼容。这使下列情况成为了可能:一个应用程序操纵另一个应用程序中的对象,或者公开对象以便操纵它们。

    9.性能参数解析:
    WEB资源参数

            每秒点击次数:中Vuser每秒向Web服务器提交的HTTP请求数,依据点击次数来评估Vuser产生的负载量。

            吞吐量:案运行过程中服务器上每秒的吞吐量。吞吐量的度量单位是字节,表示Vuser在任何给定的某一秒上从服务器获得的数据量,依据服务器吞吐量来评估Vuser产生的负载量。

            每秒HTTP响应数:中每秒从Web服务器返回的HTTP状态代码号(表示HTTP请求的状态,例如“the request was successful”、“the page was not found”)

            每秒下载页面数:每秒钟从服务器下载的网页数,依据下载的页面数来评估Vuser产生的负载量。

            每秒重试次数:中每秒钟内服务器尝试的连接次数,在下列情况下将重试服务器连接:初始连接未经授权、要求代理服务器身份验证、服务器关闭了初始连接、初始连接无法连接到服务器或者服务器最初无法解析负载生成者的IP地址。

            连接数:每个时间点上打开的TCP/IP连接数。

            每秒SSL连接数:每秒打开的新的以及重新使用的SSL连接数。当对安全服务器打开TCP/IP连接后,浏览器将打开SSL连接,因为新建SSL连接需要消耗大量的资源,所以应该尽量少地打开新的SSL连接。

    网页细分图
            注意:由于要从客户端测定服务器时间,因此,如果发送初始HTTP请求到发送第一次缓冲这一段时间内网络性能发生变化,则网络时间可能会影响此测定。因此,所显示的服务器时间是一个估计值,可能不太精确。
    DNS解析:显示使用最近的DNS服务器将DNS名称解析为IP地址所需的时间。“DNS 查找”度量是指示DNS解析问题或DNS服务器问题的一个很好的指示器。

            连接:显示与包含指定URL的Web服务器建立初始连接所需的时间。连接度量是一个很好的网络问题指示器。此外,它还可表明服务器是否对请求作出响应。

            第一次缓冲:显示从初始HTTP请求(通常为 GET)到成功收回来自Web服务器的第一次缓冲时为止所经过的时间。第一次缓冲度量是很好的Web服务器延迟和网络滞后指示器。注意:由于缓冲区大小最大为 8K,因此第一次缓冲时间可能也就是完成元素下载所需的时间。

            SSL握手:显示建立SSL连接(包括客户端 hello、服务器hello、客户端公用密钥传输、服务器证书传输和其他部分可选阶段)所用的时间,自此点之后,客户端与服务器之间的所有通信都将被加密。SSL握手度量仅适用于HTTPS通信。

            接收:显示从服务器收到最后一个字节并完成下载之前经过的时间。“接收”度量是很好的网络质量指示器(查看用来计算接收速率的时间/ 大小比率)。

            FTP验证:显示验证客户端所用的时间。如果使用FTP,则服务器在开始处理客户端命令之前,必须验证该客户端。“FTP 验证”度量仅适用于 FTP 协议通信。

            客户端时间:显示因浏览器思考时间或其他与客户端有关的延迟而使客户机上的请求发生延迟时,所经过的平均时间。

            错误时间:显示从发出HTTP请求到返回错误消息(仅限于HTTP错误)这期间经过的平均时间。

            系统资源(UNIX资源参数):
    CPU utilization :CPU的使用时间百分比
    Disk rate :磁盘传输速率
    Paging rate :每秒钟读入物理内存或写入页面文件中的页数
    Page-in rate :每秒钟读入到物理内存中的页数
    Page-out rate :每秒钟写入页面文件和从物理内存中删除的页数
    Collision rate :每秒钟在以太网上检测到的冲突数
    Context switches rate :每秒钟在进程或线程之间的切换次数
    Average load :上一分钟同时处于“就绪”状态的平均进程数
    Swap-in rate :正在交换的进程数
    System mode CPU utilization :在系统模式下使用CPU的时间百分比
    User mode CPU utilization :在用户模式下使用CPU的时间百分比

    网络监视参数

            网络延迟时间:源计算机与目标计算机(例如,数据库服务器和Vuser负载生成器)之间的整个路径的延迟。

            网络子路径时间:从源计算机到路径上每个节点的延迟。注意:从源计算机到每个节点的延迟是同时而又独立地度量的。因此,从源计算机到其中一个节点的延迟可能大于源计算机与目标计算机之间的整个路径上的延迟。

            网络段延:路径上每个段的延迟。

            验证网络是否是瓶颈:可以合并各种图来确定网络是否是瓶颈。例如,通过使用网络延迟时间图和运行Vuser图,可以确定Vuser的数量如何影响网络延迟。网络延迟时间图指示在方案运行期间的网络延迟。

    数据库服务器

            User Calls :在每次登录、解析或执行时, Oracle 会分配资源(Call State 对象)以记录相关的用户调用数据结构。在确定活动时,用户调用与RPI调用的比指明了,因用户发往Oracle的请求类型而生成的内部工作量

            Total file opens :由实例执行的文件打开总数。每个进程需要许多文件(控制文件、日志文件、数据库文件)以便针对数据库进行工作

            Opened cursors current :当前打开的光标总数

            DB block changes :由于与一致更改的关系非常密切,此统计计算对SGA中所有块执行的、作为更新或删除操作一部分的更改总数。这些更改将生成重做日志项,如果事务被提交,将是对数据库的永久性更改。此统计是一个全部数据库作业的粗略指示,并且指出(可能在每事务级上)弄脏缓冲区的速率。

    10.AIX操作系统机器性能瓶颈定义:
    瓶颈定义
    CPU bound : vmstat : when %user+%sys greater than 80%;
    Disk I/O bound : vmstat : when %iowait greater than 40%(AIX4.3.3 or later);
    Application disk bound :vmstat : when %tm_act greater than 70%;
    Paging space low : lsps -a : when used paging space greater than 70% active;
    Paging bound : iostat vmstat : paging logical volumes %tm_act greater than 30% of the I/O(iostat) and paging activity greater than 10* the number of CPUs(vmstat);
    Thrashing : vmstat sar :rising page outs, CPU wait and run queue;

    11.系统性能分析命令:
    cpu : vmstat,iostat,topas,nmon,ps,sar,time,timex,netpmon,trace,trcrpt;
    内存:vmstat,topas,nmon,ps,svmon,lsps,filemon,trace,trcrpt;
    磁盘:iostat,topas,nmon,lvmstat,iostat -d, lvmstat, lsps,filemon,lsattr,lsdev;
    网络:netstat,topas,nmon,entstat,nfsstat,ifconfig,iptrace,ipreport,trace,trcrpt;
    监视CPU使用情况:vmstat 2 ; iostat -t 2 6;sar -P ALL 2 3;
    监视内存使用情况: vmstat 2 10;ps aux;svmon -G;svmon -Pau 10;
    监视I/O使用情况: iostat 5;sar -d 3 3;
    监视网络使用情况: netstat -i ;netstat -m;netstat -v;

    此文来源于51testing博客,转载请注明出处
    原始链接:
    http://www.51testing.com/?94273/action_viewspace_itemid_13778.html

  • Visual Studio 2008单元测试实践

    2007-12-07 17:42:29

    本文转载自http://blog.csdn.net/kkshizhu520/archive/2007/12/04/1915438.aspx
       
        单元测试是在软件开发过程中要进行的最低级别的测试活动,在单元测试活动中,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

        在一种传统的结构化编程语言中,比如C,要进行测试的单元一般是函数或子过程。在象C++这样的面向对象的语言中, 要进行测试的基本单元是类。对Ada语言来说,开发人员可以选择是在独立的过程和函数,还是在Ada包的级别上进行单元测试。单元测试的原则同样被扩展到第四代语言(4GL)的开发中,在这里基本单元被典型地划分为一个菜单或显示界面。

        单元测试不仅仅是作为无错编码的一种辅助手段在一次性的开发过程中使用,单元测试必须是可重复的,无论是在软件修改,或是移植到新的运行环境的过程中。因此,所有的测试都必须在整个软件系统的生命周期中进行维护。

        Visual Studio 2008 单元测试功能介绍

    一、测试代码与被测代码分离成独立的两个项目

        单元测试中,测试的代码不能对被测试的代码施加影响。如果将测试代码写入被测试的代码中,测试完成后再删除的话,测试的正确性将得不到保证。因此,在Visual Studio 2008种提供了一种“Test Project”的项目,测试代码写在Test Project中,并且测试工程可以进行重复使用。

    二、测试代码的自动生成

        书写测试代码是一件很烦琐的事情,这些代码没有像程序代码一样具有“创造性”,因此该部分代码可以进行自动化生成。Visual Studio 2008就提供了一个自动生成测试代码的测试框架。利用Visual Studio 2008自动生成的代码,只需要很少的改动就可以完成整个测试程序。

    三、测试管理

        Visual Studio 2008提供了测试列表来进行测试工作的管理工作,我们需要一个反映目前测试状况的工具,那些测试通过了,那些没有通过,应该提供一个列表来为我们改进测试手段,进行更全面的测试提供指导。
     
        利用Visual Studio 2008来进行单元测试

        假设我们有一个类BankAccount,该类定义了一个银行的账户,私有属性_currentBalance是银行储户的账户金额,depositMoney是存款方法,对帐户增加一笔资金,makePayment是支付方法,对账户减少一笔资金。代码如下:

     

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

     

    namespace BankAccountDemo.Business

    {

        
    class BankAccount

        
    {

            
    private float _currentBalance;

       
    public float CurrentBalance

            
    {

                
    get return _currentBalance; }

                
    set { _currentBalance = value; }

            }


            
    public BankAccount(float initialBalance)

            
    {

                
    this._currentBalance = initialBalance;

            }


            
    public void depositMoney(float depositAmount)

            
    {

                
    this._currentBalance += depositAmount;

            }


            
    public void makePayment(float paymentAmount)

            
    {

                
    this._currentBalance -= paymentAmount;

            }


     

        }


    }



        要对
    BankAccount类进行单元测试,只需要在BankAccount的定义处鼠标右键,在菜单中选择“Create Unit Tests”即可进入测试项目的创建工作。如下图所示:

     



       
    在弹出的创建单元测试的对话框中,对需要创建测试的方法和属性进行选择,然后点击“OK”按钮,如图所示:

       
    紧接着在出现的文本框中输入测试项目的名称“BankAccountDemo.Business.Tests”,点击确定后,测试项目被创建。在这里“BankAccountDemo.Business.”只是用于更好的对命名空间进行规划,完全可以直接使用“BankAccountDemoTest”来作为测试项目的名字。
    生成的测试代码如下,为了紧凑的表现代码,将注释代码作了删除。

    这个时候的代码并不能开始测试,而需要我们按照测试用例的要求将测试用例的数据加入到测试方法中,并进行结果的比较,修改后的depositMoneyTest方法如下:

     

    [TestMethod()]

    public void depositMoneyTest()

    {

        float initialBalance = 0F; // TODO: Initialize to an appropriate value

        BankAccount target = new BankAccount(initialBalance); // TODO: Initialize to an appropriate value

        float depositAmount = 100F; // TODO: Initialize to an appropriate value

        target.depositMoney(depositAmount);

        Assert.AreEqual(initialBalance + depositAmount, target.CurrentBalance, "Deposit Test: Deposit not applied correctly");

     }


         
    鼠标右键在depositMoneyTest方法内任意位置单击,在弹出的菜单中选择“Run Tests”,即可以对该方法进行测试。在“Test Results”窗口中显示测试的结果,如下图所示:

     

     


        可以看出,
    Visual Studio 2008给我们提供了一个功能强大,操作简单的单元测试功能。利用该功能,程序员在编写代码后,可以马上对所编写的类进行单元测试,通过了程序员自行组织的单元测试后再将代码交给测试人员进行进一步测试。

       
    总结:微软将单元测试功能从Visual Studio 2005 Team System开始集成到开发环境中,是经过了微软公司多年的实践经验证明的。如今,开发环境从以前的单一开发功能,将关注点分散到软件的整个生命周期过程中来,已经成为一个ALM平台。软件开发人员不仅需要做开发工作,而且需要对自己开发的代码进行单元测试,不能将所有的问题全部抛给测试人员。测试人员可以将更多的精力放在系统一级的测试工作上面。

    using BankAccountDemo.Business;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    namespace BankAccountDemo.Business.Tests

    {

        [TestClass()]

        
    public class BankAccountTest

        
    {

            
    private TestContext testContextInstance;

     

            
    public TestContext TestContext

            
    {

                
    get

                
    {

                    
    return testContextInstance;

                }


                
    set

                
    {

                    testContextInstance 
    = value;

                }


            }


     

            
    Additional test attributes

     

     

            [TestMethod()]

            
    public void CurrentBalanceTest()

            
    {

                
    float initialBalance = 0F; // TODO: Initialize to an appropriate value

                BankAccount target 
    = new BankAccount(initialBalance); // TODO: Initialize to an appropriate value

                
    float expected = 0F; // TODO: Initialize to an appropriate value

                
    float actual;

                target.CurrentBalance 
    = expected;

                actual 
    = target.CurrentBalance;

                Assert.AreEqual(expected, actual);

                Assert.Inconclusive(
    "Verify the correctness of this test method.");

            }


     

            [TestMethod()]

            
    public void makePaymentTest()

            
    {

                
    float initialBalance = 0F; // TODO: Initialize to an appropriate value

                BankAccount target 
    = new BankAccount(initialBalance); // TODO: Initialize to an appropriate value

                
    float paymentAmount = 0F; // TODO: Initialize to an appropriate value

                target.makePayment(paymentAmount);

                Assert.Inconclusive(
    "A method that does not return a value cannot be verified.");

            }


     

            [TestMethod()]

            
    public void depositMoneyTest()

            
    {

                
    float initialBalance = 0F; // TODO: Initialize to an appropriate value

                BankAccount target 
    = new BankAccount(initialBalance); // TODO: Initialize to an appropriate value

                
    float depositAmount = 0F; // TODO: Initialize to an appropriate value

                target.depositMoney(depositAmount);

                Assert.Inconclusive(
    "A method that does not return a value cannot be verified.");

            }


    [TestMethod()]

            
    public void BankAccountConstructorTest()

    查看(916) 评论(0) 收藏 分享 管理

  • loadrunner- winsock 函数 一览表

    2007-12-04 18:10:48

    lrs_accept_connection 接受侦听套接字连接

            lrs_close_socket 关闭打开的套接字


            lrs_create_socket 初始化套接字


            lrs_disable_socket 禁用套接字操作


            lrs_exclude_socket 重播期间排除套接字


            lrs_get_socket_attrib 获取套接字属性


            lrs_get_socket_handler 获取指定套接字的套接字处理程序


            lrs_length_receive 接收来自指定长度的缓冲区的数据


            lrs_receive 接收来自套接字的数据


            lrs_receive_ex 接收来自数据报或流套接字的数据(具有特定长度)


            lrs_send 将数据发送到数据报上或流套接字中


            lrs_set_receive_option 设置套接字接收选项


            lrs_set_socket_handler 设置特定套接字的套接字处理程序


            lrs_set_socket_options 设置套接字选项


    缓冲区函数

            lrs_free_buffer 释放分配给缓冲区的内存


            lrs_get_buffer_by_name 从数据文件中获取缓冲区及其大小


            lrs_get_last_received_buffer 获取套接字上接收到的最后的缓冲区及其大小


            lrs_get_last_received_buffer_size 获取套接字上接收到的最后一个缓冲区的大小


            lrs_get_received_buffer 获取最后接收到的缓冲区或其一部分


            lrs_get_static_buffer 获取静态缓冲区或其一部分


            lrs_get_user_buffer 获取套接字的用户数据的内容


            lrs_get_user_buffer_size 获取套接字的用户数据的大小


            lrs_set_send_buffer 指定要在套接字上发送的缓冲区


    环境函数

            lrs_cleanup 终止 Windows 套接字 DLL 的使用


            lrs_startup 初始化 Windows 套接字 DLL


    关联语句函数

            lrs_save_param 将静态或接收到的缓冲区(或缓冲区部分)保存到参数中


            lrs_save_param_ex 将用户、静态或接收到的缓冲区(或缓冲区部分)保存到参数中


            lrs_save_searched_string 在静态或接收到的缓冲区中搜索出现的字符串,将出现字符串的缓冲区部分保存到参数中


    转换函数

            lrs_ascii_to_ebcdic 将缓冲区数据从 ASCII 格式转换成 EBCDIC 格式


            lrs_decimal_to_hex_string 将十进制整数转换为十六进制字符串


            lrs_ebcdic_to_ascii 将缓冲区数据从 EBCDIC 格式转换成ASCII 格式


            lrs_hex_string_to_int 将十六进制字符串转换为整数


    超时函数

            lrs_set_accept_timeout 为接受套接字设置超时


            lrs_set_connect_timeout 为连接到套接字设置超时


            lrs_set_recv_timeout 为接收套接字上的初始预期数据设置超时


            lrs_set_recv_timeout 为建立连接后接收套接字上的预期数据设置超时


            lrs_set_send_timeout 为发送套接字数据设置超时


            录制会话之后,通过 VuGen 的内置编辑器可以查看录制的代码。您可以在脚本中滚动,查看应用程序生成的函数,并检查传输的数据。在主窗口中查看脚本时,可以看到VuGen 录制活动的顺序。在典型的会话期间,将录制下列函数顺序:


            lrs_startup 初始化 WinSock DLL


            lrs_create_socket 初始化套接字


            lrs_send 在数据报上或者向流套接字发送数据


            lrs_receive 接收来自数据报或流套接字的数据


            lrs_disable_socket 禁用套接字操作


            lrs_close_socket 关闭打开的套接字


            lrs_cleanup 终止 WinSock DLL 的使用

            VuGen 在 Windows 上使用 Windows 套接字协议支持应用程序的录制和重播;而在UNIX 平台上仅支持重播。

Open Toolbar