发布新日志

  • QTP基础设置

    2015-03-26 08:42:32



    一.Automation>>Record and Run Settings

    第一个选项卡>>web:测试web程序(Web选项卡仅当相应的Web插件安装和加载后才会自动生成)

    Record and run test on any open browser:录制已经打开的浏览器(QTP所支持的)

    Open the following address when a record or run session begins:指定QuickTest打开新的浏览器并只使用指定的URL地址。(输入浏览器 地址)

    Open the following browser when a run session begins:指定浏览器

    Do not record and run on browsers that are already open:不要录制已经打开的浏览器

    Close the browser when the test closes:录制结束时,自动关闭程序启动的浏览器

    第二个选项卡>>Windows applications:测试运行在Windows上的应用,包括标准Windows,Visual Basic和ActiveX的应用程序

    Record and run test on any open Windows-based application:录制已经打开的应用程序。

    Record and run only on:增加应用程序的可执行文件路径

    1.Applications opened by QuickTest:使用QTP打开应用程序

    2.Applications opened via the Desktop (by the Windows shell):通过桌面应用程序打开(由Windows外壳程序)。这个选项只能在记录和运行是通过Windows桌面上打开的应用程序。

    3.Applications specified below:记录应用程序的详细信息

    Application details:设置应用程序路径、工作文件夹(如果没有指定工作文件夹,则默认为应用程序文件夹问工作文件夹)、程序参数等…
    二. File>>settings…

    第一个选项卡>>properties 程序配置

    Name、Author、Created by、Last modified by分别指出:测试的名称、谁创造了测试(Windows用户名)、QuickTest版本号、QuickTest最后一次修改的版本号。

    Location :文件的绝对路径。

    Description:测试的描述。

    Associated add-ins:相关的加载项显示添加与测试相关的插件

    Modify:选择外接程序与测试相关联(选择当前链接的插件)。

    Generate script. 导出当前settings里面所有配置信息的脚本,这些脚本里面的对象都是qtp的自动化对象模型。(使用时在resources下导入该qfl文件)

    第二个选项卡>>Run 运行设置

    Data table iterations:针对table数据表的循环行数;指定测试迭代的次数。

    1.Run one iteration only:只运行一次迭代(第一行)。运行测试只有一次,只用在全球数据表的第一行。

    2.Run on all rows:运行的所有行。运行具有使用全局数据表的所有行反复测试。

    3.Run from row __to row__:从行__运行到行__。运行具有指定行的使用在全范围内的数据表中的值迭代测试。

    When error occurs during run session:为错误发生在运行测试时,程序如何响应(提示类型)

    1.popup message box:一个错误在运行过程中会发生时,QuickTest会显示一个弹出消息框,描述该错误。你可以选择这个消息框按钮继续或终止运行会话。

    2.proceed to next action iteration:发生错误时QuickTest强制进入下一个循环动作。

    3.stop run:发生错误时QuickTest会强制停止运行测试。

    4.proceed to next step:在测试中发生错误时QuickTest强制执行下一个步骤。

    object synchronization timeout:QuickTest强制等待一个对象在运行前加载的等待时间。

    注:当使用Web对象的工作时,QuickTest最多等待的时间量的浏览器导航超时选项设置,加上对象同步超时设置的时间

    Disable Smart Identification during the run session:启用智能识别对象(对相似的智能识别失效。只要做web测试,建议都选上。选上后再抓对象。)

    注意:当您选择此选项,启用智能识别的对象属性和对象库对话框复选框被禁用,虽然保存设置。当您清除此选项,启用智能识别复选框恢复到原来的设置或关闭

    Save image of desktop when error occurs (if test is run by the Mercury Business Process Monitor):此选项仅适用于由该业务流程监控Mercury应用管理组件运行测试。

    字面翻译:如果出现错误时捕捉桌面的快照。

    第三个选项卡>>Resources 调用外部资源(如函数脚本)

    Libraries:添加、删除和排序的文件;还可以设置新的默认函数库

    Set as Default:设置为默认设置为默认清单,在new test的时候程序会自动加载这些资源。

    Check Syntax:验证是否有相关的函数库包含语法错误。(语法检查)

    Data Table:指定数据表的位置

    1.Default location (under test directory): 默认位置(在测试目录)。

    2.Other location: 其他位置。

    第四个选项卡>>Parameters 输入、输出值设置

    Input parameters:输入参数,指定的参数的测试可以接收来自源程序运行或调用它的值。

    Output parameters:输出参数,指定的参数,测试可以传递给源程序,运行或调用它。

    第五个选项卡>>Environment 环境变量设置

    Built-in:内置环境变量。指QTP自身的环境变量(如操作系统,计算机名等),可以随意调用。

    1.Name:变量名

    2.Description:描述

    3.Current value:变量值

    User –defined:用户定义的环境变量。只有当前的脚本才可以调用。

    1.name:自定义环境变量名

    2.value:自定义环境变量值

    3.type:每个用户定义的变量类型:内部或外部。

    4.export:导出用户自定义的环境变量

    5. Load variables and values from external file:文件保存

    第六个选项卡>>Web  web设置

    Browser navigation timeout:QuickTest等待网页载入时间的最大值。

    User name:用标准的认证机制的用户名。

    Password:使用标准的密码验证机制。

    Advanced:打开高级身份验证对话框,它使您可以手动在您的网站日志,以允许访问受密码保护的资源,采用先进的验证机制。

    第七个选项卡>>Recovery  场景恢复设置

    Scenarios:显示每个场景恢复方案的名称和路径。可以添加,删除,并优先列表中的场景,可以编辑所选文件的文件路径。

    Scenario description:显示对场景恢复方案的描述。

    Activate recovery scenarios:设置何时启动场景恢复方案

    1.On every step:每一个步骤都运行场景恢复。

    2.On error:出错时运行场景恢复。

    3.Never:整个运行测试都不运行场景恢复。

    Set as Default:还原默认设置
    三.接下来tools>>options…

    第一个选项卡>>General 常规设置

    Display Add-in Manager on startup:在启动时显示加载项管理器(插件选择)

    Display Welcome screen on startup:在启动QTP时显示欢迎界面

    Check for software updates on startup:启动时检查是否有更新

    Disable recognition of virtual objects while recording:录制时禁用虚拟对象识别,QTP在创建好虚拟对象后,如果选择了此项,则在录制到要用虚拟对象的时候,录制结束后,代码中会直接把要用虚拟对象的地方省略

    Automatically update test and component steps when you rename test objects:当重命名测试库中对象后自动更新测试和组件步骤

    Automatically generate "With" statements after recording:

    Generate "With" statements for __ or more objects:(with:搞格式用,简洁)

    When pointing at a window, activate it after __ tenths of a second:

    Restore Layout:初始化QTP窗口布局。

    Generate Script:导出配置对话框,点击该按钮将会把options中的配置以脚本形势导出来,里面大多使用自动化对象模型的对象,大家可以试试看导出的内容。

    第二个选项卡>>Folders设置当前测试脚本路径.

    通过此页可以设置当前测试脚本路径.

    第三个选项卡>>Active Screen快照的截图策略详细设置。

    快照的截图策略详细设置。该设置会增加大量的磁盘空间。

    Capture level:指定QTP录制时存储对象的级别(级别越高,越占用磁盘空间)

    Custom Level:自定义Action选项

    Default Level:恢复对象存储级别默认值

    Advanced:高级(定义Action外观)

    第四个选项卡>>Run

    Run mode:

    1.Normal (displays execution marker);Delay each step execution by:设置运行步骤间隔时间且会有当前运行步骤提示

    2.Fast:以最快速度执行测试

    Submit a defect to Quality Center for each failed step:自动提交测试中的bug信息,需连接到一个QC/TD

    View results when run session ends:测试运行结束,结果显示会话框自动弹出。

    Allow other Mercury products to run tests and components:

    Save still image captures to results:快照功能

    1.Always:每一步骤都保存快照

    2.For errors:出现错误时保存快照

    3.For errors and warnings:出现错误或警告时保存快照

    Save movie to results:录像功能

    1.Always:每一步骤都保存录像

    2.For errors:出现错误时保存录像

    3.For errors and warnings:出现错误或警告时保存录像

    Save movie segment up to __  KB prior to each error and warning:指定录像的起始点(当录像保存类型不为‘Aleays’时,在出现错误或警告前多少KB开始录制)

    Save movie of entire run:测试执行过程全部录像并保存

    Advanced:进阶(仅当保存录像的选择。提供先进的屏幕记录器选项会影响电影文件大小和外观。)

    第五个选项卡>>Windows Applications

    Attached text:

    Search radius:搜索半径;指出搜索最大距离,以像素为单位。

    Search area:搜索范围;指定对象的搜索区域。

    Open menu to retrieve item properties:在运行过程中检索会话菜单项属性(默认选择)。

    Record non-unique list items:当一个以上的对象具有相同的名称。则指定属性区分

    1.by name:通过名称。记录对象的名称进行识别

    2.by index:通过索引。记录对象的索引号进行识别。

    Record owner-drawn buttons as:如何识别并记录在应用程序上的对象。

    1.push buttons:按钮

    2.check boxes:复选框

    3.radio buttons:单选按钮

    4.objects:对象

    Advanced:打开高级选项对话框,可以自定义记录和运行Windows应用程序的选项。

    第六个选项卡>>Web

    Ignore the following browsers:忽略任何下面指定的浏览器(网页)。

    Ignore Quality Center:忽视QC中同时被打开的录制或运行一个测试或组件的实例

    Add __ seconds to page load time:指定页面加载的时间。

    Broken links - check only links to current host:(默认勾选)检查当前的主机断开的链接。

    Page/Frame. Options:自定义页和框架的测试对象。

    Advanced:打开高级Web选项对话框,可以自定义记录和运行网站的选择。
    四.tools>>View Options

    第一个选项卡>>General

    Show line numbers:专家视图窗口在左侧显示行号。

    Auto-indent:启动自动缩进

    Indent selected text when pressing Tab key:按‘Tab’键进行缩进

    Statement completion:语法自动生成

    Draw box around current line:

    Show all characters:显示符号(可选制表符,新行,空格字符符号)。

    Auto-expand VBScript. syntax:自动扩展VBScript语法。

    Use tab character:一个制表符‘Tab’键 所占的字符数。

    第二个选项卡>>Fonts and Colors  外观设置

    外观、颜色、字体设置

    第三个选项卡>>Key Binding 个性化设置

    设置快捷键
    五.Tools>>Object  Identification:对象识别

    Environment:显示当前加载的所有插件。选择不同的插件,下面会出现当前插件自带标准的Test Object Class(测试对象类)。

    User Defind:可以自定义。
    选择具体的测试对象类,右面有Mandatory Property(必须的属性)和Assistive Property(辅助的属性)。当必须的属性不足以识别一个对象时,可以会加上辅助的属性来识别。
    Enable Smart Identification :是针对某个小的脚本来进行屏蔽相似匹配功能。
    六.tools>>Web Event Recording Configuration:web事件录制配置

    Default Settings 还原默认设置

    在Custom Web Event Recordiing Configuration中:点击Custom Setting按钮。

    窗口中存放对象需要录制的方法,可以对对象的方法进行维护。

    例如:Event——》add——具体对象方法

    Objects pane:(左)显示Web测试对象类和HTML标记的对象列表。

    添加对象:object>add。

    只有HTML标签中的对象可以被删除。从清单中删除一个HTML对象,object>delete。

    Events pane:(右)显示与对象关联的事件清单。

    添加事件:event>add。

    删除事件:enevt>delete。

    Event Name:事件名称

    Listen:触发条件

    1.Always:始终开启该事件

    2.If Handler:由用户触发事件

    3.If Handler or Behavior:由用户或程序触发事件

    4.Never:始终关闭该事件

    Record:是否该事件(操作)

    1.Enabled:运行录制

    2.Disabled:禁止录制

    Reset:初始化设置
    Reset to:可以设置High、Medium和Basic(最基本的标准对象库)
  • QTP Web 操作

    2014-04-16 10:44:35

    QTP如何打开浏览器,并进入网站,关闭浏览器

    '打开IE,进入系统------方法1:快
    SystemUtil.Run"C:\Program Files\Internet Explorer\IEXPLORE.EXE","http://www.baidu.com"

    '打开IE,进入系统------方法2:慢
    SystemUtil.Run"http://www.51testing.com"

    '打开IE,进入系统1后,再跳转到系统2
     SystemUtil.Run"C:\Program Files\Internet Explorer\IEXPLORE.EXE","http://www.51testing.com"
    Browser("micClass:=Browser").Page("micClass:=Page").Sync : wait 2
    Browser("micClass:=Browser").Navigate "http://www.hao123.com"
    checkURL = Trim(Browser("micClass:=Browser").Object.LocationURL)
    print checkURL


    '打开多个浏览器,进入不同页面
    SystemUtil.Run"C:\Program Files\Internet Explorer\IEXPLORE.EXE"
    SystemUtil.Run"C:\Program Files\Internet Explorer\IEXPLORE.EXE"

    Browser("CreationTime:=0").Navigate "http://www.51testing.com"
    Browser("CreationTime:=1").Navigate "http://www.hao123.com"

    '关闭浏览器

    Browser("micClass:=Browser").Close


    部分Browser方法,如Navigate、Back、Home、Refresh等在某些人的机器上是好用的,但在另外一些人的机器上就不好用了。脚本执行到这些方法,并不会抛出错误;而且qtp日志里看到的状态是"done".

        经过一段时间的观察,终于发现这些机器上IE加载项(IE"工具"->"管理加载项")的不同:

        BHOManager Class插件的问题。文件名是BHOManager.dll,部分人的机器上该插件被禁用或删除掉了,猜测原因可能是使用了某些清理ie的工具导致。

        解决该问题的方法很简单:

        如果是被禁用了,只要重新启用即可;如果是被删除掉了,可以重新安装qtp,或者从别处拷贝BHOManager.dll文件过来,用regsvr32 BHOManager.dll注册后就可以了。


     SystemUtil.Run "http://www.51testing.com"  
    Browser("micClass:=Browser").Navigate "http://www.baidu.com"    
    Browser("micClass:=Browser").Page("micClass:=Page").Sync:wait 1

    '打开新的标签
    Browser("micClass:=Browser").OpenNewTab:wait 1
    Dim testHWND 
    testHWND = Browser("creationtime:=1").GetROProperty("HWND")
    Browser("creationtime:=1").Navigate "http://www.qq.com"
    Browser("creationtime:=1").Page("micClass:=Page").Sync:wait 2

    '关闭新的标签
    Browser("hwnd:="&testHWND).close
    Browser("creationtime:=0").Refresh:wait 3

  • 基于PostSharp的AOP框架设计 .

    2012-09-12 09:20:13

    1. AOP已经不是一个什么新名词了,在博客园使用关键字搜索可以查出n多条关于AOP的介绍,这里就不再赘述了。   
    2.   
    3. 在Bruce Zhang's Blog里面有很多关于AOP介绍及其在.net下实现研究,总觉得如果什么都从头来写难免有自造轮子的嫌疑,但是目前也没有很成熟的AOP框架让我们能轻松完成基于AOP架构,不过一直以来都在关注的PostSharp开源项目日趋成熟,目前已发布了PostSharp 1.0 (Beta release 3)。即使如此,也还没能到应用到产品上的时候。   
    4.   
    5. 前段时间一直在封装一个权限系统,时常为如何给调用方提供一个良好的编程接口烦恼,加之前前段时间考虑的日志、异常接管、事务、缓存等等一些横向组件的架构分析,自然就想用AOP技术实现,但是由于实现难度实在不小作罢;这两天又重新学习研究了PostSharp的架构与实现思想,觉得还是尝试一下,将其融入现有框架;   
    6.   
    7. 早在年初就有不少前辈大师就如何使用这个东西撰写过文章,如Q.yuhen的PostSharp - Lightweight Aspect-Oriented System该仁兄下面见解很到位:   
    8.   
    9. 和以往基于 Dynamic Proxy 方式与 AOP 解决方案做个比较。   
    10.   
    11. 由于采用 MSIL Injection,因此静态代码注入的执行效率要高于使用 Reflection Emit。   
    12. 使用 MSBuild Task,使得开发人员可以像使用编译器内置 Attribute 那样使用 AOP。   
    13. 可以拦截任意方法,而 Dynamic Proxy 方式的 AOP 往往采取继承方式来拦截 Virtual 方法。   
    14. 拥有更多的控制权。包括中断执行流程,修改参数和返回值等等。   
    15. 还可以拦截 Field Access、Exception 等操作。   
    16. 无需将对象创建代码改成 "new proxy()",更加透明。   
    17. 可以使用通配符进行多重拦截匹配。   
    18. 静态注入带来的问题更多的是注入代码的质量和调试复杂度。   
    19. 另外有一老外的Using AOP and PostSharp to Enhance Your CodeAB两部分,相当精彩,本文就是在参考这两篇好文的基础上做的。   
    20.   
    21. 我们假设有这么个场景,其实这也是实际业务中很常见的处理方式:有一定单管理模块,具备新增、删除两功能,我们在新增删除的时候必须校验权限,在删除的时候还必须记录日志,出现异常了还必须捕捉并记录异常;   
    22.   
    23. 按以前的写法我们可能很麻烦,我们要如此这般的写:   
    24.   
    25. public class XOrders  
    26.     {  
    27.         public bool Add(string id, string orderName)  
    28.         {  
    29.             try  
    30.             {  
    31.                 if (User.AddEnable)  
    32.                 {  
    33.                     //TODO:新增订单的实现   
    34.                     Console.WriteLine("正在执行新增订单方法的操作,回车继续……");  
    35.                     Console.ReadLine();  
    36.                     Console.WriteLine("您添加订单成功:编号:{0},名称:{1}", id, orderName);  
    37.                     return true;  
    38.                 }  
    39.                 else  
    40.                 {  
    41.                     //   
    42.                 }  
    43.             }  
    44.             catch (Exception)  
    45.             {  
    46.                 //TODO:记录异常的实现   
    47.                 throw;  
    48.             }   
    49.   
    50.             return true;   
    51.   
    52.         }   
    53.   
    54.         public bool Delete(string id)  
    55.         {  
    56.             try  
    57.             {  
    58.                 if (User.DeleteEnable)  
    59.                 {  
    60.                     //TODO:删除订单的实现   
    61.                     Console.WriteLine("您删除订单成功:编号:{0}", id);  
    62.                 }  
    63.                 else  
    64.                 {  
    65.                     //   
    66.                 }   
    67.   
    68.             }  
    69.             catch (Exception)  
    70.             {  
    71.                 //TODO:记录异常的实现   
    72.                 throw;  
    73.             }   
    74.   
    75.             return true;  
    76.         }   
    77.   
    78. 这种写的弊端我就不多说了,有很多先驱都阐述过……   
    79.   
    80. 我要演示的是采用AOP技术的框架原型实现:   
    81.   
    82. 首先我们应该安装PostSharp(一定要安装要不能没办法注入处理代码)   
    83.   
    84. 然后我们实现Orders对象   
    85.   
    86. using System;   
    87.   
    88. namespace PostSharp.Demo  
    89. {  
    90.     public class Orders  
    91.     {  
    92.         [Permission]  
    93.         [Exception]  
    94.         public bool Add(string id, string orderName)  
    95.         {  
    96.             Console.WriteLine("正在执行新增订单方法的操作,回车继续……");  
    97.             Console.ReadLine();  
    98.             Console.WriteLine("您添加订单成功:编号:{0},名称:{1}", id, orderName);  
    99.             return true;  
    100.         }   
    101.   
    102.         [Logger]  
    103.         [Permission]  
    104.         [Exception]  
    105.         public bool Delete(string id)  
    106.         {  
    107.             Console.WriteLine("您删除订单成功:编号:{0}", id);   
    108.   
    109.             return true;  
    110.         }  
    111.     }  
    112. }   
    113.   
    114. 当然还要模拟一个用户资格认证   
    115.   
    116. namespace PostSharp.Demo  
    117. {  
    118.     /// <summary>   
    119.     /// 静态的用户对象,用于存放当前登录用户,成员资格   
    120.     /// </summary>   
    121.     public static class User  
    122.     {  
    123.         private static string _userId;   
    124.   
    125.         public static string UserId  
    126.         {  
    127.             get { return _userId; }  
    128.             set { _userId = value; }  
    129.         }   
    130.   
    131.         public static bool AddEnable  
    132.         {  
    133.             get  
    134.             {  
    135.                 return (_userId.ToLower() == "admin");  
    136.             }  
    137.         }   
    138.   
    139.         public static bool DeleteEnable  
    140.         {  
    141.             get  
    142.             {  
    143.                 return (_userId.ToLower() == "admin");  
    144.             }  
    145.         }  
    146.     }  
    147. }   
    148.   
    149. 再然后我们实现权限控制方面PermissionAttribute,日志方面LoggerAttribute,异常处理方面ExceptionAttribute……   
    150.   
    151. PermissionAttribute   
    152.   
    153. using System;  
    154. using PostSharp.Laos;   
    155.   
    156. namespace PostSharp.Demo  
    157. {  
    158.     [Serializable]  
    159.     [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]  
    160.     public class PermissionAttribute : OnMethodBoundaryAspect  
    161.     {  
    162.         public override void OnEntry(MethodExecutionEventArgs eventArgs)  
    163.         {  
    164.             if (!User.AddEnable)  
    165.             {  
    166.                 Console.WriteLine("用户:【{0}】没有权限:【{1}】", User.UserId, eventArgs.Method);  
    167.                 eventArgs.FlowBehavior = FlowBehavior.Return;  
    168.             }   
    169.   
    170.         }  
    171.     }  
    172. }   
    173.   
    174. LoggerAttribute   
    175.   
    176. using System;  
    177. using PostSharp.Laos;   
    178.   
    179. namespace PostSharp.Demo  
    180. {  
    181.     [Serializable]  
    182.     [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]  
    183.     public sealed class LoggerAttribute : OnMethodInvocationAspect  
    184.     {  
    185.         public override void OnInvocation(MethodInvocationEventArgs eventArgs)  
    186.         {  
    187.             DateTime time = DateTime.Now;  
    188.             string log = "时间:{0},操作人员:{1},操作:{2}!";   
    189.   
    190.             object[] arg = eventArgs.GetArguments();   
    191.   
    192.             log = String.Format(log, time, User.UserId, "删除Id为" + arg[0].ToString() + "的订单!");   
    193.   
    194.             System.IO.File.WriteAllText("C://Log.Txt", log);  
    195.         }  
    196.     }  
    197. }   
    198.   
    199. ExceptionAttribute   
    200.   
    201. using System;  
    202. using PostSharp.Laos;   
    203.   
    204. namespace PostSharp.Demo  
    205. {  
    206.     [Serializable]  
    207.     [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]  
    208.     public class ExceptionAttribute : OnExceptionAspect  
    209.     {  
    210.         public override void OnException(MethodExecutionEventArgs eventArgs)  
    211.         {  
    212.             Console.WriteLine("程序出现异常:{0}", eventArgs.Exception.Message);  
    213.             eventArgs.FlowBehavior = FlowBehavior.Return;  
    214.         }  
    215.     }  
    216. }   
    217.   
    218.     
    219.   
    220. 然后再用控制台程序测试下能不能成功   
    221.   
    222. Orders order = new Orders();  
    223.             Console.WriteLine("请输入用户名:");  
    224.             User.UserId = Console.ReadLine();  
    225.             Console.WriteLine("请输入密码:");  
    226.             Console.ReadLine();  
    227.             string id;   
    228.   
    229.             LRedo:  
    230.             Console.WriteLine("请输入您要执行的操作:新增(A),删除(D),退出(X)");   
    231.   
    232.             string opt = Console.ReadLine();   
    233.   
    234.             if (opt.ToLower() == "a")  
    235.             {  
    236.                 Console.WriteLine("请输入订单编号:");  
    237.                 id = Console.ReadLine();   
    238.   
    239.                 Console.WriteLine("请输入订单名称:");  
    240.                 string name = Console.ReadLine();  
    241.                 order.Add(id, name);  
    242.             }  
    243.             else if (opt.ToLower() == "d")  
    244.             {  
    245.                 Console.WriteLine("请输入订单编号:");  
    246.                 id = Console.ReadLine();  
    247.                 order.Delete(id);  
    248.             }  
    249.             else if (opt.ToLower() == "x")  
    250.             {  
    251.             }  
    252.             else  
    253.             {  
    254.                 Console.WriteLine("您的输入不正确,请重新输入!");  
    255.                 goto LRedo;  
    256.             }   
    257.   
    258.             Console.WriteLine("按任意键退出……");  
    259.             Console.ReadLine();   
    260.   
    261. 写完这些我们再反编译一下生成的exe文件,发现里面的Orders成了这模样了,神奇了?   
    262.   
    263. public class Orders  
    264. {  
    265.     // Methods   
    266.     static Orders()  
    267.     {  
    268.         if (!~PostSharp~Laos~Implementation.initialized)  
    269.         {  
    270.             LaosNotInitializedException.Throw();  
    271.         }  
    272.         ~PostSharp~Laos~Implementation.~targetMethod~1 = methodof(Orders.Add);  
    273.         ~PostSharp~Laos~Implementation.~aspect~1.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~1);  
    274.         ~PostSharp~Laos~Implementation.~targetMethod~5 = methodof(Orders.Delete);  
    275.         ~PostSharp~Laos~Implementation.~aspect~5.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~5);  
    276.         ~PostSharp~Laos~Implementation.~targetMethod~4 = methodof(Orders.Delete);  
    277.         ~PostSharp~Laos~Implementation.~aspect~4.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~4);  
    278.         ~PostSharp~Laos~Implementation.~targetMethod~3 = methodof(Orders.Add);  
    279.         ~PostSharp~Laos~Implementation.~aspect~3.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~3);  
    280.         ~PostSharp~Laos~Implementation.~targetMethod~2 = methodof(Orders.Delete);  
    281.         ~PostSharp~Laos~Implementation.~aspect~2.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~2);  
    282.     }   
    283.   
    284.     private bool ~Delete(string id)  
    285.     {  
    286.         Console.WriteLine("您删除订单成功:编号:{0}", id);  
    287.         return true;  
    288.     }   
    289.   
    290.     public bool Add(string id, string orderName)  
    291.     {  
    292.         bool ~returnValue~1;  
    293.         MethodExecutionEventArgs ~laosEventArgs~7;  
    294.         try  
    295.         {  
    296.             object[] ~arguments~6 = new object[] { id, orderName };  
    297.             ~laosEventArgs~7 = new MethodExecutionEventArgs(methodof(Orders.Add, Orders), this, ~arguments~6);  
    298.             ~PostSharp~Laos~Implementation.~aspect~1.OnEntry(~laosEventArgs~7);  
    299.             if (~laosEventArgs~7.FlowBehavior == FlowBehavior.Return)  
    300.             {  
    301.                 return (bool) ~laosEventArgs~7.ReturnValue;  
    302.             }  
    303.             try  
    304.             {  
    305.                 Console.WriteLine("正在执行新增订单方法的操作,回车继续……");  
    306.                 Console.ReadLine();  
    307.                 Console.WriteLine("您添加订单成功:编号:{0},名称:{1}", id, orderName);  
    308.                 ~returnValue~1 = true;  
    309.             }  
    310.             catch (Exception ~exception~2)  
    311.             {  
    312.                 object[] ~arguments~3 = new object[] { id, orderName };  
    313.                 MethodExecutionEventArgs ~laosEventArgs~4 = new MethodExecutionEventArgs(methodof(Orders.Add, Orders), this, ~arguments~3);  
    314.                 ~laosEventArgs~4.Exception = ~exception~2;  
    315.                 ~PostSharp~Laos~Implementation.~aspect~3.OnException(~laosEventArgs~4);  
    316.                 switch (~laosEventArgs~4.FlowBehavior)  
    317.                 {  
    318.                     case FlowBehavior.Continue:  
    319.                         goto Label_0145;   
    320.   
    321.                     case FlowBehavior.Return:  
    322.                         ~returnValue~1 = (bool) ~laosEventArgs~4.ReturnValue;  
    323.                         goto Label_0145;  
    324.                 }  
    325.                 throw;  
    326.             }  
    327.         Label_0145:  
    328.             ~laosEventArgs~7.ReturnValue = ~returnValue~1;  
    329.             ~PostSharp~Laos~Implementation.~aspect~1.OnSuccess(~laosEventArgs~7);  
    330.             ~returnValue~1 = (bool) ~laosEventArgs~7.ReturnValue;  
    331.         }  
    332.         catch (Exception ~exception~5)  
    333.         {  
    334.             ~laosEventArgs~7.Exception = ~exception~5;  
    335.             ~PostSharp~Laos~Implementation.~aspect~1.OnException(~laosEventArgs~7);  
    336.             switch (~laosEventArgs~7.FlowBehavior)  
    337.             {  
    338.                 case FlowBehavior.Continue:  
    339.                     return ~returnValue~1;   
    340.   
    341.                 case FlowBehavior.Return:  
    342.                     return (bool) ~laosEventArgs~7.ReturnValue;  
    343.             }  
    344.             throw;  
    345.         }  
    346.         finally  
    347.         {  
    348.             ~laosEventArgs~7.ReturnValue = ~returnValue~1;  
    349.             ~PostSharp~Laos~Implementation.~aspect~1.OnExit(~laosEventArgs~7);  
    350.             ~returnValue~1 = (bool) ~laosEventArgs~7.ReturnValue;  
    351.         }  
    352.         return ~returnValue~1;  
    353.     }   
    354.   
    355.     [DebuggerNonUserCode]  
    356.     public bool Delete(string id)  
    357.     {  
    358.         bool ~returnValue~2;  
    359.         MethodExecutionEventArgs ~laosEventArgs~8;  
    360.         try  
    361.         {  
    362.             object[] ~arguments~7 = new object[] { id };  
    363.             ~laosEventArgs~8 = new MethodExecutionEventArgs(methodof(Orders.Delete, Orders), this, ~arguments~7);  
    364.             ~PostSharp~Laos~Implementation.~aspect~2.OnEntry(~laosEventArgs~8);  
    365.             if (~laosEventArgs~8.FlowBehavior == FlowBehavior.Return)  
    366.             {  
    367.                 return (bool) ~laosEventArgs~8.ReturnValue;  
    368.             }  
    369.             try  
    370.             {  
    371.                 Delegate delegateInstance = new ~PostSharp~Laos~Implementation.~delegate~0(this.~Delete);  
    372.                 object[] arguments = new object[] { id };  
    373.                 MethodInvocationEventArgs eventArgs = new MethodInvocationEventArgs(delegateInstance, arguments);  
    374.                 ~PostSharp~Laos~Implementation.~aspect~5.OnInvocation(eventArgs);  
    375.                 ~returnValue~2 = (bool) eventArgs.ReturnValue;  
    376.             }  
    377.             catch (Exception ~exception~3)  
    378.             {  
    379.                 object[] ~arguments~4 = new object[] { id };  
    380.                 MethodExecutionEventArgs ~laosEventArgs~5 = new MethodExecutionEventArgs(methodof(Orders.Delete, Orders), this, ~arguments~4);  
    381.                 ~laosEventArgs~5.Exception = ~exception~3;  
    382.                 ~PostSharp~Laos~Implementation.~aspect~4.OnException(~laosEventArgs~5);  
    383.                 switch (~laosEventArgs~5.FlowBehavior)  
    384.                 {  
    385.                     case FlowBehavior.Continue:  
    386.                         goto Label_0160;   
    387.   
    388.                     case FlowBehavior.Return:  
    389.                         ~returnValue~2 = (bool) ~laosEventArgs~5.ReturnValue;  
    390.                         goto Label_0160;  
    391.                 }  
    392.                 throw;  
    393.             }  
    394.         Label_0160:  
    395.             ~laosEventArgs~8.ReturnValue = ~returnValue~2;  
    396.             ~PostSharp~Laos~Implementation.~aspect~2.OnSuccess(~laosEventArgs~8);  
    397.             ~returnValue~2 = (bool) ~laosEventArgs~8.ReturnValue;  
    398.         }  
    399.         catch (Exception ~exception~6)  
    400.         {  
    401.             ~laosEventArgs~8.Exception = ~exception~6;  
    402.             ~PostSharp~Laos~Implementation.~aspect~2.OnException(~laosEventArgs~8);  
    403.             switch (~laosEventArgs~8.FlowBehavior)  
    404.             {  
    405.                 case FlowBehavior.Continue:  
    406.                     return ~returnValue~2;   
    407.   
    408.                 case FlowBehavior.Return:  
    409.                     return (bool) ~laosEventArgs~8.ReturnValue;  
    410.             }  
    411.             throw;  
    412.         }  
    413.         finally  
    414.         {  
    415.             ~laosEventArgs~8.ReturnValue = ~returnValue~2;  
    416.             ~PostSharp~Laos~Implementation.~aspect~2.OnExit(~laosEventArgs~8);  
    417.             ~returnValue~2 = (bool) ~laosEventArgs~8.ReturnValue;  
    418.         }  
    419.         return ~returnValue~2;  
    420.     }  
    421. }   
  • 使用PostSharp在.NET平台上实现AOP

    2012-08-21 11:05:14

     

    摘要

    本文首先介绍AOP(面向方面编程)的相关概念及理论,然后介绍如何使用PostSharp框架在.NET平台上实现AOP,最后对PostSharp的机制及AOP的优劣进行一个简单的分析。

    AOP(Aspect-Oriented Programming)

    AOP的基本定义及作用

    根据维基百科的定义,“AOP(Aspect-Oriented Programming)是一种将函数的辅助性功能与业务逻辑相分离的编程泛型(programming paradigm),其目的是将横切关注点(cross-cutting concerns)分离出来,使得程序具有更高的模块化特性。AOP是面向方面软件开发(Aspect-Oriented Software Development)在编码实现层面上的具体表现(面向方面软件开发AOSD是一个囊括面向方面分析、面向方面设计和面向方面编程等一系列概念的完整工程系统——笔者注)。AOP包括编程模型和具体用于实现AOP的框架两部分。”

    下面对上文提到的定义进行一些解释。

    在当前大多数支持面向对象的编程语言中(例如C#,Java等),函数(Function)是表述程序功能的最小单元,而一个函数的代码层面往往同时含有核心业务逻辑和辅助性功能。核心业务逻辑指一个函数本身主要要实现的业务功能,例如在一个在线电子商务系统中,“PlaceOrder”函数其核心业务逻辑是“下订单”,而“UpgradeMember”函数其核心业务是“提升一个会员的等级”。但是,一个函数除了核心业务代码外,往往还会有一些辅助性功能代码,如事务处理、缓存处理、日志记录、异常处理等等。而这些辅助性功能一般会存在于大多数甚至所有业务函数中,即形成AOSD中所谓的横切关注点,如图1所示。

    image

    图1、横切关注点示意

    横切关注点的存在,造成了如下几个问题。

    • 代码编写和维护困难。

    横切关注点不仅横切各个函数,还可能在不同类甚至不同工程间横切,使得同一个辅助功能(如事务处理)分散到各处,如果要增加新函数时要时刻注意别忘了添加所有需要的横切代码。另外,如果需要对其进行修改,则需要到所有被横切的函数中修改,维护难度极大。

    • 引入大量冗余代码

    由于同一个辅助性功能的代码几乎是完全相同的,这样就会令同样的代码在各个函数中出现,引入了大量冗余代码。

    • 降低代码质量

    横切关注点令核心业务代码和辅助性代码杂糅纠缠在一起,破坏了业务函数代码的纯净性和函数职责的单一性,引入了大量繁杂的代码和结构,使得代码质量下降。

    所以,AOP的核心思想就是在编写代码时将横切关注点分离出来,形成单独的模块,单独编写和维护,不再分散到各业务函数,使得业务函数仅包含核心业务代码,从而解决以上问题。而在程序编译或运行时,通过某些手段(下文介绍)令独立的横切关注点代码可以与核心业务代码自动协作运行,完成本身需要的功能。

    AOP相关术语

    方面(Aspect)

    一个Aspect指上文提到的横切关注点在编程中的具体实现,它包含一个横切关注点所需要实现的具体辅助功能。具体到代码中,Aspect可能会被实现为一个Class,一个Function或一个Attribute。

    连接点(Join Point)

    连接点指一个业务函数代码中的一个位置或时机,在这个位置或时机允许Aspect代码插入执行。常见的连接点有进入函数执行业务代码前时、执行完全部业务代码离开函数前、当有异常发生在异常处理代码执行前等等。

    织入(Weaving)

    织入指将指定的Aspect代码插入指定连接点,使得横切代码与业务代码交合在一起。

    连接模型(JPM, Join Point Model)

    JPM主要是面向方面语言(如AspectJ)或面向方面框架的语义模型。主要包含以下三点:有哪些可用连接点,如何指定连接点以及如何织入。

    AOP的实现方式

    一般来说,在纯编译型语言(如C、C++)等语言中实现AOP非常困难,必须完全从编译器角度入手。本文主要讨论托管型语言(如C#,Java)中AOP的实现方式。AOP的主要实现方式有编译时AOP和运行时AOP两种,下面分别介绍。

    编译时AOP(静态织入)

    编译时AOP的实现思想是给语言的编译器做扩展,使得在编译程序的时候编译器将相应的Aspect代码织入到业务代码的指定连接点,输出整合的结果。图2是编译时AOP的示意图(以.NET平台为例)。

    image

    图2、编译时AOP示意图

    如图2所示,当使用静态织入时,带AOP扩展的编译器会在编译时将Aspect代码织入业务函数代码,形成整合后的IL,然后交由CLR运行。

    运行时AOP(动态织入)

    运行时AOP如图3所示。image

    图3、运行时AOP的示意图

    如图3所示,运行时AOP的实现方式是将扩展添加到运行虚拟机而不是编译器。Aspect和业务代码分别独立编译,而在运行时由虚拟机在必要时进行织入。

    PostSharp

    PostSharp简介

    PostSharp是一个用于在.NET平台上实现AOP的框架,是我比较常用的一个AOP框架,官方网站为http://www.sharpcrafters.com。目前最新版本为2.0,但是2.0的license不再免费,因此个人建议下载1.5版,同时下文都是基于PostSharp1.5。

    PostSharp使用静态织入方式实现AOP,其连接点非常丰富,使用简单,而且相对其它一些.NET平台上的AOP框架来说,PostSharp较为轻量级,但是功能却一点也不逊色,因此是我比较喜欢的一个AOP框架。更多关于PostSharp的介绍请参看其官方网站。

    另外使用PostSharp与其它框架不太一样的是一定要下载安装包安装,只引用类库是不行的,因为上文说过,AOP框架需要为编译器或运行时添加扩展。

    使用PostSharp实现AOP示例

    这一节将通过一个例子演示如何使用PostSharp在.NET平台上实现AOP。这个例子将通过AOP为核心业务函数增加日志记录功能。

    新建项目

    首先新建一个C#的WinForm应用程序,如图4所示,这里将工程命名为“PostSharpExample”。

    image

    图4、新建项目

    编写核心业务函数

    首先我们来编写核心业务。当然这里不存在真正的业务,我们只是模拟一个而已。将要模拟的核心业务是预定房间。先构建一个如图5所示的简单UI。

    image

    图5、UI界面

    下面我们为项目增加一个“CoreBusiness”类,并在其中添加“Subscribe”方法。代码如下:

    using System;
    
    namespace PostSharpExample
    {
        public class CoreBusiness
        {
            public static void Describe(string memberName, string roomNumber)
            {
                System.Windows.Forms.MessageBox.Show(String.Format("尊敬的会员{0},恭喜您预定房间{1}成功!", memberName, roomNumber), "提示");
            }
        }
    }

    可以看到,这里Subscribe方法仅仅是输出一个提示框。当然,在真正项目中这种输出型代码不应该写在业务逻辑中,这里这样写主要是为了演示方便。然后,我们在Form1中调用Subscribe业务方法:

    using System;
    using System.Windows.Forms;
    
    namespace PostSharpExample
    {
        public partial class Form1 : Form. {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void BTN_SUBSCRIBE_Click(object sender, EventArgs e)
            {
                if (!String.IsNullOrEmpty(TXB_NAME.Text.Trim()) && !String.IsNullOrEmpty(TXB_ROOM.Text.Trim()))
                    CoreBusiness.Describe(TXB_NAME.Text.Trim(), TXB_ROOM.Text.Trim());
                else
                    MessageBox.Show("信息不完整","提示");
            }
        }
    }

    运行程序就可以看到相应的效果:

    image

    图6、预定房间成功演示效果

    使用AOP增加日志记录功能

    现在加入我们要为程序添加日志功能,记录业务函数的执行情况。这里我们假定需要将日志记录到纯文本文件中,首先我们完成日志记录工具类,LoggingHelper。

    using System;
    using System.IO;
    
    namespace PostSharpExample
    {
        class LoggingHelper
        {
            private const String _errLogFilePath = @"log.txt";
    
            public static void Writelog(String message)
            {
                StreamWriter sw = new StreamWriter(_errLogFilePath, true);
                String logContent = String.Format("[{0}]{1}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), message);
                sw.WriteLine(logContent);
                sw.Flush();
                sw.Close();
            }
        }
    }

    如果不使用AOP,则我们要为包括Subscribe在内的每一个方法在核心业务代码的前后插入日志记录代码(Writelog),我们看看使用PostSharp如何将这种横切关注点分离出来。因为要使用PostSharp,所以要先添加对PostSharp库文件的引用,安装过PostSharp后,在系统可引用项中会多出“PostSharp.Laos”、“PostSharp.Public”和“PostSharp.AspNet”,这里我们做的是Winform程序,所以只需添加对“PostSharp.Laos”和“PostSharp.Public”的引用即可。

    下面我们就要写Aspect了,PostSharp的Aspect是使用Attribute实现的,下面是我实现的日志记录Aspect代码。

    using System;
    using PostSharp.Laos;
    
    namespace PostSharpExample
    {
        [Serializable]
        [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
        public sealed class LoggingAttribute : OnMethodBoundaryAspect
        {
            public string BusinessName { get; set; }
    
            public override void OnEntry(MethodExecutionEventArgs eventArgs)
            {
                LoggingHelper.Writelog(BusinessName + "开始执行");
            }
    
            public override void OnExit(MethodExecutionEventArgs eventArgs)
            {
                LoggingHelper.Writelog(BusinessName + "成功完成");
            }
        }
    }

    我们约定每个Aspect类的命名必须为“XXXAttribute”的形式。其中“XXX”就是这个Aspect的名字。PostSharp中提供了丰富的内置“Base Aspect”以便我们继承,其中这里我们继承“OnMethodBoundaryAspect ”,这个Aspect提供了进入、退出函数等连接点方法。另外,Aspect上必须设置“[Serializable] ”,这与PostSharp内部对Aspect的生命周期管理有关,具体为什么请参看这里

    我们的LoggingAttribute非常简单,就是在进入(Entry)和离开(Exit)函数时分别记录日志到log文件。现在我们把这个Aspect应用到业务方法上:

    [Logging(BusinessName="预定房间")]
    public static void Describe(string memberName, string roomNumber)
    {
        System.Windows.Forms.MessageBox.Show(String.Format("尊敬的会员{0},恭喜您预定房间{1}成功!", memberName, roomNumber), "提示");
    }

    可以看到,应用Aspect非常简单,就是将相应的Attribute加到业务方法上面。现在我们再运行预定房间程序,结果和上次没什么两样,但是如果我们打开程序目录,会看到多了一个“log.txt”文件,里面记录有类似图7的内容。

    image

    图7、日志内容

    可以看到,我们已经通过AOP实现了日志记录功能。通过AOP将横切关注点分离出来后,日志记录的代码都放在LoggingAttribute里,需要修改只要修改一处即可。同时,业务方法仅含有业务代码,这样大大提高了程序代码的可读性和可维护性。

    对PostSharp运行机制的简要分析

    上文已经说到,PostSharp使用的是静态织入技术,下面我们分析一下PostSharp是如何实现的。

    首先,当安装PostSharp时,它自动为Visual Studio编译器添加了AOP扩展。如果仔细观察PostSharpExample编译信息,会发现有这么两行:

    image

    图8、PostSharp编译信息

    很明显,在.NET Complier编译完成后,下面PostSharp又做了一部分工作,这部分工作就是静态织入的过程。如果我们用.NET Reflector查看PostSharpExample.exe中Subscribe方法的反编译代码,会发现多了很多东西:

    image

    图9、织入Aspect后的Describe代码(由.NET Reflector反编译)

    这些多出来的代码,就是PostSharp静态织入进去的。当然,这些代码在每次编译完成后,PostSharp都会重新织入一次,所以整个过程对程序员是透明的,我们只需维护纯净的业务代码和Aspect代码即可。

    使用PostSharp的优点和缺点(即使用AOP的优点和缺点)

    总体来说,使用PostSharp,将会带来如下优点:

    • 横切关注点单独分离出来,提高了代码的清晰性和可维护性。
    • 只要在Aspect中编写辅助性功能代码,在一定程度上减少了工作量和冗余代码。

    当然,使用PostSharp也不是没有缺点,主要缺点有如下两方面:

    • 增加了调试的难度。
    • 相比于不用AOP的代码,运行效率有所降低。

    所以,对于是否引入AOP,请根据项目具体情况,权衡而定。

    对于PostSharp的进一步学习

    本文只是简要介绍了PostSharp以及实现了一个小例子,并不打算详细完整地介绍PostSharp的方方面面,而只想起到一个抛砖引玉的作用。PostSharp还有非常丰富的功能等待各位学习,因此,如果您对PostSharp十分有兴趣,想进一步学习,请参看PostSharp官方参考文档

  • bugzilla 安装

    2012-02-14 16:30:30

    bugzilla安装笔记

    今天终于把bugzilla装上去了!庆祝!呵呵

    perl的模块装了好几天,不是缺这就是缺那,现在终于搞定了!

    简单记一下安装步骤:

    一、安装Apache

             安装Apache比较简单

            1、下载源码包:http://download.chinaunix.net/down.php?id=114&ResourceID=66&site=1

            2、解包:tar -jxvf apapche-httpd-2.2.0.tar.bz2

            3、安装:cd apache-http*

                            ./configure --prefix=/usr/local/apache2 --enable-module=so

                            make      然后再      makeinstall       完成安装

            4、配置:vi /usr/local/apache2/conf/httpd.conf      添加: AddHandler cgi-script. .cgi

                                                                                             <Directory "/var/www/bugzilla/">
                                                                                                        Options All
                                                                                                        AllowOverride Limit
                                                                                                        Order allow,deny
                                                                                                        Allow from all    
                                                                                             </Directory>                                                  

    二、安装mysql

            1、下载源码包:http://download.chinaunix.net/down.php?id=24933&ResourceID=7159&site=1

            2、解包:tar -zxvf mysql-5.0.32.tar.gz

            3、安装:cd mysql-5.0*

                            ./configure --prefix=/usr/local/mysql

                            make       然后      make install      完成安装

            4、初始化mysql:/usr/local/mysql/bin/mysql_install_db --user=root

                                        /usr/local/mysql/bin/mysqld_safe --user=root &      (启动mysql服务端)

                                        /usr/local/mysql/bin/mysql --user=root      ( 启动mysql客户端)

                                        use mysql; (选择系统数据库)  

                                        update user set Password=password('YourPassword') where User='root';(设置数据库root密码)

                                        insert into user (User,Host,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Index_priv,Alter_priv,Create_priv,Drop_priv,Grant_priv,Reload_priv,Shutdown_priv,Process_priv,File_priv) values('mysql','',password('YourPassword'),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); (增加数据库用户)

    三、安装Perl

            1、下载源码包:http://download.chinaunix.net/down.php?id=78&ResourceID=44&site=1

            2、解包:tar -jvxf perl-5.8.8.tar.bz2

            3、安装:rm -f config.sh Policy.sh

                            sh Configure -de

                            make      然后 make test      通过后再 make install

            (类似的开发工具包建议在安装系统时就装上,以后会少很多麻烦。假如这里编译出现问题,根据提示,找到相应的包装上就可以了。个人比较喜欢ubuntu的apt-get install,没这么多麻烦~)

    四、安装perl模块(这才是最烦人的地方)

            1、首先初始化perl的cpan:perl -MCPAN -e 'shell'

                  命令执行以后会进行一系列的配置,都有提示这一步是比较简单的,一般一路回车就可以了,最后会选模块搜索服务器,这个在大陆比较快(http://cpan.linuxforum.net/)把它选在前面就可以了。

                 cpan是Comprehensive Perl Archive Network的英文缩写,一个巨大的网络资源库。有了它后面安装perl的模块会相对简单一些。

            2、安装bugzilla所需的perl模块

            必要模块:    

            1. CGI 2.93 or CGI 3.11 if using mod_perl
            2. Date::Format (2.21)
            3. DBI (1.41)
            4. DBD::mysql (2.9003) if using MySQL
            5. DBD::Pg (1.45) if using PostgreSQL
            6. File::Spec (0.84)
            7. Template (2.12)
            8. Email::Send (2.00)
            9. Email::MIME::Modifier (any)

           可选模块:

            1. GD (1.20) for bug charting
            2. Template::Plugin::GD::Image (1.20) for Graphical Reports
            3. Chart::Base (1.0) for bug charting
            4. GD::Graph (any) for bug charting
            5. GD::Text (any) for bug charting
            6. XML::Twig (any) for bug import/export
            7. MIME::Parser (5.406) for bug import/export
            8. LWP::UserAgent (any) for Automatic Update Notifications
            9. PatchReader (0.9.4) for pretty HTML view of patches
           10. Image::Magick (any) for converting BMP image attachments to PNG
           11. Net::LDAP (any) for LDAP Authentication
           12. SOAP::Lite (any) for the web service interface
           13. HTML::Parser (3.40) for More HTML in Product/Group Descriptions
           14. HTML::Scrubber (any) for More HTML in Product/Group Descriptions
           15. Email::MIME::Attachment::Stripper (any) for Inbound Email
           16. Email::Reply (any) for Inbound Email
           17. mod_perl2 (1.999022) for mod_perl
           18. CGI (2.93) for mod_perl
           19. Apache::DBI (0.96) for mod_perl2

            有点汗~~我是被这些模块,折腾了几天了~~

            不过,别急~ perl提供了很简便的模块安装方式:perl -MCPAN -e 'install 模块名' 。比如安装bugzilla的模块,执行这个命令就可以了(理论上的):perl -MCPAN -e 'install "Bundle::Bugzilla"' 。不过,一般不会成功(上面个命令是将所有模块一起装,还可以将各模块分开装,比如:perl -MCPAN -e 'install GD::Graph"')。

            经过上面的步骤,应该可以装下一些perl模块了。运气好,全部都可以装上。假如您和我一样属于运气超差的那一类,那就接着下面的步骤走:

            首先分析安装失败的原因:

            失败的原因无外乎有二:一是缺少相关软件包;二是操作、配置不正确。

            排开第二项,要解决的就是第一项了。前几天之所以失败,原因就在于贪图便宜,一直用perl -MCPAN -e 'install 模块名' ,这样的方式来装,结果总是失败,尤其是GD模块,装不上,还不知道原因。perl的cpan虽然会分析安装关联,但是她只局限于自己的范围内关联,不是她范内的事,她就不管了。后来终于灵机一动,手动安装——这样可以看出出错信息,知道缺少什么,然后再去找来装上就OK了。

            手动安装,先要到网上把bugzilla所需的模块都下下来(http://download.chinaunix.net这里您要的都有,强!)然后分别解压,安装就OK了。如果中途遇到出错,根据出错提示,很容易判断出出错的原因,一般会是缺少其他的工具,去网上找下来先装她就OK了。要补充一句的是,perl模块的安装稍微有点不同。./configure换成perl Makefile.PL 后面一样了make      然后 make install

            手动安装+自动安装,不能装的都装上了。高兴,呵呵!

    五、安装sendmail或者(qmail)

              红帽sendmail默认已经可以用了,如果没有,建议安装qmail。

    六、安装bugzilla(吐口气,很简单了~)

            1、下载源码包:http://ftp.mozilla.org/pub/mozilla.org/webtools/bugzilla-2.22.2.tar.gz

            2、解包:tar zxvf bugzilla-2*

            3、配置:mkdir /var/www/bugzilla     

    (创建bugzilla目录)

                            cd bugzilla*         

     然后           mv * /var/www/bugzilla     

    (移动bugzilla文件到apache服务目录)

                            chmod -R 777 /var/www/bugzilla     

    (改变权限)

                            /var/www/bugzilla/checksetup.pl

    (检查安装,如果上一步的perl模块没有装好,这里会提示)

                            vi /var/www/bugzilla/localconfig

    修改以下内容:

                                               $db_host = "localhost";
                                               $db_name = "bugs";
                                               $db_user = "mysql";
                                               $db_pass = "YourPassword";

                            /var/www/bugzilla/checksetup.pl

    (自动创建数据库,设置目录权限,完了以后,要你输入bugzilla管理员的邮箱,密码等,这是登录用的,要记住。)

                           

    再来一次 /var/www/bugzilla/checksetup.pl 确认已经成功

    哈哈,赶快登录你的bugzilla吧!(第一次登录会要求你做一些配置,都有提示,按照提示做就OK啦!俺要睡觉了,晚安~~)                                                 

        


    http://hi.baidu.com/windinthewillows/blog/item/51c01c82c78f13a30df4d24b.html
  • ruby 安装

    2011-09-28 12:58:03

    编写背景:
    有半年多没有写
    Ruby+Waitr的自动化测试脚本了,今天开始封网测试机器会被关闭,赶着这段国庆空闲时间,好好整整开源的自动化测试工具,争取淮海战役打完后,组织测试组的帅哥美女们开始写些自动化测试代码,为明年的测试工作效率提升打基础。
    好久没装,今天费了一上午终于给装上了,这次要好好整理出文档才行,便于下次使用时可查阅,同时共享给对这方面感兴趣的测试同行。
    一、工具介绍:
    Ruby Ruby是面向对象的编程语言,它追求的是[font=ˎ̥]简便快捷的面向对象编程[font=ˎ̥]Ruby是解释型语言,因此不需编译即可快捷地编程。同时Ruby具有类似Perl的强大的文本处理功能,它可并不只是个玩具,您可以用它来进行实用的编程。此外,您还可以很方便地使用[font=ˎ̥]C语言来扩展Ruby的功能,因此可以把她当作各种库的前端来使用。
    Watir Watir( Web Application Testing in Ruby) 是一个优秀的开源工具,用于开发基于Web 应用的自动化测试程序。它使用Ruby 脚本语言,提供了轻量级的自动化测试程序框架和丰富的开发库,有效地加速了自动化测试程序开发。
    Watir 的主要特性以及使用 Watir 开发自动化程序的优势
    Watir是一个轻量级的用于开发基于Web应用的自动化测试框架,它基于Ruby语言,提供了丰富的开发库,简化了自动化测试程序开发。下面我们总结了Watir的主要一些优良特性:
    l         [font=ˎ̥]Watir 基于[font=ˎ̥] Ruby 语言。[font=ˎ̥] Ruby 是面向对象语言,功能强大,简单易用。程序解释执行不用编译;
    l         [font=ˎ̥]Watir 支持多种操作系统平台,包括[font=ˎ̥] Windows, Mac, Linux ;同时支持多种主流浏览器,如[font=ˎ̥] IE, Firefox, Chrome
    l         [font=ˎ̥]Watir 提供了丰富的开发库,封装了包括浏览器窗口[font=ˎ̥] windows[font=ˎ̥]button, link, dialog, image, table, div 等绝大多数[font=ˎ̥] HTML 对象类型,方便测试人员快速构建自动化测试程序。
    l         [font=ˎ̥]Ruby 提供了强大的交互命令工具[font=ˎ̥] IRB[font=ˎ̥]Interactive Ruby Shell[font=ˎ̥], [font=ˎ̥] Watir 程序开发中,我们使用[font=ˎ̥] IRB 调试代码。别于传统调试方法,测试人员可以就单独一条命令或者一段程序进行调试,从而能够快速定位错误,节省调试时间。
    l         [font=ˎ̥]Ruby 提供了[font=ˎ̥] Test::Unit 单元测试框架,通过继承该框架,我们可以对测试用例,测试用例集[font=ˎ̥] (Test Suites) 进行灵活方便地组合和调用,并且可利用断言[font=ˎ̥] (Assertion) 来验证测试结果。
    l         其他脚本语言如[font=ˎ̥] Perl, Python, Shell 等也可以很好地集成到[font=ˎ̥] Watir 程序中。
    l         [font=ˎ̥]Watir 程序在运行时,允许测试人员在该测试机器上访问其他网页或者进行其他操作而不会影响到对象识别的结果。
    二、开源自动化测试工具组合:Ruby+Watir安装
    安装准备:
    1.       工具安装包准备:
    Ruby官方下载地址:http://www.ruby-lang.org/zh_cn/downloads/,稳定版本Ruby 1.8.6
    Watir下载地址:http://rubyforge.org/frs/?group_id=104&release_id=28016,建议装watir 1.5.2
    Firefox下载地址:http://www.hacker.cn/Get/gjrj/06102608545293311.shtml,建议装2.0
    Gem下载地址:http://rubyforge.org/frs/?group_id=104&release_id=28016
    建议装:rubygems-update-1.3.4.gem

    Firefox插件jsshfirebugfirewatir下载
    Jssh下载地址:用Google搜索,之前找的忘记是那了,建议装jssh-WINNT-2[1].x.xpi
    Firebug下载地址:用google搜索,之前找的忘记是那了,建议装firebug-1.05
    Firewatir下载地址:http://code.google.com/p/firewatir/downloads/list,建议装firewatir-1.1
    2.       安装步骤:
    Ø         安装环境:Windows xp
    Ø         安装ruby,直接点击rubyexe安装文件即可
    Ø         安装firefox,直接点击exe安装文件即可
    Ø         安装firefox插件,安装方法:打开firefox浏览器,点击“文件”/“打开”,选择插件文件名,安装即可;提醒:需要安装插件有:jsshfirebug
    Ø         安装firewatir,安装方法:点击“开始”/“运行”,在页面输入命令:cmd,进入DOS命令操作界面;进入ruby安装的目录,输入命令:gem install firewatir-1.1.gem
    Ø         安装watir
    1)      点击“开始”/“运行”,在页面输入命令:cmd,进入DOS命令操作界面,
    2)      进入ruby安装的目录,输ruby –v,查看ruby版本,显示:Ruby 1.8.6
    3)      输入gem –v,查看gem版本,显示0.94
    4)      升级gem,把gem包拷贝到ruby安装目录,在dos界面输入命令:gem install rubygems-update-1.3.4.gemgem包名)

    提醒:安装完后进入ruby目录:libuby\gems\1.8\gemsubygems-update-1.3.4,点击这个文件夹中的文件:setup.rb,升级gem即可

    5)      安装watir包,把watir包拷贝到ruby安装目录,在dos界面输入命令:gem install watir-1.5.2.gem
    3.       安装完毕检查
    dos界面,进入firewatir安装路径下(一般在:"ruby"lib"ruby"gems"1.8"gems"firewatir-1.1),进入unittests文件夹,输入命令:ruby mozilla_all_tests.rb,如果可以正确执行程序,说明安装正确没有问题,到此可以开始自动化测试开发的旅程了。^_^

  • QTP运行错误:对象无法识别的解决办法(转)

    2009-05-13 15:05:35

     

    1.1 如何去识别对象描述(Identifying Test Object Descrīption Problems)
         如果你能在被测程序中看到对象,但仍出现了“Cannot Identify Object”错误信息,这就表示仓库中对象的描述与程序中对象的描述一定存在着差异。
         解决对象描述问题的第一步是找到差异,最简单的方法是将仓库中对象的属性值与程序中对象的属性值进行比较。(仓库中对象的属性值可在Object Repository窗口中查看,程序中对象的属性值可用Object Spy功能查看。)
         比较仓库中对象的属性值与程序中对象的属性值的操作见1.3。
         在完成比较后,是否发现存在差异?如果是,请参考1.4;如果否,请参考1.5。

    1.2 处理对象丢失问题(Solving Missing Object Problems)
    在运行脚本时,QTP尝试进行某种操作,而该操作的对象在程序中却没有出现,出现这种情况的原因有以下几种:
     对象不再存在。对象已经被从程序中删除。解决方法:见1.2.1。
     对象还没有装载。解决方法:见1.2.2。
     当前的程序页面(或窗口)不正确,不是对象所在的页面(或窗口)。解决方法:见1.2.3。
     前一个步骤没有正确执行。解决方法:见1.2.3。

    1.2.1 解决对象不再存在的问题
    如果对象已经不再在被测程序中存在,则应在脚本中修改或删除相关步骤。

    1.2.2 解决对象装载超时的问题
    如果对象丢失的原因是因为没有足够的时间装载,尝试以下解决方案:
    a.对于Web对象,增加Browser Navigation Timeout(File>Setting>Web页签)时间。
    b.在包括该对象的步骤前使用Wait语句,让QTP在执行该步骤之前等待一段时间。

    1.2.3 检查前面步骤的执行情况
    如果是因为打开了错误的页面(或窗口)导致对象丢失问题,或因为前一步骤执行措误导致对象丢失问题,则请按以下方法检查原因:
    a. 如果怀疑在完成脚本后,被测程序又发生了改变,则检查对象的继承关系以及对象描述。参考1.1。
    b. 如果怀疑脚本错误,则检查脚本的每一个步骤。你可能是遗失了某个步骤,也可能是使用了不正确的方法或参数。

    1.3 测试对象的属性值与Run-time对象的属性值的比较(Comparing Test Object and Run-Time Object Property Values)

    根据以下的步骤比较测试对象与Run-time对象的属性值:
    1) 进入Obecjt Repository窗口(Resources>Object Repository),选择对象。
    2) 记录对象的class以及它的各个属性及属性值。
    3) 打开被测程序,并打开包含被测对象的页面或窗口。
    4) 在QTP中选择菜单Tools>Object Spy或点击Object Spy按钮,打开Object Spy对话框
    5) 选择“Test Object Properties”选项。
    6) 点击右上角的按钮(带有手图标的),这时QTP窗口以及Object Spy对话框都被最小化。
    7) 在程序页面(或窗口)中点击目标对象,恢复Object Spy对话框,并在对话框中显示对象及其父对象(以树的形式显示),并在Properties页签中显示当前对象的属性及属性值。
    8) 这时Object Spy对话框的Properties页签中显示Run-time对象的所有属性,在此查看对象的class,以及它的属性及属性值,并将它与第2步中记下的内容进行比较。

    1.4 解决对象描述存在的问题(Solving Object Descrīption Problems)
         如果发现仓库中对象的属性值与程序中对象的属性值存在不同,你应该判断这个不同是个别对象的问题,还是其它同类对象也存在相同的问题。
         是所有(或多个)同类对象都存在问题吗?如果是,则参考1.6;如果否,则参考1.7

    1.5 关于父对象描述的识别问题(Identifying Parent Object Descrīption Problems)
    对象的识别还与它所继承的父对象有关。
         如果你能在被测程序中看到对象,而且程序中对象的属性值与仓库中对象的属性值也是一致的,但仍然遭遇到了“Cannot identify object”错误,则这个错误可能与它的父对象有关(如仓库中父对象的属性值与程序中父对象的属性值不一致),也可能是仓库中的对象与程序中对象的继承关系不相同导致的。
    要判断是继承关系中的哪个父对象出现了问题,请尝试下面的方法之一:

     重新录制对象,比较新旧对象的父对象。
    欲了解如何完成比较,参考1.8。
     对继承关系中的每个父对象,分别插入一个Exist语句,并运行该部分脚本。
    欲了解如果创建Exist语句,参考1.9。
    注:你也可以使用Object Repository窗口中的Highlight in Application功能,在被测程序中定位对象。
    一旦找到了存在问题的父对象,接下来偿试以下方法:
     修复存在问题的父对象的描述。方法见1.4。
     在专家视图的模式下,查找所有继承存在问题的实例并进行修正。举例:1.8.1。

    1.6 解决某类对象的识别问题(Soving Object Identification Problems for a Test Object Class)
         如果你发现某类对象的对象描述对于被测程序来说都不是很合理,或你预期到对象描述中的某属性值是经常变化的,你可以在Object Identification对话框中改变该类的识别属性的设置,或定义该类的Smart Identification设置并启用Smart Identification机制,这样QTP就可以唯一识别对象了。

    1.7 解决单个对象的描述问题(Solving Individual Test Object Descrīption Problems)
    选择下列方法之一来解决对象的描述问题:
     如果被测程序中对象描述发生了改变,并且你也清楚改变的内容,并且该改变是永久性或长期性的,你可以直接手工修改仓库中对象描述中的相关属性值。
     如果被测程序中的对象的属性值依赖于前面的步骤或其它对象,则将该属性值参数化,这样就可以使用其它步骤的输出值为属性值。
     如果属性值的组成部分中,部分是固定的,部分是动态改变的,则可以将属性值设计为正则表达式。
     如果属性值是遵循某种规则变化的,或者是不可预期的,则从对象描述中移除该属性,并向对象描述中添加一个或多个属性以便于QTP进行对象识别。
     If you can only access the information on the property values during the run session, you can create and use functions that use programmatic descrīptions to identify the object using property values retrieved earlier in the run session.
    For more information on programmatic descrīptions, see Using Programmatic Descrīptions.
     如果在录制过程中对象是唯一的,但现在程序中出现了两个或多个描述相同的对象,但是它们在页面(或窗口)中的位置不相同,则应在Object Properties或Object Repository窗口中,向对象描述中添加一个ordinal identifier(index或location)。

    1.8 重新录制对象,以判断父对象描述是否存在问题(Re-recording an Object to Identify Parent Object Descrīption Problems)
    根据下面的指引,来判断父对象的问题。
    通过重新录制对象,来判断它的父对象是否存在问题:
    1) 打开浏览器或程序,来到包含被测对象的页面或窗口。
    2) 在关键字视图模式,选择最后一个组件(component),或在专家视图模式,将光标放在最后一个脚本步骤的下面。
    3) 点击Record按钮,或选择Automation>Record。
    4) 点击(或操作)页面或窗口中的目标对象。
    5) 点击Stop按钮,或选择Automation>Stop,完成步骤添加。
    6) 右击新添加的步骤,并选择Object Properties右键菜单。
    7) 在Object Properties对话框中,点击Repository,打开Object Repository窗口,并选中了新对象。注意记下该对象的继承关系。
    8) 在Object Repository窗口中找到旧的对象(即存在问题的对象),将它的继承关系与新对象的继承关系进行比较。
    通过比较,可以检查到新旧对象是父对象的描述存在不同,还是它们的继承关系根本就不同。
    a. 如果是父对象的描述问题,则修改父对象的描述。参见1.4.
    b. 如果是对象的继承关系不正确(即具有不同的父对象)引起的问题,则在脚本中找到所有使用该继承关系的实例,将它们替换为正确的继承关系。举例:参见1.8.1。

    1.8.1 举例
         假设有一个带有Frame的网站,你录制了一个操作针对Image对象“Poster”的操作步骤。在Object Repository窗口,你可以Image对象的继承关系如下所示:
    MyCompany(Browser)
         MyCompany(Page)
             Main(Frame)
                  Poster(image)
         当你运行脚本时,网页看起来没有什么不同,但是识别Image对象时却出现了“Cannot identiry object”的错误提示。当你重新录制操作步骤,然后在Object Repository窗口中查看新的Image对象时,发现该对象的继承关系如下所示:
    MyCompany(Browser)
         MyCompany(Page)
              Poster(image)
         从中可以看出,Frame已经从Web Page中移除,所以尽管Image对象“Poster”的描述没有发生任何改变,但它的继承关系已经改变了。
         在Object Repository窗口,你可以看到新旧Image对象“Poster”是两个完全不同的对象:旧的位于已经被移除的Frame对象之下,而新的则直接位于Page“Mycompany”对象之下。
         修复这个问题,可以在脚本步骤中将旧的对象替换为新的对象。
         为了保持Object Repository窗口的整洁,你应删除那些已不再存在的对象(如本例中的Frame)。

    1.9 创建Exist语句,以判断父对象的描述是否存在问题
         QTP在录制发生在某个对象上的操作时,也会同时去了解对象以及它的继承关系。因此,如果在运行过程中,QTP不能识别继承关系中的任何一个父对象,都会导致目标对象的识别失败。
         使用带有Exist方法的Msgbox语句,可以方便的检查出是继承关系中的哪个父对象出现了问题。
         假设在运行下面脚本时,你遇到了“Cannot identify Object”错误信息(但是可以确定对象仓库中Link对象的描述与当前程序中对象的描述是完全一致的):
    Browser("Yahoo!").Page("Yahoo!").Link("Arts & Humanities").Click
    你可以在该语句前面插入以下语句:
    Msgbox Browser("Yahoo!").Exist
    Msgbox Browser("Yahoo!").Page("Yahoo!").Exist
    Msgbox Browser("Yahoo!").Page("Yahoo!").Link("Arts & Humanities").Exist
    然后你从头开始运行脚本,发现第1行语句运

         但是,当QTP运行到第2步时,就弹出信息框,内容为“False”,表示不能找到Page object。这就证明Page对象存在问题。
         确定了出现问题的父对象以后,修复该问题。参见1.4。


    2.       运行错误:对象不唯一(The object is not unique)
    在被测页面或窗口中的同一父对象下,找到多个与仓库中对象描述相符的Run-tim对象。
    请确定是只有个别对象存在此问题,还是此类对象的所有对象(或部分对象)存在此问题。
    此类对象的所有对象(或部分对象)都存在此问题吗?如果是,参考2.1;如果否,参考2.2。

    2.1 为某对象类设置能唯一识别对象的描述规则(Configuring Unique Test Object Descrīptions for a Test Object Class)
         如果你发现某类对象的对象描述都不足以唯一识别对象,你可以在Object Identification对话框中,改变该类的识别属性的设置,或定义该类的Smart Identification设置并启用Smart Identification机制,这样QTP就可以唯一识别对象了。

    2.2 设置通唯一识别对象的对象描述(Creating a Unique Test Object Descrīption for an Object)
    查看当前对象的描述,并偿试在程序中找到其它具有相同描述的对象并查看它们的描述。
     如果你找到了可以将它们区别开来的一个或多个属性,则修改仓库中对象的相关属性(如向描述中添加属性等),以使QTP在运行时可以唯一识别它。
     如果它们的识别属性完全相同,则在对象描述中为对象添加一个ordinal identifier(index或location)。

    3.       运行错误:找不到父对象(Parent not found)
    识别对象时,会先识别它的父对象是否正确。如果遇到“Parent not found”的错误信息,请偿试以下解决方法:
     修复出现问题的父对象的描述。参见1.4。
     在脚本中找到继承关系不正确的实例,并修改为正确的继承关系。例如1.8.1。

    4.       运行错误:无效的参数(Invalid arguments)
    一个或多个方法的参数是无效的。
    参数无效可能是参数类型错误,也可能是参数个数不正确。
    根据以下建议,找到方法的正确语法:
     在Keyword模式,如果方法包括参数,则在Value栏会显示该方法的参数提示。

     在Expert 模式,如果方法包括参数,则当你插入方法然后按下Shift+Ctrl+Space键时,QTP会显示该方法的参数的提示信息。(注:只有在Editor Options对话框的General页签中打开了Statement completion功能时才可以看到参数的提示信息。)


    5.       运行错误:不能识别item(Cannot identify item)
    QTP不能识别方法参数中指定的列表或树对象的item时,请确认指定的item是否存在于对象之中。
     如果item不存在,则删除相关脚本步骤,或修改item。
     如果item存在,但被测程序中它的名字发生了改变,则修改item的名称,或在脚本中使用item的index而不是名字(如“#4”)。注意,不同的对象或方法,它们使用index的语法可能不同。

    6.       运行错误:对象的item不唯一(The object’s item is not unique)
    在列表或树对象中,可能有多个名字相同的item。
    在这种情况下,可以指定item使用index(例如“#4”)。

    7.       运行错误:运行失败(Test run failed)
    测试运行失败,还有可能是其它未知错误造成的。检查出现错误时的脚本步骤。
    如果错误出现在执行检查点或输出值时,请查阅关于检查点与输出值的帮助。
    如果错误出现在使用外部文件时,如数据库表、数据库、环境变量文件、或关联仓库文件等,则检查是否可以正常获取并使用文件,或这些文件的存储格式是否正确。
    如果错误出现在完成某个脚本动作时,请参考QuickTest Object Model Reference帮助,以确认方法或函数的使用是否正确。
    如果错误出现在执行一个标准的VBscrīpt语句时,参考Microsoft VBscrīpt Reference以获得帮助。
  • [转] 如何学习自动化测试工具QTP

    2009-05-11 10:23:03

      网上看到一篇写的不错的文章,个人觉得总结的比较全面,转载过来分享下。-_-

        本文出自:http://www.51testing.com/?161787

        从事了几年测试工作,也着实见证了测试的发展,如今测试行业对从业者的要求是越来越高,不再仅仅局限于要求会写测试用例、会细致的执行测试、能有效的发现系统缺陷等;越来越多的企业对应聘者本身的技能要求也越来越高,招聘信息中诸如“精通VBscrīpt、Perl/Rbuy等至少一门脚本语言”、“至少熟悉一门开发语言”、“精通QTP、LR等自动化测试工具”、“有大型项目自动化实施成功经验”此类的字眼也逐渐增多。目前看来,除白盒测试内容和测试管理外,主流的方向有两个:功能自动化测试和性能测试。这就要求从业人员能够在短时间内快速的掌握这些知识,才能获取到更好的工作机会。本人是名功能自动化测试的工程师,以自己学习、工作的过程结合QTP讲讲该如何学习自动化测试

        首先,想从事自动化测试,必须先了解What/Why/How,也就是常说的去了解什么是自动化测试、为什么要进行自动化测试、该如何进行自动化测试,这类的资料在网上有很多,这里就不做重复了

    其次,需要根据项目的特点,选择合适的自动化测试工具,并了解工具的特性。以QTP为例,该如何去掌握它呢?对于初学者,大多数都是通过录制的方式来生成脚本,这个阶段应该掌握的基础知识有

         1)   QTP是如何去识别对象的,对于新手经常会出现录制的脚本回放的时候报错的现象,这个时候就应该考虑为什么呢?如果很了解QTP识别对象的原理啊,我想就能很快定位到原因了

         2)   去掌握一些QTP对象的方法,如GetROPreperty、GetTOPreperty、ChildObjects等等,对于相似的方法应该去搞清楚到底区别在哪?像GetROPreperty、GetTOPreperty有什么区别等

         3)   什么是Action参数、什么又是Test参数?两者有什么区别,又有什么联系,在同一Test和不同Test间这些参数如何工作

         4)   什么是环境变量?环境变量是如何建立和使用的,环境变量在参数传递中和action参数、test参数有什么不同

         5)   了解检查点的知识,明白什么是内置检查点,什么又是自定义检查点。并搞清楚在什么时候该如何使用检查点

         6)   掌握对象库的操作,了解对象库对于测试的意义,象是否启用智能识别对测试脚本有何影响、为什么同一对象识别起来会有_1、_2之类的后缀等都是需要去研究清楚的问题

        这几个问题都搞清楚的话,那基本就能够利用QTP生成正确的脚本了,当然以上只是部分必须掌握的内容,其实还是很多细节的设置,就需要在实际运用中去掌握了。

        接下来,就可以进一步提升自己的QTP运用水平了,这个阶段就需要去学习vbs知识和如何运用描述性编程实现脚本了,同时在这个过程中还需要去学习html知识、DOM、XML、以及像excel、word等的API知识了,总的来说,这个阶段应该掌握的内容大体上包括

         1)   VBscrīpt的基础知识,熟悉常用的方法和函数,掌握文件对象的操作等

         2)   熟练掌握XML技术;excel、word等API对象,可以根据需要创建日志等

         3)   熟练掌握DOM和HTML知识,能够结合这些技术对Web页面进行解析

         4)   掌握数据库的基本操作语句,能够利用ADO对象进行数据操纵

         5)   熟练掌握正则表达式,很多时候处理对象问题相当方便

         6)   掌握如何调用dll进行工作

         7)   能够利用QTP的自动化对象模型创建出需要的运行模式

         8)   掌握WMI知识

        以上只是我考虑到的部分,并不全面,呵呵,供大家参考,当然这些技术主要是针对Web系统运行,因为我们的系统就是B/S的,呵呵。如果这些知识都能够扎实的掌握的话,个人认为,基本上能够处理自动化过程中的绝大多数问题了,这个时候你对自动化测试的技术应该是有一定积累了

    接下来就需要考虑自动化测试框架问题了。当脚本规模到了一定的程度,就会面临一些问题,如:

         1)   如何有效的管理并调度脚本

         2)   如何实现脚本运行的无人值守,测试过程中能够自动进行错误处理并进行日志记录

         3)   如何生成简介明确的测试报告

         4)   如何能够更加高效的维护测试脚本

         5)   实现框架代码和业务代码的分层、业务脚本和业务数据的分离

        这个阶段主要体现的是测试人员的测试思想,是可以脱离工具独立存在的过程。当然各个公司项目的实际情况不同,导致设计出来的思想不同,但总体上来说一般包括数据驱动和关键字驱动两种模式。后者实现的技术难度大于前者,大多数公司目前都采用的数据驱动模式。这个阶段不应局限于技术运用上,而需要从测试全局考虑,进行分层设计、模块化实现,减少代码之间的耦合

    如果以上三个方面都能够做的很好的话,那么恭喜你,你已经可以独立负责项目的自动化测试建立工作了,呵呵!

        总之,学习自动化测试需要在实际项目中进行,这样提高的会比较快,项目中运用了很多种技术,自动化实施过程会碰见各种各样的问题,是很好的学习机会,关键要善于总结、积累经验,只要能够把各个细节做好,那么你一定能够成为一名优秀的自动化测试工程师

  • 今天很生气 16/12/2008

    2008-12-17 12:09:34

    今天很生气,怎么有这么笨的人,把我气的半死,饭都吃不下了。

    原因很简单,就是一个QA太笨,叫她做个东西给我,在她负责的模块,千叮咛万嘱咐结果都会出错,做之前还要她查一下需求,我的天哪,这样都会做错,今天问她,她才说不是那样的,我就纳闷了,不是那样的干吗还给错数据,给之前还给你确认过,还能给错?!!遇到这种同事真是能气死活人,看着她平时也挺认真,天天在那里做,怎么就不出成绩呢,不喜欢这么笨的人,这种错误又不能训,训了别的QA可能会有情绪,这种情况下真是好难做,真想把她大批一顿,以惩罚他的笨。

    原以为写出来就不会那么生气,没有,依旧很生气。咳

  • LoadRunner 如何选择合适的协议

    2008-10-16 16:52:40

    LR的录制工作原理,LR跟WR不一样,它不关心你的对象识别什么,不关心你的什么窗口之类的,LR有一个Agent的进程,来专门监控客户端与服务器之间的通信,然后用自己的函数进行录制,所以说,LR录制的时候关心的是通信,是客户端与服务器之间的数据包。说到这里,大家就比较清楚了,为什么有的时候不能录制呢?因为,协议不认识阿,导致LR截获的数据包不能解析,所以录制下来是空的。

    到这里看来,我们怎么样选择协议呢?当然原则就是说,你的数据包的通信协议能被LR 识别。

    过去流行的一种看法是,只要B/S结构的都是选择http协议,如果不是B/S 结构的那肯定是socket, 其实这种说法比较片面,我觉得要真正理解这个问题,必须搞杏出你所测系统的数据流采用什么协议包装的,这个我个人觉得,最好是能去向开发人员多理解这个问题,多学习。

    协议参考选择:

    应用类型   协议选择

    1,web 网站  Http/HTML

    2, FTP 服务器 FTP

    3, 邮件服务器 IMAP, POP3, SMTP

    4, C/S (第一种)客户端 以ADO, OLEDB方法连接后台数据库 MSSQL Server, Oracle, Sybase, DB2, Infirmix

        C/S (第二种) 客户端以ODBC方法廉洁后台数据库 ODBC

       C/S (第三种) 没有后台数据库 Socket

    5, ERP系统 SAP Peoplesoft

    6, 分布式组件  COM/DACOM EJB

    7, 无线应用 WAPPALM

    总之,只有充分理解被被测系统的应用类型和技术架构,才能做出正确的选择。

     

    以上内容为摘抄,觉得写的不错,就摘下来自己收藏。

     

  • 无聊的一天

    2008-10-16 15:27:21

    今天是阳历2008年10月16号,已经持续一周都好无聊了,早该结束的项目一拖再拖,到现在还有一些东西搞不清楚,当然这不是我的原因,我还没有那么大的权利和能力,呵呵。没事情做,即使有事情也不想做,时间就这样一天天的浪费掉,想当初对工作是多么的憧憬阿,毕业时是多么的高兴啊,现在看来也就这样,每天都昏沉沉的,好像自己的潜力根本没有发挥出来,自己就窝在这里,整天无所事事,但是还必须待在公司,拿着那一份撑部死也饿不着的工资,很空虚很无聊。

    不知道别人做测试累不累,反正我这里一点都不累,干着也没劲,想换个工作了。

  • 与测试工作相关

    2008-07-09 14:25:30

    事件过的飞快,不知不觉已经参加工作一年有余,一年下来也真正的具备了一点所谓的测试经验,测试经验得来并不难,难的是怎么在已有测试经验的上再有所提高,测试行业的门槛低,收入也低,很多公司口头上都是说重视测试,但是测试人员的待遇远远低于开发人员,这也是测试人员的悲哀,但是有一点要说明,如果没有测试人员,全凭开发人员就能够开发出没有缺陷的软件是天方夜谭。
  • 今天比较郁闷

    2007-12-12 14:30:43

    今天要寄点东西回学校,本来可以选择快递公司的,可是又怕快递公司的不安全(可能是我平时太小心了),最后还是选择了邮局,可是去邮局真是波折,坐错公交车,这已经不是第一次了,有的时候真是怀疑自己在外边的生活能力,很想回家那边工作,可是男朋友在这边,也许选择一个人就选择一个生活方式吧,
  • 第一次参加UAT

    2007-10-08 14:10:53

      今天要第一次UAT了,以前从未参加过,所以感觉好新奇,早上好早就爬起来赶往客户那边,首先PL把系统环境搭建好,测试人员这个时候就是打杂咯,把测试用例分类,然后就是客户进行测试,哈哈,好简单。

    下午回到公司,继续写自己的测试用例。

    测试其实还不错,主要就是找错误,一般项目刚开始会有好多错误出来,一下子找出好多错误真是好兴奋,哈哈,只要是把需求搞清楚了,测试就很简单了,哈哈。

  • 测试之后还是测试,

    2007-09-28 11:14:13

       参加工作了,以前没有参加过工作,哈哈,以为会是一件很激动人心的事情,可是一切都来的平淡无奇,没有感觉到任何的过渡,跟想象的很不一样,觉得测试有前途就选择了测试,工作的任务就是每天读文档,最烦的是要读英文的文档,写测试用例,真是烦的要死,任务又重,每天早上爬起来就是盯着文档看,真是无聊,不过想想,做开发应该也有趣不到哪去。做这行就是会这样子,没的办法。

  • 不再做傻大姐

    2007-09-14 14:27:32

       现在才发现知道的东西太少,包括生活和工作上的,很多时候像白痴一样,被讥笑为外星人,哈哈,以前可以原谅自己的无知,如果继续助长自己的无知,继续无知下去将是自己所不可原谅的,无知不是可爱,是落后是可耻的,所以以后要主意咯。
  • 一位前辈工程师职业发展的忠告

    2007-08-15 15:35:03

    好好规划自己的路,不要跟着感觉走!根据个人的理想决策安排,绝大部分人并不指望成为什么院士或教授,而是希望活得滋润一些,爽一些。那么,就需要慎重安排自己的轨迹。从哪个行业入手,逐渐对该行业深入了解,不要频繁跳槽,特别是不要为了一点工资而转移阵地,从长远看,这点钱根本不算什么,当你对一个行业有那么几年的体会,以后钱根本不是问题。频繁地动荡不是上策,最后你对哪个行业都没有摸透,永远是新手!

    可以做技术,切不可沉湎于技术。千万不可一门心思钻研技术!给自己很大压力,如果你的心思全部放在这上面,那么注定你将成为孔乙己一类的人物!适可而止为之,因为技术只不过是你今后前途的支柱之一,而且还不是最大的支柱,除非你只愿意到老还是个工程师!

    [3]不要去做技术高手,只去做综合素质高手!在企业里混,我们时常瞧不起某人,说他“什么都不懂,凭啥拿那么多钱,凭啥升官!”这是普遍的典型的工程师的迂腐之言。

    很牛吗?人家能上去必然有他的本事,而且是你没有的本事。你想想,老板搞经营那么多年,难道见识不如你这个新兵?人家或许善于管理,善于领会老板意图,善于部门协调等等。因此务必培养自己多方面的能力,包括管理,亲和力,察言观色能力,攻关能力等,要成为综合素质的高手,则前途无量,否则只能躲在角落看示波器!技术以外的技能才是更重要的本事!!从古到今,美国日本,一律如此!

    [4]多交社会三教九流的朋友!不要只和工程师交往,认为有共同语言,其实更重要的是和其他类人物交往,如果你希望有朝一日当老板或高层管理,那么你整日面对的就是这些人 。了解他们的经历,思维习惯,爱好,学习他们处理问题的模式,了解社会各个角落的现象和问题,这是以后发展的巨大的本钱,没有这些以后就会笨手笨脚,跌跌撞撞,遇到重重困难,交不少学费,成功的概率大大降低!

    [5]知识涉猎不一定专,但一定要广!多看看其他方面的书,金融,财会,进出口,税务, 法律等等,为以后做一些积累,以后的用处会更大!会少交许多学费!!

    [6]抓住时机向技术管理或市场销售方面的转变!要想有前途就不能一直搞开发,适当时候 要转变为管理或销售,前途会更大,以前搞技术也没有白搞,以后还用得着。搞管理可以培养自己的领导能力,搞销售可以培养自己的市场概念和思维,同时为自己以后发展积累庞大的人脉!应该说这才是前途的真正支柱!!!
    [7]逐渐克服自己的心里弱点和性格缺陷!多疑,敏感,天真(贬义,并不可爱),犹豫不决,胆怯,多虑,脸皮太薄,心不够黑,教条式思维。。。这些工程师普遍存在的性格弱点必须改变!很难吗?只在床上想一想当然不可能,去帮朋友守一个月地摊,包准有效果 ,去实践,而不要只想!不克服这些缺点,一切不可能,甚至连项目经理都当不好--尽管你可能技术不错!
    [8]工作的同时要为以后做准备!建立自己的工作环境!及早为自己配置一个工作环境,装备电脑,示波器(可以买个二手的),仿真器,编程器等,业余可以接点活,一方面接触市场,培养市场感觉,同时也积累资金,更重要的是准备自己的产品,咱搞技术的没有钱 ,只有技术,技术的代表不是学历和证书,而是产品,拿出象样的产品,就可技术转让或与人合作搞企业!先把东西准备好,等待机会,否则,有了机会也抓不住!

    [9]要学会善于推销自己!不仅要能干,还要能说,能写,善于利用一切机会推销自己,树 立自己的品牌形象,很必要!要创造条件让别人了解自己,不然老板怎么知道你能干?外面的投资人怎么相信你?提早把自己推销出去,机会自然会来找你!搞个个人主页是个好注意!!特别是培养自己在行业的名气,有了名气,高薪机会自不在话下,更重要的是有合作的机会...

    [10]该出手时便出手!永远不可能有100%把握!!!条件差不多就要大胆去干,去闯出自己的事业,不要犹豫,不要彷徨,干了不一定成功,但至少为下一次冲击积累了经验,不干永远没出息,而且要干成必然要经历失败。不经历风雨,怎么见彩虹,没有人能随随便便成功

  • 常见112个测试英语面试题

    2007-08-13 16:16:14

    1.        What types of documents would you need for QA, QC, and Testing?
    2.        What did you include in a test plan?
    3.        Describe any bug you remember.
    4.        What is the purpose of the testing?
    5.        What do you like (not like) in this job?
    6.        What is quality assurance?
    7.        What is the difference between QA and testing?
    8.        How do you scope, organize, and execute a test project?
    9.        What is the role of QA in a development project?
    10.        What is the role of QA in a company that produces software?
    11.        Define quality for me as you understand it
    12.        Describe to me the difference between validation and verification.
    13.        Describe to me what you see as a process. Not a particular process, just the basics of having a process.
    14.        Describe to me when you would consider employing a failure mode and effect analysis.
    15.        Describe to me the Software Development Life Cycle as you would define it.
    16.        What are the properties of a good requirement?
    17.        How do you differentiate the roles of Quality Assurance Manager and Project Manager?
    18.        Tell me about any quality efforts you have overseen or implemented. Describe some of the challenges you faced and how you overcame them.
    19.        How do you deal with environments that are hostile to quality change efforts?
    20.        In general, how do you see automation fitting into the overall process of testing?
    21.        How do you promote the concept of phase containment and defect prevention?
    22.        If you come onboard, give me a general idea of what your first overall tasks will be as far as starting a quality effort.
    23.        What kinds of testing have you done?
    24.        Have you ever created a test plan?
    25.        Have you ever written test cases or did you just execute those written by others?
    26.        What did your base your test cases?
    27.        How do you determine what to test?
    28.        How do you decide when you have ‘tested enough?’
    29.        How do you test if you have minimal or no documentation about the product?
    30.        Describe me to the basic elements you put in a defect report?
    31.        How do you perform regression testing?
    32.        At what stage of the life cycle does testing begin in your opinion?
    33.        How do you analyze your test results? What metrics do you try to provide?
    34.        Realising you won’t be able to test everything - how do you decide what to test first?
    35.        Where do you get your expected results?
    36.        If automating - what is your process for determining what to automate and in what order?
    37.        In the past, I have been asked to verbally start mapping out a test plan for a common situation, such as an ATM. The interviewer might say, “Just thinking out loud, if you were tasked to test an ATM, what items might you test plan include?” These type questions are not meant to be answered conclusively, but it is a good way for the interviewer to see how you approach the task.
    38.        If you’re given a program that will average student grades, what kinds of inputs would you use?
    39.        Tell me about the best bug you ever found.
    40.        What made you pick testing over another career?
    ________________________________________
    41.        What is the exact difference between Integration & System testing, give me examples with your project.
    42.        How did you go about testing a project?
    43.        When should testing start in a project? Why?
    44.        How do you go about testing a web application?
    45.        Difference between Black & White box testing
    46.        What is Configuration management? Tools used?
    47.        What do you plan to become after say 2-5yrs (Ex: QA Manager, Why?)
    48.        Would you like to work in a team or alone, why?
    49.        Give me 5 strong & weak points of yours
    50.        Why do you want to join our company?
    51.        When should testing be stopped?
    52.        What sort of things would you put down in a bug report?
    53.        Who in the company is responsible for Quality?
    54.        Who defines quality?
    55.        What is an equivalence class?
    56.        Is a “A fast database retrieval rate” a testable requirement?
    57.        Should we test every possible combination/scenario for a program?
    58.        What criteria do you use when determining when to automate a test or leave it manual?
    59.        When do you start developing your automation tests?
    60.        Discuss what test metrics you feel are important to publish an organization?
    61.        In case anybody cares, here are the questions that I will be asking:
    62.        Describe the role that QA plays in the software lifecycle.
    63.        What should Development require of QA?
    64.        What should QA require of Development?
    65.        How would you define a “bug?”
    66.        Give me an example of the best and worst experiences you’ve had with QA.
    67.        How does unit testing play a role in the development/software lifecycle?
    68.        Explain some techniques for developing software components with respect to testability.
    69.        Describe a past experience with implementing a test harness in the development of software.
    70.        Have you ever worked with QA in developing test tools? Explain the participation Development should have with QA in leveraging such test tools for QA use.
    71.        Give me some examples of how you have participated in Integration Testing.
    72.        How would you describe the involvement you have had with the bug-fix cycle between Development and QA?
    73.        What is unit testing?
    74.        Describe your personal software development process.
    75.        How do you know when your code has met specifications?
    76.        How do you know your code has met specifications when there are no specifications?
    77.        Describe your experiences with code analyzers.
    78.        How do you feel about cyclomatic complexity?
    79.        Who should test your code?
    80.        How do you survive chaos?
    ________________________________________
    81.        What processes/methodologies are you familiar with?
    82.        What type of documents would you need for QA/QC/Testing?
    83.        How can you use technology to solve problem?
    84.        What type of metrics would you use?
    85.        How to find that tools work well with your existing system?
    86.        What automated tools are you familiar with?
    87.        How well you work with a team?
    88.        How would you ensure 100% coverage of testing?
    89.        How would you build a test team?
    90.        What problem you have right now or in the past? How you solved it?
    91.        What will you do during the first day of job?
    92.        What would you like to do five years from now?
    93.        Tell me about the worst boss you’ve ever had.
    94.        What are your greatest weaknesses?
    95.        What are your strengths?
    96.        What is a successful product?
    97.        What do you like about Windows?
    98.        What is good code?
    99.        Who is Kent Beck, Dr Grace Hopper, Dennis Ritchie?
    100.        What are basic, core, practises for a QA specialist?
    101.        What do you like about QA?
    102.        What has not worked well in your previous QA experience and what would you change?
    103.        How you will begin to improve the QA process?
    104.        What is the difference between QA and QC?
    105.        What is UML and how to use it for testing?
    106.        What is CMM and CMMI? What is the difference?
    107.        What do you like about computers?
    108.        Do you have a favourite QA book? More than one? Which ones? And why.
    109.        What is the responsibility of programmers vs QA?
    110.        What are the properties of a good requirement?
    111.        Ho to do test if we have minimal or no documentation about the product?
    112.        What are all the basic elements in a defect report?
  • 测试工程师的一天(收录)

    2007-08-13 16:02:27

    看到的文章,本人觉得很有用,就收藏了,

    1. 引言
       软件测试成为最近 IT 行业的“香饽饽”,引得很多人对软件测试跃跃欲试。可是软件测试的门槛并不低,对于没有软件测试经验的新人而言,如何尽快转入测试工作中去呢?
       了解软件测试都做些什么,具体过程是怎么进行的,可以有助于对软件测试进行初步了解,尽快进入测试工作角色。但是关于软件测试的工作流程,各种现有书籍和文章往往都描述的非常复杂,充斥着不少测试术语,使测试初学者望而生畏。
       现在让我们换一种角度看看典型的软件测试是如何进行的,暂且把软件测试过程看作一场大戏,主角就是测试工程师,按照时间顺序记录软件测试工程师一天的工作场景(假设正常工作时间 9:00 到 18:00 )。
       2. 测试大戏开演
        时间: 9:00
        工作场景:
    •        启动工作计算机,查看收到的电子信件。
       画外音:
    •        查看收到的电子邮件(哇塞,这么多电子邮件!),理解当天的测试工作的内容和要求。
    •        测试工程师至少配置两台计算机:其中一台是日常工作用,例如,收发电子邮件等。另外还有一台软件测试用的计算机。
       时间: 9:10
       工作场景:
    •        回复电子邮件。
       画外音:
    •        回复电子邮件。如果对于安排的测试任务和要求存在任何疑问,请在回复电子邮件时列举出来。如果任务明确,回信中可以简单的说明理解测试任务了,按照测试任务要求进行测试。(正好今天有一封电子邮件分配了测试任务 A ,而且任务明确,测试文档等完整。)
    •        电子邮件有不同的优先级,任务非常紧迫的电子邮件应该优先处理,尽快回复。(面对多封邮件保持镇定,分清哪些邮件需要马上回复)
    •        并非全部的电子邮件都需要回复(抄送给自己的邮件和一般通告等不需要回复)
       时间: 9:25
       工作场景:
    •        启动用于测试的计算机
    •        根据测试要求配置操作系统、安装要测试的软件
    •        根据测试用例执行测试任务 A 。
       画外音:
    •        测试一般需要按照测试指导文档和测试用例进行。(软件测试可不是盲目的乱测一气的呀!)
    •        很多软件的测试要求在一个“干净”的计算机上测试(提示:干静的计算机是仅安装了操作系统,没有安装其他应用程序的计算机)。
    •        在进行正式测试前,需要阅读测试文档,明确测试任务(这些测试文档你找到了吗?是最新的测试文档吗?)。
       时间: 11:00
       工作场景:
    •        执行软件测试,书写软件测试 Bug 报告
       画外音:
    •        按照测试要求,尽量多找出软件的 Bug 。(什么破软件,能找出这么多 Bug ! 反过来想,软件如果没有 Bug ,我们测试工程师不就失业了吗!)
    •        根据发现的软件 Bug ,按照客户要求写出每个 Bug 的报告(要书写明白,否则客户事后会要求你重写,很费时间,也影响公司的测试质量,是否很没有面子?)
       时间: 11:30
       工作场景:
    •        报告测试执行中的遇到了问题
       画外音:
    •        如果测试用例的步骤不明确或者测试的软件不能成功安装,无法进行下面的测试,应该及时向测试负责人报告,等待答复后进行测试。(重大问题,切莫瞒报,也别主观想当然地猜测!)
    •        如果某些测试步骤不明确,但是可以暂时跳过,请向测试负责人报告,并且继续进行下面的测试。(灵活处理,合理利用时间,时间就是金钱!)
       时间: 12:00
       工作场景:
    •        查收和回复新邮件,新邮件又来了一个新的测试任务 B ,而且要求紧急处理。
    •        暂停测试任务 A ,进行测试任务 B 。
       画外音:
    •        测试过程中,要主要定时查看是否有新邮件,特别是那些要求非常紧急的任务。(重要任务一定要优先处理,否则就是工作失职)
    •        如果新任务比较紧急,应该中断当前的测试,接着执行新任务。(为什么计划总是没有变化快,可是现实就是这样。)
       时间: 12:30
       工作场景:
    •        午餐、休息
       画外音:
    •        阳光、午餐、休息,美!(禁止在办公室玩任何电子游戏,办公室不是娱乐场所!)
       时间: 13:30
       工作场景:
    •        查收和回复新邮件
       画外音:
    •        真幸运,没有其他新任务。
    •        继续上午的任务 B 。
       时间: 14:30
       工作场景:
    •        完成新任务 B ,向测试负责人提交任务 B 的测试结果
       画外音:
    •        完成任何任务后,需要向测试负责人发送任务完成的电子邮件。(这一点很重要的,否则你做的工作再多,测试负责人也不一定很清楚)
    •        提交任务的电子邮件中,应该写明任务是否全部完成,存在什么问题,测试结果存放在什么计算机的哪个目录中。(想象测试负责人需要你提交哪些内容,最好在一封信中交待明白,完整,清楚,条理分明)
       时间: 14:40
       工作场景:
    •        发送测试任务 A 不能按期完成的电子邮件
       画外音:
    •        由于执行了新测试任务 B ,使得测试任务 A 不能按时完成,应该及早向测试负责人发送电子邮件。(如果你不主动说无法按时完成任务 A ,测试负责人就默认为你能够按时完成。而如果到了完成任务的最后期限,而你突然向测试负责人说任务还没有完成,那么我可以很负责任地告诉你:测试负责人将会很生气,后果很严重!)
    •        得到测试负责人的答复后,继续执行测试任务 A 。
    •        如果客户要求必须当天完成测试任务 A ,可能要做好加班准备(苦恼 … )。或者请测试负责人将一部分任务分解给其他测试人员执行(呵呵,谢谢兄弟们拉我一把 ... )。
       时间: 14:50
       工作场景:
    •        继续执行测试任务 A 。
       画外音:
    •        寻找软件 Bug (这是主要任务之一)
    •        书写 Bug 测试报告(这也是主要任务之一)
       时间: 15:30
       工作场景:
    •        查收和回复新邮件
       画外音:
    •        没有新电子邮件,呵呵!(最不喜欢在测试工作中,经常有邮件来骚扰!)
    •        继续执行测试任务 A 。
       时间: 17:00
       工作场景:
    •        参加测试小组内部会议
       画外音:
    •        经常在测试过程中,测试小组内部会召开短暂的会议。(交流很重要的,倾听和发言一个都不能少)
    •        会议内容一般是测试过程中遇到的问题,以及可能的解决办法,也包括测试进度是否与测试计划保持一致。
       时间: 17:30
       工作场景:
    •        发送当天任务完成情况的电子邮件
       画外音:
    •        当天任务完成情况的报告应该在下班前尽早发送给测试负责人,以便得到及时回复。
    •        总结当天测试任务完成的情况(全部完成还是部分完成)
    •        测试遇到的需要测试负责人或者问题客户帮助解决的问题(遇到问题一定要反映,不要什么问题都自己扛!)
    •        给出当天处理 Bug 的数量、类型和存放位置(确保测试负责人能很容易的找到这些测试结果吗?)
       时间: 17:45
       工作场景:
    •        整理当天的测试文档,
    •        做好备份
    •        个人总结
       画外音:
    •        备份当天的测试结果(有备无患!)
    •        总结测试遇到的问题和学习的新知识(好好学习,天天向上!)
    •        准备第二天的测试任务(未雨绸缪)
       时间: 18:00
       工作场景:
    •        下班
       画外音:
    •        如果不需要加班,按时回家,爽!
       3. 测试大戏背后的故事
       上面的测试场景描述基本上反映了软件测试工程师的工作情形,但是由于测试工作的复杂性、琐碎性、变化性,实际测试过程将是不断变化的。
        测试的变化性
       对于软件本地化等外包测试,测试过程和测试要求因不同客户而异,即使相同客户的不同项目,也会有些变化。另外,测试所用的测试计划、测试用例、测试 Build 版本经常变化。这是对测试工程师需要面对和正确处理的工作挑战。
        多任务同时处理
       软件测试工程师在一天的工作时间里,可能需要做多件事情(例如,测试负责人可能中间会安排新的任务),正常测试过程经常被中断,对此需要有相应的心理准备。
        及时交流
       测试过程很少是一帆风顺的,特别是不熟悉的新软件,或者测试用例没有表达清楚。这时除了自己学习和思考,还需要向测试组的其他同事请教。如果问题仍然没有解决,请及时向测试负责人反映情况,寻求帮助(提示:测试负责人积累了软件测试经验,一般问题都可以搞定,但是测试负责人也不是万能的,他们也有很多不能解决的问题,但是他们有“杀手锏” — 向客户的测试负责人寻求帮助,由于源语言是客户开发的,客户才是万能的!)。
       电子邮件是主要的交流方式
       测试过程不要一味地在测试计算机上做下去,要经常在日常工作用计算机查看和回复电子邮件,以免耽误了更重要的任务。除了电子邮件之外,也可以打电话和即时网络交流工具( MSN 等),或者面对面与同事交流(提示:对于复杂的问题,与其来回发送多封电子邮件还说不明白,还不如打个电话或者面对面交谈更有效)。
       4. 结束语
       有人说,测试很枯燥,而且“一点技术含量都没有”。也有人说,软件测试大有前途!现在中国确的不是软件编程大师,而是软件测试大师。这些观点孰是孰非,您请自己琢磨。不过既然从事了测试行业,还是将它做好为上!
  • 测试进阶三步曲(转录)

    2007-08-13 15:58:48

    ,入行导读
    测试这个领域,入门浅,真正进入之后才会发现其博大精深,涉足6年余,才仅有点感觉,在此稍做总结,与涉入测试领域的同志共勉:

    阶段一:入门 1、软件工程:软件开发模式首先了解软件研发的过程,才能采取不同的测试策略。如传统的瀑布模型,就可以按V模型的方式进行测试的计划、设计和执行工作;如果是RUP方式,则测试过程就要按照历次迭代进行分阶段的测试,每次迭代的测试方法和重点会有所不同。还有很多开发模式,测试工作都需要根据不同情况进行适当调整。 2、测试理论:基本过程与方法系统测试、集成测试、单元测试以及BETA测试、验收测试等的测试依据不同,所使用的方法也不同,边界值法、等效类划分、错误推测、因果图以及条件覆盖、判定覆盖等等,方法非常多,在各阶段测试设计过程中都会用到,所以作为基础课程必须掌握。

    二、进阶 了解了上面两条,相当于刚学会什么叫编程语言、C语言的语法是什么,能编写HELLOWORLD小程序了,会编码不等于能编好代码,测试也是一样。掌握上面两条已经可以拿着一个产品说明书开始用产品了,进行初级的系统功能测试(勉强算测试吧:),真正要深入,还需要再学习以下内容 3、软件特性:软件产品的基本特性 首先知道一个软件必须要具有的基本特性,即一个好的软件是什么样子的,才可能去有目的的设计测试用例。ISO的一些标准中定义了软件的质量模型,functionality、reliability、usability、efficiency、maintainability、portability等,这些在真正进行测试设计前必须能够详细了解,没有这些基础,拿着简单的几份需求、设计文档进行测试是远远不够的。 4、测试设计:测试的精髓所在 要进行测试,必须要提前知道测试什么、怎么测,这时候就需要进行测试策略、方案、用例的设计了。这种设计的基础除上面提到的3个大的内容都要用到外,还要对被测对象进行重复的了解,同时要考虑是否需要驱动/桩模块/模拟环境的支持、如何来设计这些模块与环境、需要什么样的工具、用什么样的方法、用户真正使用的环境是什么等等,测试设计的能力需要在不断的实际项目操作经验中积累。
    5、测试工具-提高测试效率的手段 个人认为测试工具在测试知识领域内的重要性并不是很强,属于辅助性的一种手段,可以用来提高效率,但不能依靠它来保证产品质量。测试工具现在已是林林总总,见过的、用过的已有几十种之多,这部分的学习先从面上入手,从功能测试、性能测试、代码测试等几个领域找出几个典型工具,先了解它们能做什么、不能做什么,在测试设计时可以根据情况具体选择,在测试实施过程中再熟练掌握。 掌握上面这些内容,已经可以参与一些项目的测试了,经过一、二年的实践经验,可以说骄傲地说自己已经是个测试工程师了。


    三、高级-更全面、更系统最主要经验更丰富 测试这个领域,所谓高级是无法确定的,所以在此也不敢指导如何成为高级测试工程师,只能说前5条都很熟了以后,可以在其它一些领域进行深入探索: 6、测试流程 方法、工具是回事,真正能把这些东西连贯使用,很好的执行,还需要测试流程来保证,业界有现成的流程可参考,但也只能做参考,团队的规模、产品的领域不同流程肯定不同,制定一套完整、顺畅的流程才是让测试工作有效执行的保证。 7、系统分析 具有系统分析能力的测试工程师才能在产品早期即需求、设计阶段发现产品的问题,盲目地跟着开发需求、设计文档走地测试只能保证产品问题不多,产品没问题并不代表产品就能用、好用。 8、技术创新 测试领域没有固定的、一成不便的理论和方法,在经验积累之后,可以针对产品、环境的不同摸索出不同的流程、方法,可以设计自己的测试文档体系,也建立自己的测试工具平台,向上的空间是永无止境的。  



    目前业界测试工具包括商用的、免费的至少也有上百种,仅掌握一、两种测试工具如同沧海一粟,是远远不够的。测试如同编程,测试如果要做好,真正的决定因素在于测试的设计,工具只是辅助工作的一种手段而已,换句话说,测试工程师才是测试工作的主体,测试工程师的能力和素质决定了测试工作和产品的质量。测试工具象是工程师手里的双刃剑,选不好或用不好就不能提高效率、节约成本,如一些功能自动化测试工具,如ROBOT、QARUN、WINRUNNER之类的,对于新推出的产品,往往客户需求经常变化,版本间改动会很大,这时这些工具就用不上,因为每次都要重新录制脚本,下次还用不上,录制脚本的过程实际就是测试的过程,这个阶段的功能完全手工测试就可以了,而当版本成熟后,问题和改动比较少,这时后用功能自动测试工具主要目的仅是为避免因改动导致其它原正确使用的功能出问题(新增特性本身的测试还是要手工测试一遍的),但这种情况只要严格控制开发人员代码修改范围、做好代码走读(小修改的代码量很少)、测试人员做好周边相关功能的测试(这就要求测试人员对产品功能、系统结构的全面了解),完全可以避免,而且在使用这些工具过程中,测试人员还要花费时间去掌握脚本编程,有些工具仅支持几种语言和有限的控件,超出这些范围又要更换工具,这样算来,费用就远远不止十几万、几十万买一套工具了,人工成本增加不少,测试效率也未必提高。性能测试工具也很多,而且侧重点也不同,商用工具共同的特点就是奇贵,其实业界管理类软件的复杂度并不高,C/S、B/S结构的免费性能测试工具网上大把,选择一个简单好用的下载就可以了,完全没必要花重金买或用盗版的商用工具。商用性能测试工具以前用过的比较好用的也就算quantify了,用起来很简单,分析报告很细很管用,用它发现和解决了大型软件中的很多性能问题。个人认为在免费工具不能满足要求的情况下建议自己来开发性能测试工具,因为无非就测试那么几项内容,所用技术也无非就是网络编程的基础技术,这样积累下来,容易形成针对同类产品的一个实用的性能测试平台,对一个测试组就足够用了。单元测试工具建议还是必须要用的,无论商用还是免费的都可以,因为把问题扼杀在编码阶段比后期系统测试更能有效提高产品的质量。测试过程中的工具也不仅是功能、性能的自动测试,还有一些仿真工具、协议分析工具等,这些的专业性很强,可根据不同的产品来专门选择。另外,可以自行开发一些测试环境准备的小工具,对提高测试效率也是很有帮助的。总之,测试工程师要做好一个产品的测试,适当采用测试工具是必要的,但没必要完全迷信于那么一、两种测试工具,不能过分依赖测试工具,只有对各种测试工具全面了解,才能冷静、客观的去分析和选择。另外,规范开发流程、测试过程、强化测试设计的能力和素质,都是保证产品质量的有效手段。人的素质提高、作用提高了,工具的作用自然会相对减弱,企业也就会把关注点从测试工具使用转移到测试人才培养,测试工程师的地位也就会逐步得到提高了。
211/212>
Open Toolbar