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

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

  回顾 

  在之前的两章分别介绍了一个简单的示例操作动作的录制原理通过修改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
}
目录
相关文章
|
29天前
|
安全 测试技术
现代软件测试中的自动化技术应用及挑战
在当今数字化时代,软件测试的重要性日益凸显。本文探讨了现代软件测试中自动化技术的应用现状和挑战,分析了自动化测试在提高效率、降低成本、增强可靠性等方面的优势,同时也提出了自动化测试所面临的挑战和解决方案。
|
29天前
|
人工智能 测试技术 虚拟化
现代软件测试中的自动化工具与技术
随着信息技术的迅猛发展,现代软件开发和测试领域也在不断创新。本文将探讨现代软件测试中自动化工具与技术的应用。通过分析自动化测试的优势、挑战以及最佳实践,帮助读者更好地理解当前软件测试领域的发展趋势,并为实际工作提供参考。
16 1
|
30天前
|
敏捷开发 供应链 测试技术
深入理解与应用软件测试中的Mock技术
【2月更文挑战第30天】 在现代软件开发过程中,单元测试是保证代码质量的重要手段。然而,对于高度依赖外部系统或服务的应用来说,传统的单元测试方法往往难以实施。Mock技术应运而生,它通过模拟外部依赖的响应,使开发者可以在隔离的环境中测试目标代码。本文将探讨Mock技术的概念、应用场景以及如何在软件测试中有效地使用Mock对象,以增强测试的灵活性和可靠性。
|
1月前
|
SQL 消息中间件 Kafka
Apache Hudi测试、运维操作万字总结
Apache Hudi测试、运维操作万字总结
72 1
|
2月前
|
调度
【技术探讨】无线通信模块拉距测试,是否一定要带笔记本电脑?
对于Sub-G的无线模块通常通信距离较远可以达到公里级甚至数公里之远,而笔记本的续航时间通常是2-3个小时,很多用户测试到一半,不得不提前终止测试,回去给笔记本电脑充电
|
2月前
|
人工智能 测试技术 API
你知道哪些新兴的测试技术?
你知道哪些新兴的测试技术?
|
1月前
|
前端开发 搜索推荐 开发者
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
27 0
|
1月前
|
JavaScript 前端开发 开发者
SAP UI5 控件 sap.m.ListBase 的 inset 属性的作用介绍
SAP UI5 控件 sap.m.ListBase 的 inset 属性的作用介绍
15 0
|
1月前
|
前端开发 JavaScript API
SAP UI5 sap.ui.require.toUrl 的作用介绍
SAP UI5 sap.ui.require.toUrl 的作用介绍
28 0
|
1月前
|
JSON 前端开发 测试技术
SAP UI5 sap.ui.core.util.MockServer.simulate 方法介绍
SAP UI5 sap.ui.core.util.MockServer.simulate 方法介绍
21 0