回顾 

  在之前的两章分别介绍了一个简单的示例, 操作动作的录制原理,通过修改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填入到对象库,我们来看看他生成的识别代码(可以简略看,下面会有说明)。

<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代码:

<Maps>
<UIMap Id="UIMap1">
<TopLevelWindows>
<!-- 表示最高级别的窗体,属性ControlType表示按类型“Window”类型识别对象,对应识别原理之一-->
<TopLevelWindow ControlType="Window" Id="UI 系统登录Window">
<!--TechnologyName标签没有实际作用,但是删除了会报错,因此保留,之后的也是-->
<TechnologyName>MSAA</TechnologyName>
<AndCondition Id="SearchCondition">
<!-- 表示窗体的关键标识属性,识别的时候寻找Name属性为“系统登录”的窗体,对应识别原理之二-->
<PropertyCondition Name="Name"& gt;系统登录</PropertyCondition>
<!--表示窗体的关键标识属性,识别的时候寻找ClassName属性为“WindowsForms10.Window”的窗体-->
<PropertyCondition Name="ClassName" Operator="Contains">WindowsForms10.Window</PropertyCondition>
</AndCondition>
<!-- 表示窗体的子对象,对应识别原理之三-->
<Descendants>
<!--UI 对象,按类型“Window”类型识别-->
<UIObject ControlType="Window" Id="UITbx_uidWindow">
<TechnologyName>MSAA</TechnologyName>
<AndCondition Id="SearchCondition">
<!-- 关键标识属性,ControlName属性为“Tbx_uid”的对象-->
<PropertyCondition Name="ControlName">Tbx_uid</PropertyCondition>
</AndCondition>
<!-- 他的子对象-->
<Descendants>
<!--UI 对象,按类型“Edit”(文本框)类型识别-->
<UIObject ControlType="Edit" Id="UITbx_uidEdit">
<TechnologyName>MSAA</TechnologyName>
<AndCondition Id="SearchCondition">
<!-- 关键标识属性,Name属性为“密码 :”-->
<PropertyCondition Name="Name"& gt;密码 :</PropertyCondition>
</AndCondition>
<Descendants />
</UIObject>
</Descendants>
</UIObject>
</Descendants>
</TopLevelWindow>
</TopLevelWindows>
</UIMap>
</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测试支持识别的对象  

平台 支持级别
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

[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
}

转载于:https://www.cnblogs.com/waw/archive/2011/09/02/2162940.html

一起谈.NET技术,VS2010测试功能之旅:编码的UI测试(3)-操作对象的识别原理...相关推荐

  1. VS2010测试功能之旅:编码的UI测试(6)- 提高UI测试稳定性的8个方法(下)

    VS2010测试功能之旅 --编码的UI测试系列之六:提高UI测试稳定性的8个方法(下) RealZhao,2011年5月11日 回顾 在之前,我们介绍了提高UI测试稳定性的8个方法的前6个,接下来介 ...

  2. 【转】VS2010测试功能之旅:编码的UI测试(2)-操作动作的录制原理(上)

    VS2010测试功能之旅 --编码的UI测试系列之二:操作动作的录制原理(上) RealZhao,2011年2月18日 回顾 在之前我们介绍了如何用VS2010的UI测试功能创建一个简单的示例,大致描 ...

  3. 一起谈.NET技术,VS2010测试功能之旅:编码的UI测试(2)-操作动作的录制原理(下)...

    回顾 在本章上部分介绍了操作动作的录制原理,描述了操作动作是如何录制,UIMap.uitest和UIMap.Designer.cs的代码如何生成,以及他们的结构.在这个部分,将着重说明如何通过修改UI ...

  4. VS2010 测试功能之旅:编码的UI测试(4)-通过编写测试代码的方式“.NET研究”建立UI测试(下)...

    回顾 最近比较忙,距离上次更新的时间较久,见谅. 在本章上部分,介绍了"添加用户"窗口的测试代码编写.想必大家也看到了,在UIMap.cs文件中实现自定义编码是一件很轻松的事情,接 ...

  5. VS2010测试功能之旅:编码的“.NET研究”UI测试(2)-操作动作的录制原理(上)...

    回顾  在之前我们介绍了如何用VS2010的UI测试功能创建一个简单的示例,大致描述了如何使用编码的UI测试进行录制和回放,在这章会着重描述VS2010是如何录制操作,并且生成代码,以及初步介绍如何通 ...

  6. 使用编码的 UI 测试来测试 Windows 应用商店应用

    自从Win8应运而生以来,Windows应用商店便立马成为开发者展示的舞台,而这短短的几年里应用的数量就可数以万计,这也不可避免地出现了良莠不齐的局面.我们都知道Visual Studio是目前最流行 ...

  7. 通过VS编码的UI测试来测试用户界面(一)

    通过VS编码的UI测试来测试用户界面(一) 1.前期操作: 1.文件->新建->项目 2.测试->编码的UI测试项目->填写项目名称(这里就不改变了) 3.点击确定后会出现如下 ...

  8. 测试功能范围_IT8511+电子负载 OCP?测试功能

    IT8511+电子负载 OCP 测试功能 IT8500+系列电子负载具有过电流保护(OCP)测试功能,在 OCP 测试模式下,当输入电压达到 Von 值时,延时一段时间,电流开始工作,每隔一定时间按步 ...

  9. 前端如何实现网络速度测试功能_前端组件单元测试

    啥?单元测试?我哪有时间写单元测试? 从软件质量说起 日常生活中,商品质量永远是我们进行选择时需要着重考虑的因素,计算机软件也不例外.优秀的软件应当如我们预期的一样工作,能够正确地处理所有功能性需求. ...

最新文章

  1. 在 Linux 下运行 ASP.NET 2.0
  2. 常用加密算法的Java实现(一) ——单向加密算法MD5和SHA
  3. 参数--argumengs
  4. Rest之一-什么是REST?以及RESTful的实现
  5. C语言入门经典题目及其答案
  6. 配置postfix+dovecot+mysql+postfixadmin+squirrelmail 邮件系统笔记
  7. Android实用代码七段(二)
  8. VS2010链接SQLsever2008数据库时出现[DBNETLIB][ConnectionOpen (Connect()).]SQL Server 不存在或拒
  9. Vue之不常注意的点
  10. pdf reference官方指南之-图片
  11. 带外壳版本4G LTE模块,包括华为ME909系列、移远EC20系列、移远EC200T系列
  12. JAVA垃圾回收器与垃圾回收算法
  13. ROS中关于yaml文件参数的读取,和nh.param函数
  14. XP系统最大能支持多少内存
  15. WIFI能杀死植物吗?
  16. 作业调度系统--SGE和PBS的使用方法
  17. JAVA-读取excel转成html 将excel表格转换为HTML文件格式 转成前端表格样式
  18. FileDetector-基于java开发的照片整理工具
  19. 小米一面、二面,面经
  20. kali系统升级(包含软件信息、所有软件、整个系统)

热门文章

  1. android easylink 搜索设备_手把手教你将数据从Android移动到iPhone步骤与技巧
  2. c++ array容器 传参_华东理工:氮和氧共掺杂的分级多孔碳,用于超级电容器的电极材料...
  3. java jersey使用总结_jersey使用指南
  4. 哪个版本好_《道德经》道尽人生大智慧,哪个版本《道德经》的注释比较好呢?...
  5. 远程服务器如何传文件大小,linux服务器远程传文件大小
  6. Go实现启动参数加载
  7. 在 Linux 中把一个网页转换成 PDF的技巧介绍
  8. Cargo 教程介绍
  9. 介绍java -cp java -jar的区别
  10. 十分钟理解Java泛型擦除