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

  回顾 

  在之前的两章分别介绍了一个简单的示例操作动作的录制原理通过修改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
}


时间: 2024-07-29 16:09:04

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

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

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

一起谈.NET技术,VS2010测试功能之旅:编码的UI测试(1)

前言 研究VS2010的自动化测试有一段时间了,在研究的过程中,发现网上的VS2010相关的测试资料十分稀少,这给学习带来比较大的困难.幸运的是,自己因为常用QuickTest Professional做自动化测试,并且对.Net代码比较了解,使得在学习的过程中并不是特别困难,对UI CODED TEST也已经有一定了解.本着与大家交流,共同进步的想法,思考之后,决定写这些随笔,来对VS2010的测试功能做一些探索和总结.希望大家能够多多指教! 自动化测试  自动化测试指软件测试的自动化,软件测

VS2010测试功能之旅:编码的UI测试(1)

前言 研究VS2010的自动化测试有一段时间了,在研究的过程中,发现网上的VS2010相关的测试资料十分稀少,这给学习带来比较大的困难.幸运的是,自己因为常用QuickTest Professional做自动化测试,并且对.Net代码比较了解,使得在学习的过程中并不是特别困难,对UI CODED TEST也已经有一定了解.本着与大家交流,共同进步的想法,思考之后,决定写这些随笔,来对VS2010的测试功能做一些探索和总结.希望大家能够多多指教! 自动化测试 自动化测试指软件测试的自动化,软件测试

VS“.NET研究”2010测试功能之旅:编码的UI测试(1)

前言 研究VS2010的自动化测试有一段时间了,在研究的过程中,发现网上的VS2010相关的测试资料十分稀少,这给学习带来比较大的困难.幸运的是,自己因为常用QuickTest Professional做自动化测试,并且对.Net代码比较了解,使得在学习的过程中并不是特别困难,对UI CODED TEST也已经有一定了解.本着与大家交流,共同进步的想法,思考之后,决定写这些随笔,来对VS2010的测试功能做一些探索和总结.希望大家能够多多指教! 自动化测试  自动化测试指软件测试的自动化,软件测

一起谈.NET技术,VS2010 测试功能之旅:编码的UI测试(4)-通过编写测试代码的方式建立UI测试(下)

回顾 最近比较忙,距离上次更新的时间较久,见谅. 在本章上部分,介绍了"添加用户"窗口的测试代码编写.想必大家也看到了,在UIMap.cs文件中实现自定义编码是一件很轻松的事情,接下来将介绍下个部分,查询用户窗体的测试代码的编写,以及他们测试的关联. 示例程序介绍 系统主窗口:(下载点我) 该系统拥有两个功能,"添加用户"和"查询用户": 点击添加用户后,进入添加用户子窗体:("添加用户"窗口的测试代码编写在上部分已经实现)

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

回顾  在之前我们介绍了如何用VS2010的UI测试功能创建一个简单的示例,大致描述了如何使用编码的UI测试进行录制和回放,在这章会着重描述VS2010是如何录制操作,并且生成代码,以及初步介绍如何通过自己写代码的方式进行测试. 内容简介  在上一章我们已经介绍过,建立一个编码的UI测试CodedUITest1.cs,录制完成之后,会自动生成一个UIMap1.uitest文件.  图1:录制完成后自动生成的UIMap1.uitest文件  事实上,在录制过程中起着关键作用的并非是CodedUIT

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

回顾 最近比较忙,距离上次更新的时间较久,见谅. 在本章上部分,介绍了"添加用户"窗口的测试代码编写.想必大家也看到了,在UIMap.cs文件中实现自定义编码是一件很轻松的事情,接下来将介绍下个部分,查询用户窗体的测试代码的编写,以及他们测试的关联. 示例程序介绍 系统主窗口:(下载点我) 该系统拥有两个功能,"添加用户"和"查询用户": 点击添加用户后,进入添加用户子窗体:("添加用户"窗口的测试代码编写在上部分已经实现)

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

回顾  在之前我们介绍了如何用VS2010的UI测试功能创建一个简单的示例,大致描述了如何使用编码的UI测试进行录制和回放,在这章会着重描述VS2010是如何录制操作,并且生成代码,以及初步介绍如何通过自己写代码的方式进行测试. 内容简介  在上一章我们已经介绍过,建立一个编码的UI测试CodedUITest1.cs,录制完成之后,会自动生成一个UIMap1.uitest文件.  图1:录制完成后自动生成的UIMap1.uitest文件  事实上,在录制过程中起着关键作用的并非是CodedUIT

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

回顾 在之前的入门篇系列中,分别介绍了一个简单的示例, 操作动作的录制原理,通过修改UIMap.UItest文件控制操作动作代码的生成,对象的识别原理.接下来正式进入我们UI测试的进阶篇,在这一章,将讲述如何初步通过自己编写代码的方式来建立UI测试. 示例程序 一个系统的基本功能是增,删,改,查,其中增和改界面基本一样,删就几乎是一个按钮的事,所以我做了一个程序示例(下载点我),拥有增和查两个功能,之后的操作都将会在这个示例之上进行: 系统主窗口: 该系统拥有两个功能,"添加用户"和&