技术开发 频道

Visual Studio2010测试:对象识别原理

    【IT168 技术】对象的识别原理

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

  在编码的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文件中,对象的识别代码的生成部分是放在节点下的,点击生成代码后,会将其真正起作用的识别代码生成到UIMap.designer.cs下,那么他们的代码究竟是怎样的呢?

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

<Maps>
  
<UIMap Id="UIMap1">
    
<TopLevelWindows>
      
<TopLevelWindow ControlType="Window" Id="UI 系统登录Window" FriendlyName="系统登录" SpecialControlType="None" SessionId="199642">
        
<TechnologyName>MSAA</TechnologyName>
        
<WindowTitles>
          
<WindowTitle> 系统登录</WindowTitle>
        
</WindowTitles>
        
<SearchConfigurations>
          
<SearchConfiguration>VisibleOnly</SearchConfiguration>
        
</SearchConfigurations>
        
<AndCondition Id="SearchCondition">
          
<PropertyCondition Name="Name"& gt;系统登录</PropertyCondition>
          
<PropertyCondition Name="ClassName" Operator="Contains">WindowsForms10.Window</PropertyCondition>
          
<PropertyCondition Name="ControlType">Window</PropertyCondition>
        
</AndCondition>
        
<SupportLevel>0</SupportLevel>
        
<Descendants>
          
<UIObject ControlType="Window" Id="UITbx_uidWindow" FriendlyName="Tbx_uid" SpecialControlType="None">
            
<TechnologyName>MSAA</TechnologyName>
            
<WindowTitles>
              
<WindowTitle> 系统登录</WindowTitle>
            
</WindowTitles>
            
<SearchConfigurations>
              
<SearchConfiguration>VisibleOnly</SearchConfiguration>
            
</SearchConfigurations>
            
<AndCondition Id="SearchCondition">
              
<PropertyCondition Name="ControlName">Tbx_uid</PropertyCondition>
              
<PropertyCondition Name="ControlType">Window</PropertyCondition>
            
</AndCondition>
            
<SupportLevel>0</SupportLevel>
            
<Descendants>
              
<UIObject ControlType="Edit" Id="UITbx_uidEdit" FriendlyName="Tbx_uid" SpecialControlType="None">
                
<TechnologyName>MSAA</TechnologyName>
                
<WindowTitles>
                  
<WindowTitle> 系统登录</WindowTitle>
                
</WindowTitles>
                
<SearchConfigurations>
                  
<SearchConfiguration>VisibleOnly</SearchConfiguration>
                
</SearchConfigurations>
                
<AndCondition Id="SearchCondition">
                  
<PropertyCondition Name="Name"& gt;密码 :</PropertyCondition>
                  
<PropertyCondition Name="ControlType">Edit</PropertyCondition>
                
</AndCondition>
                
<SupportLevel>0</SupportLevel>
                
<Descendants />
              
</UIObject>
            
</Descendants>
          
</UIObject>
        
</Descendants>
      
</TopLevelWindow>
    
</TopLevelWindows>
  
</UIMap>
</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代码,可以看到代码如下:

  [GeneratedCode("编码的 UI 测试生成器", "10.0.30319.1")]

  
public class UI 系统登录Window : WinWindow//这里的继承于WinWindow,是根据刚才XML文件里的属性 ControlType="Window"生成的,表示按Window识别,对应识别原理之一

  {

  
public UI 系统登录Window()

  {

  
//这里是搜索条件,也就是关键识别属性,根据XML 文件的AndCondition节点中的内容生成,对应识别原理之二

  
#region 搜索条件

  
this.SearchProperties[WinWindow.PropertyNames.Name] = " 系统登录";

  
this.SearchProperties.Add(new PropertyExpression(WinWindow.PropertyNames.ClassName, "WindowsForms10.Window", PropertyExpressionOperator.Contains));

  
#endregion

  }

  
// 这里是他的子对象,对应于XML文件的Descendants节点,对应识别原理之三

  
#region Properties

  
public UITbx_uidWindow UITbx_uidWindow

  {

  
get

  {

  
if ((this.mUITbx_uidWindow == null))

  {

  
this.mUITbx_uidWindow = new UITbx_uidWindow(this);

  }

  
return this.mUITbx_uidWindow;

  }

  }

  
#endregion

  
#region Fields

  
private UITbx_uidWindow mUITbx_uidWindow;

  
#endregion

  }

  [GeneratedCode(
" 编码的 UI 测试生成器", "10.0.30319.1")]

  
public class UITbx_uidWindow : WinWindow// 这里的继承于WinWindow,是根据刚才XML文件里的属性ControlType="Window"生成的,表示按Window识别

  {

  
public UITbx_uidWindow(UITestControl searchLimitContainer) :

  
base(searchLimitContainer)

  {

  
// 这里是搜索条件,也就是关键识别属性,根据XML文件的AndCondition节点中的内容生成

  
#region 搜索条件

  
this.SearchProperties[WinWindow.PropertyNames.ControlName] = "Tbx_uid";

  
#endregion

  }

  
// 这里是他的子对象,对应于XML文件的Descendants节点

  
#region Properties

  
public WinEdit UITbx_uidEdit// 这里的类型为WinEdit,是根据刚才XML文件里的属性ControlType生成的(ControlType="Edit")

  {

  
get

  {

  
if ((this.mUITbx_uidEdit == null))

  {

  
this.mUITbx_uidEdit = new WinEdit(this);

  
// 这里是搜索条件,也就是关键识别属性,根据XML文件的AndCondition节点中的内容生成

  
#region 搜索条件

  
this.mUITbx_uidEdit.SearchProperties[WinEdit.PropertyNames.Name] = " 密码 :";

  
#endregion

  }

  
return this.mUITbx_uidEdit;

  }

  }

  
#endregion

  
#region Fields

  
private WinEdit mUITbx_uidEdit;

  
#endregion

  }

  总结

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

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

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

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

0
相关文章