VS2010测试功能之旅:编码的UI测试(3)-操作对象的识别原理

VS2010测试功能之旅

——编码的UI测试系列之三:操作对象的识别原理

RealZhao,2011年3月02日

回顾

在之前的两章分别介绍了一个简单的示例, 操作动作的录制原理通过修改UIMap.UItest文件控制操作动作代码的生成。想必大家对编码的UI测试操作动作的录制应该有一定了解了,在UI操作中,操作动作总是离不开具体的操作对象,例如点击,拖动,填写值等操作,总是要对文本框,或者按钮,窗体这些对象进行操作,不是凭空生成的。本章作为入门篇的最后一章,将会说明编码的UI测试是如何识别这些对象的,并介绍UIMap.UItest文件是如何生成对象识别代码。

 

对象的识别原理

之前我们录制的时候,录制生成器解析了我们的操作对象,并且为我们生成了对象识别代码(也就是UIMap.UItest下<Map>节点的那部分),以便我们在回放的时候,能够识别到我们要操作的是哪一个对象

在编码的UI测试中,对象的识别主要是同时按以下三个方面进行

1. 按对象类别:对象属于什么类别,例如是button还是textBox

2. 按关键标识属性:能唯一识别该对象的属性

3. 按层级关系:对象在其父对象中的层次

下面开始进行详细介绍

一.对象类别: 

为便于理解,以web程序为例,假设我们的识别代码中,写明让VS2010按WebButton识别一个对象,那么VS2010则会在页面源码中只找到那些html标签是<input type=“submit”>的控件,如果识别代码中描写的是按WebLink识别对象,则VS2010只在页面源码中找到那些是<a>的标签。

 

二.关键标识属性:

通过对象类别,已经能识别出来某一类的对象,在这个基础上,接下来就需要用关键识别属性进行精准标识了,我们需要找出能唯一识别该对象的属性,假如一个窗体如下

这个窗体中包含了3个button,我们想让VS2010操作到第一个Button,如何区分这些Button呢?这就要用到关键标识属性来标识唯一一个对象

关键标识属性分为两种----自身标识属性和辅助标识属性。

1.自身标识属性:

也就是属于对象的属性,例如,button拥有Name,Text,Enable,BackColor等属性,我们假设上面那个窗体的Button的各个属性如下

很明显可以发现,第一个button的Name属性和和其他的button不一样,那么可以用其作为他的关键标识属性,并且写在识别代码中,这样vs2010就可以在这些button中能唯一识别他,例如,将Name=button2写到识别代码中,就可以唯一识别第二个Button

假设3个button的Name一样,而BackColor不同,也可以用BackColor作为关键标识属性

2.辅助标识属性:

在自动化测试中,还有一种属性叫做辅助标识属性,他并不属于对象的属性,但可以辅助标识对象

假设刚才那个窗体的各button属性如下:

可以发现他们的自身属性都是一模一样的,那么怎么做才能让VS2010识别他呢?仔细观察可以发现这样一个情况

我们可以通过该对象是第几个对象这样的辅助属性进行标识他

比如如果要识别3个Button,则需要在识别代码中设置其辅助标识属性“对象序号”为3

 

三.层级关系:

虽然上面确定了唯一对象,的确已经可以标识出对象了,不过实际上在识别的时候还会按层级关系查找,例如第一章提到的一个简单的窗体

我们用录制生成器解析他的第一个文本框Tbx_uid,在自动生成的识别代码中,他们的层级关系是这样的

对应到刚才的Form,层级为:

VS2010在识别这个Textbox1的时候,会只识别属于 系统登录Window下的Tbx_uidWindow下的Tbx_uid文本框

(注:按照常规的理解,其实应该“系统登录窗体”和“Tbx_uid文本框”只有两个层级,也就是窗体下直接就是文本框,但是VS2010默认解析的时候,会把一个TextBox解析成两个层级,分为TextBoxWindow和TextBoxEdit,结果本来应该总共只有两级结果搞成了三级,如果仔细观察可以发现其他控件也是这样的,所以在这里纠结的朋友希望你们看到此段后能够减轻些疑惑...)

 

UIMap.UItest文件控制识别代码的生成

第二章上部分已经提到,在UIMap.uitest文件中,对象的识别代码的生成部分是放在<Maps>节点下的,点击生成代码后,会将其真正起作用的识别代码生成到UIMap.designer.cs下,那么他们的代码究竟是怎样的呢?

以刚才那个窗体生成的代码为例,我们要识别TextBox1,如果使用录制生成器,把TextBox1填入到对象库,我们来看看他生成的识别代码(可以简略看,下面会有说明)

 

ExpandedBlockStart.gif UIMap.uitest文件默认生成的<Maps>节点的代码
 1     < Maps >
 2       < UIMap  Id ="UIMap1" >
 3         < TopLevelWindows >
 4           < TopLevelWindow  ControlType ="Window"  Id ="UI系统登录Window"  FriendlyName ="系统登录"  SpecialControlType ="None"  SessionId ="199642" >
 5             < TechnologyName > MSAA </ TechnologyName >
 6             < WindowTitles >
 7               < WindowTitle > 系统登录 </ WindowTitle >
 8             </ WindowTitles >
 9             < SearchConfigurations >
10               < SearchConfiguration > VisibleOnly </ SearchConfiguration >
11             </ SearchConfigurations >
12             < AndCondition  Id ="SearchCondition" >
13               < PropertyCondition  Name ="Name" > 系统登录 </ PropertyCondition >
14               < PropertyCondition  Name ="ClassName"  Operator ="Contains" > WindowsForms10.Window </ PropertyCondition >
15               < PropertyCondition  Name ="ControlType" > Window </ PropertyCondition >
16             </ AndCondition >
17             < SupportLevel > 0 </ SupportLevel >
18             < Descendants >
19               < UIObject  ControlType ="Window"  Id ="UITbx_uidWindow"  FriendlyName ="Tbx_uid"  SpecialControlType ="None" >
20                 < TechnologyName > MSAA </ TechnologyName >
21                 < WindowTitles >
22                   < WindowTitle > 系统登录 </ WindowTitle >
23                 </ WindowTitles >
24                 < SearchConfigurations >
25                   < SearchConfiguration > VisibleOnly </ SearchConfiguration >
26                 </ SearchConfigurations >
27                 < AndCondition  Id ="SearchCondition" >
28                   < PropertyCondition  Name ="ControlName" > Tbx_uid </ PropertyCondition >
29                   < PropertyCondition  Name ="ControlType" > Window </ PropertyCondition >
30                 </ AndCondition >
31                 < SupportLevel > 0 </ SupportLevel >
32                 < Descendants >
33                   < UIObject  ControlType ="Edit"  Id ="UITbx_uidEdit"  FriendlyName ="Tbx_uid"  SpecialControlType ="None" >
34                     < TechnologyName > MSAA </ TechnologyName >
35                     < WindowTitles >
36                       < WindowTitle > 系统登录 </ WindowTitle >
37                     </ WindowTitles >
38                     < SearchConfigurations >
39                       < SearchConfiguration > VisibleOnly </ SearchConfiguration >
40                     </ SearchConfigurations >
41                     < AndCondition  Id ="SearchCondition" >
42                       < PropertyCondition  Name ="Name" > 密码 : </ PropertyCondition >
43                       < PropertyCondition  Name ="ControlType" > Edit </ PropertyCondition >
44                     </ AndCondition >
45                     < SupportLevel > 0 </ SupportLevel >
46                     < Descendants  />
47                   </ UIObject >
48                 </ Descendants >
49               </ UIObject >
50             </ Descendants >
51           </ TopLevelWindow >
52         </ TopLevelWindows >
53       </ UIMap >
54     </ Maps >

 

别看UIMap.uitest里为这些对象生成的了一大堆代码,其实对象中真正管作用的属性就ControlType,ID两个:

ID这个属性表示调用对象在对象库中的ID,例如在第二章下部分,编写ExecuteActions的时候,描述对那个对象进行操作

ControlType这个属性用于描述按什么类别来识别对象,识别原理之一的对象类别就是用这个表示

 

而管作用的节点也就这么两个:

<AndCondition>这个节点表示识别条件,他的子节点为<PropertyCondition>,表示具体识别条件,识别原理之二的关键标识属性就用这个表示

<Descendants>这个节点用于存放这个对象的子对象,识别原理之三的层级关系就是用这个表示

 

 

现在把上面自动生成的代码优化一下,把不必要的代码删除,并加上注释。然后再使用这段XML代码在录制生成器生成UIMap.designer.cs代码

 

 1     < Maps >
 2       < UIMap  Id ="UIMap1" >
 3         < TopLevelWindows >
 4           <!-- 表示最高级别的窗体,属性ControlType表示按类型“Window”类型识别对象,对应识别原理之一 -->
 5           < TopLevelWindow   ControlType ="Window"  Id ="UI系统登录Window" >
 6             <!-- TechnologyName标签没有实际作用,但是删除了会报错,因此保留,之后的也是 -->
 7             < TechnologyName > MSAA </ TechnologyName >
 8             < AndCondition  Id ="SearchCondition" >
 9               <!-- 表示窗体的关键标识属性,识别的时候寻找Name属性为“系统登录”的窗体,对应识别原理之二 -->
10               < PropertyCondition  Name ="Name" > 系统登录 </ PropertyCondition >
11               <!-- 表示窗体的关键标识属性,识别的时候寻找ClassName属性为“WindowsForms10.Window”的窗体 -->
12               < PropertyCondition  Name ="ClassName"  Operator ="Contains" > WindowsForms10.Window </ PropertyCondition >
13             </ AndCondition >
14             <!-- 表示窗体的子对象,对应识别原理之三 -->
15             < Descendants >
16               <!-- UI对象,按类型“Window”类型识别 -->
17               < UIObject  ControlType ="Window"  Id ="UITbx_uidWindow" >
18                 < TechnologyName > MSAA </ TechnologyName >
19                 < AndCondition  Id ="SearchCondition" >
20                   <!-- 关键标识属性,ControlName属性为“Tbx_uid”的对象 -->
21                   < PropertyCondition  Name ="ControlName" > Tbx_uid </ PropertyCondition >
22                 </ AndCondition >
23                 <!-- 他的子对象 -->
24                 < Descendants >
25                   <!-- UI对象,按类型“Edit”(文本框)类型识别 -->
26                   < UIObject  ControlType ="Edit"  Id ="UITbx_uidEdit" >
27                     < TechnologyName > MSAA </ TechnologyName >
28                     < AndCondition  Id ="SearchCondition" >
29                       <!-- 关键标识属性,Name属性为“密码 :” -->
30                       < PropertyCondition  Name ="Name" > 密码 : </ PropertyCondition >
31                     </ AndCondition >
32                     < Descendants  />
33                   </ UIObject >
34                 </ Descendants >
35               </ UIObject >
36             </ Descendants >
37           </ TopLevelWindow >
38         </ TopLevelWindows >
39       </ UIMap >
40     </ Maps >

 

 接下来使用录制生成器生成UIMap.designer.cs代码,可以看到代码如下

 

 1      [GeneratedCode( " 编码的 UI 测试生成器 " " 10.0.30319.1 " )]
 2       public   class  UI系统登录Window : WinWindow // 这里的继承于WinWindow,是根据刚才XML文件里的属性ControlType="Window"生成的,表示按Window识别,对应识别原理之一
 3      {
 4          
 5           public  UI系统登录Window()
 6          {
 7               // 这里是搜索条件,也就是关键识别属性,根据XML文件的AndCondition节点中的内容生成,对应识别原理之二
 8               #region  搜索条件
 9               this .SearchProperties[WinWindow.PropertyNames.Name]  =   " 系统登录 " ;
10               this .SearchProperties.Add( new  PropertyExpression(WinWindow.PropertyNames.ClassName,  " WindowsForms10.Window " , PropertyExpressionOperator.Contains));
11               #endregion
12          }
13 
14           // 这里是他的子对象,对应于XML文件的Descendants节点,对应识别原理之三
15           #region  Properties
16           public  UITbx_uidWindow UITbx_uidWindow
17          {
18               get
19              {
20                   if  (( this .mUITbx_uidWindow  ==   null ))
21                  {
22                       this .mUITbx_uidWindow  =   new  UITbx_uidWindow( this );
23                  }
24                   return   this .mUITbx_uidWindow;
25              }
26          }
27           #endregion
28          
29           #region  Fields
30           private  UITbx_uidWindow mUITbx_uidWindow;
31           #endregion
32      }
33      
34 
35      [GeneratedCode( " 编码的 UI 测试生成器 " " 10.0.30319.1 " )]
36       public   class  UITbx_uidWindow : WinWindow //这里的继承于WinWindow,是根据刚才XML文件里的属性ControlType="Window"生成的,表示按Window识别
37      {
38          
39           public  UITbx_uidWindow(UITestControl searchLimitContainer) : 
40                   base (searchLimitContainer)
41          {
42               // 这里是搜索条件,也就是关键识别属性,根据XML文件的AndCondition节点中的内容生成
43               #region  搜索条件
44               this .SearchProperties[WinWindow.PropertyNames.ControlName]  =   " Tbx_uid " ;
45               #endregion
46          }
47           // 这里是他的子对象,对应于XML文件的Descendants节点
48           #region  Properties
49           public  WinEdit UITbx_uidEdit // 这里的类型为WinEdit,是根据刚才XML文件里的属性ControlType生成的(ControlType="Edit")
50          {
51               get
52              {
53                   if  (( this .mUITbx_uidEdit  ==   null ))
54                  {
55                       this .mUITbx_uidEdit  =   new  WinEdit( this );
56                       // 这里是搜索条件,也就是关键识别属性,根据XML文件的AndCondition节点中的内容生成
57                       #region  搜索条件
58                       this .mUITbx_uidEdit.SearchProperties[WinEdit.PropertyNames.Name]  =   " 密码 : " ;
59                       #endregion
60                  }
61                   return   this .mUITbx_uidEdit;
62              }
63          }
64           #endregion
65          
66           #region  Fields
67           private  WinEdit mUITbx_uidEdit;
68           #endregion
69      }

 

总结

在本章介绍了VS2010的对象识别原理,想必大家对这个应该有所了解了吧?

我曾今在用UI测试做项目的时候,经常会发现这样那样的对象不能用录制生成器识别,这个时候怎么办呢?了解了对象识别原理,就可以自己改XML文件来控制对象的识别,如果有想做这方面练习的朋友,可以留下你的邮箱,我这里正在编写一个C# Winform小程序,这个程序上的所有控件都经过特殊处理,无法用录制生成器识别,只有通过自己修改XML文件来控制它的识别,如果想试试自己的身手,别忘了留下邮箱哦~~

到这里编码的UI测试的入门篇就完结了,接下来会进入进阶篇,以实际的例子描述如何对一个项目进行测试

 

附1:VS2010编码的UI测试支持识别的对象

平台支持级别
Windows Internet Explorer 7.0
Windows Internet Explorer 8.0
(包括 HTML 和 AJAX)
完全支持
Windows Internet Explorer 6.0不支持
镶边OperaSafari不支持
Silverlight 3.0不支持
Flash/Java不支持
Windows 窗体 2.0 及更高版本完全支持
注意
完全支持 NetFx 控件,但并非支持所有第三方控件。
WPF 3.5 及更高版本完全支持
注意
完全支持 NetFx 控件,但并非支持所有第三方控件。
Windows Win32可适用于某些已知问题,但不正式支持
MFC可适用于某些已知问题,但不正式支持
SharePoint部分支持
Office 客户端应用程序不支持
Dynamics (Ax)部分支持
SAP不支持
Citrix/终端服务部分支持

注:Silverlight4 现在已支持,详情见http://www.silverlightshow.net/news/Coded-UI-testing-for-Silverlight-4-now-available-.aspx

园子里scottxu已有这方面研究,相关文章http://www.cnblogs.com/scottxu/archive/2011/02/28/1967112.html

 

附:发布计划

编码的UI测试系列之一:入门篇 一个简单的示例(Released)

编码的UI测试系列之二:入门篇 操作动作的录制原理(上)(Released)

编码的UI测试系列之二:入门篇 操作动作的录制原理(下)(Released)

编码的UI测试系列之三:入门篇 操作对象的识别原理 (Released)

编码的UI测试系列之四:进阶篇 通过编写测试代码的方式建立UI测试(上)(Released)

编码的UI测试系列之四:进阶篇 通过编写测试代码的方式建立UI测试(下)(Released)

编码的UI测试系列之五:进阶篇 常用测试要点和函数(1

编码的UI测试系列之六:进阶篇 常用测试要点和函数(2

编码的UI测试系列之七:进阶篇 UI测试之间的互相引用和测试组织

编码的UI测试系列之八:高级篇 远程调用其他机器进行测试

编码的UI测试系列之九:高级篇 使用MS测试管理器组织测试

 

转载于:https://www.cnblogs.com/realdigit/archive/2011/03/02/1968454.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值