一、FrameworkManager简介
FrameworkManager是由Yaron Assa(www.AdvancedQTP.com)开发的一个开源的QTP自动化测试框架,目的是让QTP的脚本编写更为优雅和清晰(for elegant, clean scripting with QTP)。
通常我们构建的代码会变得很臃肿,过于复杂而难以维护,例如写了很多的Select-Case或If结构的语句(如果输入域仅能接受Email格式数据,则这样;如果只能接受地址,则那样...)。按照这种方式写的脚本会难以维护,因为一旦被测试的应用程序添加了新的输入域,则需要重复很多代码修改和调整的工作,使用FrameworkManager则能让这些工作成为过去。
FrameworkManager仅仅关注脚本需要的信息,从而保持脚本代码的简单,避免凌乱的代码。决策判断的结构语句被分解成独立的小类,这些小类可以被轻易地维护和更新,而不至于引入大量的BUG。更重要的是,FrameworkManager是环境无关的,能被轻易地扩展用于处理那些尚未被识别的对象和控件。
二、FrameworkManager的特点
下面列举FrameworkManager的一些功能特性:
1.保持脚本简洁明了。处理对象变成了简单的oObject.Input(“New Value”)。
2.在内部自动处理不同输入类型,例如两个文本输入框,一个仅能输入Email,一个仅能输入数字。
3.在内部自动处理相互关联的操作,也就是说,把两个或多个对象操作组合成一个逻辑顺序的操作,例如单击一个按钮来验证输入框的数据;输入密码紧跟着验证密码。
4.在内部自动选择值验证的方式,例如:
Delegation – 在某个对象中输入一个值,但是在另外一个对象中显示出来。 Regular Expressions – 输入一个值,但是以前缀或后缀显示出来。
5.在内部自动处理条件输入-你可以很容易地设置一个标记来标识某个对象是不可输入的或不可操作的(untouchable),例如你有两个输入域,通过一个按钮来控制其“enabled”和“disabled”属性。
6.在内部自动处理随机值-例如从一个combo-box或list-box控件中随机选择其中的一项。
7.可轻易地为应用程序对象添加个性化的属性,例如标志某些输入域为强制性的(mandatory),把这些输入域与某个查询窗口中的数据域关联,然后在脚本中利用这些数据,快速填充这些强制性输入域的数据。
8.被测试应用程序的对象都被结构化成一个树状,让你可以在脚本中做复杂的对象搜索和操作,例如在某个TAB页下的所有输入框输入所有数据;从一个WebTable转到其父级的Frame中。
9.为了更好地组织对象树,可以添加一些虚拟的层次,从而得到一个可读性更强的对象树。
10.可扩展性强-可以在不修改已有代码的情况下添加新的数据类型产生和输入方法。FrameworkManager可以处理你添加的任何扩展、不可识别的控件和针对被测试应用程序的业务逻辑处理。
三、FrameworkManager框架的组成
FrameworkManager框架主要由3大部分组成:
1.对象树文件(ObjectTree)
这个Excel文件作为可扩展的对象库(Object-Repository),它包含FrameworkManager识别对象所需要的所有数据,以及所有对象的元数据(meta-data),例如强制输入域等。
2.对象树类(clsTreeLevel)
这个类包含FrameworkManager的真正机制。在运行时,根据对象树Excel文件生成对象树实例,所以对象操作都是通过树节点进行封装的。
3.子类(Min、i-classes)
对于树中的每一个节点(例如clsTreeLevel类中的每一个实例),都可以“插入”(plugged)一个这样的子类(mini-class)。它们控制相关的程序对象如何输入数据、操作,如何产生随机的数据等。
对象树Excel文件
可以在/Resources/ObjectTree.xls中找到该Excel文件,如果要让clsTreeLevel.vbs正确地运行起来,请确保把clsTreeLevel.vbs文件中的sExcelFile这个常量的值修改为Excel文件所在的实际路径,这些文字转自:http://softtest.chinaitlab.com/qita/778764.html
四、FrameworkManager框架代码解析
FrameworkManager目前的最新版本是0.81,可到以下地址下载:
http://www.advancedqtp.com/knowledge-base/projects/frameworkmanager/frameworkmanager-version-081/
解压目录结构如下图:
/Documentation 帮助文档。
/Libraries FrameworkManager框架的代码,包括对象树类、输入类等。
/Resources 包含对象树的Excel文件。
/Demo App 用于演示FrameworkManager用法的Demo小程序。
/Tests 用于演示FrameworkManager用法的Test。下面的Demo是qtp文件,作为测试用。
对象树Excel 文件:
Excel文件分成两部分,左边部分是具有层次结构关系的对象树,右边部分是对象的相关属性,例如QTPClass、InPutType等。
Excel表中右边部分的各个列名所代表的属性的含义:
1. Mandatory – True/False:用于标识该输入域是否为强制性的。
2. Condition-只有当该输入域的条件得到满足时,才输入。在Excel单元格中填写的格式是:FieldName>Expected Value| FieldName>Expected Value(多个条件用“|”隔开),例如VB Demo_Example 2_Field 1_Enable_Flag>False表示在对象数中该节点的值必须为False。对于负条件,则使用:FieldName>%NOT%UnExpectedValue
3. PreActions – 在输入之前必须完成的操作,填写格式为:FieldName>Value|FieldName>Value(多个前置的操作用“|”隔开),输入空值可用“%EMPTY%”表示。
4. PostActions-与PreActions类似,用于表示在输入之后必须完成的操作。
5.DPID-对象的描述性编程字符串,例如:vbname:=Something|visible:=True。如果不想使用描述性编程,而是希望通过自己编写的函数来指向一个QTP对象的话,则可使用“%FunctionName%”来获取,例如下面的GetBrowser函数:
Function GetBrowser(sRedundentParam)
If Browser("Something").Exist then
Set GetBrowser = Browser("Something")
Else Set GetBrowser = Nothing End If End Funtion
QTPClass-指定对象的类型(micclass),例如VBCombobox、Browser等。
6. InputType-当给对象树的某个节点输入时采用的子类,例如Text、Combo。这里填入的子类名加上前缀“Input”和后缀“Class”就成为脚本中能识别的子类(mini-class),对应IputClasses.vbs中的InputTextClass、InputButtonClass等。
7. Type-对象树节点的业务逻辑意义,例如Field、Tab、SaveButton等。
8. RandomValueType-当给对象树的某个节点随机输入时采用的子类,例如Text、Combo等。这里填入的子类名加上前缀“RandomValue”和后缀“Class”,就成为脚本中能识别的子类,对应RandomValueClasses.vbs中的RandomValueTextClass、RandomValueCheckboxClass等。
9.ValueInObject-对象树节点的输入操作被验证时所需的标识。有时候在一个字段输入一个值后,需要访问另外一个字段或对象,以便检查输入是否成功。
10. ValidatePattern-用于验证输入操作的正则表达式。用%Value%表示原本的输入值。用“.*%Value%.*”表示实际值中只要包含了原本的值即为成功。
脚本代码解析:
关键字Me:代表当前执行类实例,适用于类模块的过程中,把当前执行类实例的有关信息传到另一个模块的过程中。Me表示引用类的当前实例的对象,用来引用代码正在执行的该类的特定实例。在这里就表示当前clsTreeLevel当前的类,用来增加子节点时,把当前clsTreeLevel类的树结构作为子节点的Parent,Set oNewChild = New clsTreeLevel,
Set oNewChild.Parent = Me.
其实Me的这些文字描述有些我也是查询得来的,根据我的调试,发现在读Excel 第三行的“VB Demo”数据时,Me就是节点的上一级sTreeLevel类实例,当前结构值如图:
我们再看下执行到下一行数据"Example 1”的数据时,执行到AddChild方法中Set oNewChild.Parent = Me这行之前Me的结构图:
parent展开图:
所以推理,执行到数据“Field 1”时,Me结构就是到Example 1这个节点的树结构。
执行到数据“Example 4 Window”时,Me的结构图:
花了这么多时间来理解vbs的这个Me关键字,突然觉悟,一句话,Me就是当前执行数据的上一级clsTreeView的树结构,Me结构中的Children的个数就是当前节点下一个同级别的子节点个数。
clsTreeLevel.vbs执行过程:Class_Initialize --> BuildRootFromFile -调用-> ( BindLevel -调用-> (LoadFieldData,AddChild) )
--> Class_Terminate
BuildRootFromFile :读取excel指定sheet的值,并把值存到arrRange数组里,调用BindLevel方法
BindLevel :build一个树结构,通过递归循环把当前节点加入到父节点中,形成一个完整的excel一样的树形结构。
LoadFieldData :把当前节点的对应属性添加到dictionary中
AddChild :把当前执行数据添加到Me(执行数据上一级)的节点。
再了解下call oRoot.GetLeaf("VB Demo_Example 1_Field 1").Input("Random")这段代码运行的整个流程:
此时的oRoot的已经在clsTreeView.vbs里执行过了Set oRoot = New clsTreeLevel oRoot.BuildRootFromFile(sExcelFile)
oRoot.GetLeaf,通过一层层往下拨,得到当前的节点,然后调用clsTreeView类中的Input方法,当前传的值是"Random“,然后通过oRandomValueType,这个值在BuildRootFromFile方法里调用的SetTypes实例化过了,就是RandomValueClasses的实例,然后调用RandomValueClasses.vbs中的GenerateRandomValue方法,获得当前的控件,生成一个随机值,又回到Input方法里。
clsTreeView.vbs中的Input方法的具体流程:先判断当前节点的是否有Condition -->然后判断传进来的参数是否是"Radom",生成随机值 -->Do Pre Actions -->Validate object exists -->Actual Input -->Do Post Actions -->ValidateValue
Do Action里面又调用Me.GetLeaf,Input,形成一个循环,执行到clsTreeView类中的Input时,满足一定的条件,结束这个循环。