Visual Studio 2010操作對象的識別原理
在UI操作中,操作動作總是離不開具體的操作對象,例如點(diǎn)擊,拖動,填寫值等操作,總是要對文本框,或者按鈕,窗體這些對象進(jìn)行操作,不是憑空生成的。本章作為入門篇的***一章,將會說明編碼的UI測試是如何識別這些對象的,并介紹UIMap.UItest文件是如何生成對象識別代碼。
對象的識別原理
之前我們錄制的時(shí)候,錄制生成器解析了我們的操作對象,并且為我們生成了對象識別代碼(也就是UIMap.UItest下<Map>節(jié)點(diǎn)的那部分),以便我們在回放的時(shí)候,能夠識別到我們要操作的是哪一個(gè)對象
在編碼的UI測試中,對象的識別主要是同時(shí)按以下三個(gè)方面進(jìn)行
1. 按對象類別:對象屬于什么類別,例如是button還是textBox
2. 按關(guān)鍵標(biāo)識屬性:能唯一識別該對象的屬性
3. 按層級關(guān)系:對象在其父對象中的層次
下面開始進(jìn)行詳細(xì)介紹:
一.按對象類別:
為便于理解,以web程序?yàn)槔?,假設(shè)我們的識別代碼中,寫明讓VS2010按WebButton識別一個(gè)對象,那么VS2010則會在頁面源碼中只找到那些html標(biāo)簽是<input type=“submit”>的控件,如果識別代碼中描寫的是按WebLink識別對象,則VS2010只在頁面源碼中找到那些是<a>的標(biāo)簽。
二.按關(guān)鍵標(biāo)識屬性:
通過對象類別,已經(jīng)能識別出來某一類的對象,在這個(gè)基礎(chǔ)上,接下來就需要用關(guān)鍵識別屬性進(jìn)行精準(zhǔn)標(biāo)識了,我們需要找出能唯一識別該對象的屬性,假如一個(gè)窗體如下
這個(gè)窗體中包含了3個(gè)button,我們想讓VS2010操作到***個(gè)Button,如何區(qū)分這些Button呢?這就要用到關(guān)鍵標(biāo)識屬性來標(biāo)識唯一一個(gè)對象
關(guān)鍵標(biāo)識屬性分為兩種----自身標(biāo)識屬性和輔助標(biāo)識屬性。
1.自身標(biāo)識屬性:
也就是屬于對象的屬性,例如,button擁有Name,Text,Enable,BackColor等屬性,我們假設(shè)上面那個(gè)窗體的Button的各個(gè)屬性如下
很明顯可以發(fā)現(xiàn),***個(gè)button的Name屬性和和其他的button不一樣,那么可以用其作為他的關(guān)鍵標(biāo)識屬性,并且寫在識別代碼中,這樣vs2010就可以在這些button中能唯一識別他,例如,將Name=button2寫到識別代碼中,就可以唯一識別第二個(gè)Button
假設(shè)3個(gè)button的Name一樣,而BackColor不同,也可以用BackColor作為關(guān)鍵標(biāo)識屬性。
2.輔助標(biāo)識屬性:
在自動化測試中,還有一種屬性叫做輔助標(biāo)識屬性,他并不屬于對象的屬性,但可以輔助標(biāo)識對象
假設(shè)剛才那個(gè)窗體的各button屬性如下:
可以發(fā)現(xiàn)他們的自身屬性都是一模一樣的,那么怎么做才能讓VS2010識別他呢?仔細(xì)觀察可以發(fā)現(xiàn)這樣一個(gè)情況
我們可以通過該對象是第幾個(gè)對象這樣的輔助屬性進(jìn)行標(biāo)識他
比如如果要識別第3個(gè)Button,則需要在識別代碼中設(shè)置其輔助標(biāo)識屬性“對象序號”為3
三.按層級關(guān)系:
雖然上面確定了唯一對象,的確已經(jīng)可以標(biāo)識出對象了,不過實(shí)際上在識別的時(shí)候還會按層級關(guān)系查找,例如***章提到的一個(gè)簡單的窗體
我們用錄制生成器解析他的***個(gè)文本框Tbx_uid,在自動生成的識別代碼中,他們的層級關(guān)系是這樣的
對應(yīng)到剛才的Form,層級為:
VS2010在識別這個(gè)Textbox1的時(shí)候,會只識別屬于 系統(tǒng)登錄Window下的Tbx_uidWindow下的Tbx_uid文本框
(注:按照常規(guī)的理解,其實(shí)應(yīng)該“系統(tǒng)登錄窗體”和“Tbx_uid文本框”只有兩個(gè)層級,也就是窗體下直接就是文本框,但是VS2010默認(rèn)解析的時(shí)候,會把一個(gè)TextBox解析成兩個(gè)層級,分為TextBoxWindow和TextBoxEdit,結(jié)果本來應(yīng)該總共只有兩級結(jié)果搞成了三級,如果仔細(xì)觀察可以發(fā)現(xiàn)其他控件也是這樣的,所以在這里糾結(jié)的朋友希望你們看到此段后能夠減輕些疑惑...)
UIMap.UItest文件控制識別代碼的生成
在第二章上部分已經(jīng)提到,在UIMap.uitest文件中,對象的識別代碼的生成部分是放在<Maps>節(jié)點(diǎn)下的,點(diǎn)擊生成代碼后,會將其真正起作用的識別代碼生成到UIMap.designer.cs下,那么他們的代碼究竟是怎樣的呢?
以剛才那個(gè)窗體生成的代碼為例,我們要識別TextBox1,如果使用錄制生成器,把TextBox1填入到對象庫,我們來看看他生成的識別代碼(可以簡略看,下面會有說明)
別看UIMap.uitest里為這些對象生成的了一大堆代碼,其實(shí)對象中真正管作用的屬性就ControlType,ID兩個(gè):
而管作用的節(jié)點(diǎn)也就這么兩個(gè):
<AndCondition>這個(gè)節(jié)點(diǎn)表示識別條件,他的子節(jié)點(diǎn)為<PropertyCondition>,表示具體識別條件,識別原理之二的關(guān)鍵標(biāo)識屬性就用這個(gè)表示
<Descendants>這個(gè)節(jié)點(diǎn)用于存放這個(gè)對象的子對象,識別原理之三的層級關(guān)系就是用這個(gè)表示
現(xiàn)在把上面自動生成的代碼優(yōu)化一下,把不必要的代碼刪除,并加上注釋。然后再使用這段XML代碼在錄制生成器生成UIMap.designer.cs代碼
- <Maps>
- <UIMap Id="UIMap1">
- <TopLevelWindows>
- <!--表示***級別的窗體,屬性ControlType表示按類型“Window”類型識別對象,對應(yīng)識別原理之一-->
- <TopLevelWindow ControlType="Window" Id="UI系統(tǒng)登錄Window">
- <!--TechnologyName標(biāo)簽沒有實(shí)際作用,但是刪除了會報(bào)錯(cuò),因此保留,之后的也是-->
- <TechnologyName>MSAA</TechnologyName>
- <AndCondition Id="SearchCondition">
- <!--表示窗體的關(guān)鍵標(biāo)識屬性,識別的時(shí)候?qū)ふ襈ame屬性為“系統(tǒng)登錄”的窗體,對應(yīng)識別原理之二-->
- <PropertyCondition Name="Name">系統(tǒng)登錄</PropertyCondition>
- <!--表示窗體的關(guān)鍵標(biāo)識屬性,識別的時(shí)候?qū)ふ褻lassName屬性為“WindowsForms10.Window”的窗體-->
- <PropertyCondition Name="ClassName" Operator="Contains">WindowsForms10.Window</PropertyCondition>
- </AndCondition>
- <!--表示窗體的子對象,對應(yīng)識別原理之三-->
- <Descendants>
- <!--UI對象,按類型“Window”類型識別-->
- <UIObject ControlType="Window" Id="UITbx_uidWindow">
- <TechnologyName>MSAA</TechnologyName>
- <AndCondition Id="SearchCondition">
- <!--關(guān)鍵標(biāo)識屬性,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">
- <!--關(guān)鍵標(biāo)識屬性,Name屬性為“密碼?。?rdquo;-->
- <PropertyCondition Name="Name">密碼?。?/span></PropertyCondition>
- </AndCondition>
- <Descendants />
- </UIObject>
- </Descendants>
- </UIObject>
- </Descendants>
- </TopLevelWindow>
- </TopLevelWindows>
- </UIMap>
- /Maps>
接下來使用錄制生成器生成UIMap.designer.cs代碼,可以看到代碼如下
- [GeneratedCode("編碼的 UI 測試生成器", "10.0.30319.1")]
- public class UI系統(tǒng)登錄Window : WinWindow
- //這里的繼承于WinWindow,是根據(jù)剛才XML文件里的屬性ControlType="Window"生成的,表示按Window識別,對應(yīng)識別原理之一
- {
- public UI系統(tǒng)登錄Window()
- {
- //這里是搜索條件,也就是關(guān)鍵識別屬性,根據(jù)XML文件的AndCondition節(jié)點(diǎn)中的內(nèi)容生成,對應(yīng)識別原理之二
- #region 搜索條件
- this.SearchProperties[WinWindow.PropertyNames.Name] = "系統(tǒng)登錄";
- this.SearchProperties.Add(new PropertyExpression(WinWindow.PropertyNames.ClassName, "WindowsForms10.Window", PropertyExpressionOperator.Contains));
- #endregion
- }
- //這里是他的子對象,對應(yīng)于XML文件的Descendants節(jié)點(diǎn),對應(yīng)識別原理之三
- #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,是根據(jù)剛才XML文件里的屬性ControlType="Window"生成的,表示按Window識別
- public UITbx_uidWindow(UITestControl searchLimitContainer) :
- base(searchLimitContainer)
- {
- //這里是搜索條件,也就是關(guān)鍵識別屬性,根據(jù)XML文件的AndCondition節(jié)點(diǎn)中的內(nèi)容生成
- #region 搜索條件
- this.SearchProperties[WinWindow.PropertyNames.ControlName] = "Tbx_uid";
- #endregion
- }
- //這里是他的子對象,對應(yīng)于XML文件的Descendants節(jié)點(diǎn)
- #region Properties
- public WinEdit UITbx_uidEdit
- //這里的類型為WinEdit,是根據(jù)剛才XML文件里的屬性ControlType生成的(ControlType="Edit")
- {
- get
- {
- if ((this.mUITbx_uidEdit == null))
- {
- this.mUITbx_uidEdit = new WinEdit(this);
- //這里是搜索條件,也就是關(guān)鍵識別屬性,根據(jù)XML文件的AndCondition節(jié)點(diǎn)中的內(nèi)容生成
- #region 搜索條件
- this.mUITbx_uidEdit.SearchProperties[WinEdit.PropertyNames.Name] = "密碼 :";
- #endregion
- }
- return this.mUITbx_uidEdit;
- }
- }
- #endregion
- #region Fields
- private WinEdit mUITbx_uidEdit;
- #endregion
- }
總結(jié)
在本章介紹了VS2010的對象識別原理,想必大家對這個(gè)應(yīng)該有所了解了吧?
我曾今在用UI測試做項(xiàng)目的時(shí)候,經(jīng)常會發(fā)現(xiàn)這樣那樣的對象不能用錄制生成器識別,這個(gè)時(shí)候怎么辦呢?了解了對象識別原理,就可以自己改XML文件來控制對象的識別,如果有想做這方面練習(xí)的朋友,可以留下你的郵箱,我這里正在編寫一個(gè)C# Winform小程序,這個(gè)程序上的所有控件都經(jīng)過特殊處理,無法用錄制生成器識別,只有通過自己修改XML文件來控制它的識別,如果想試試自己的身手,別忘了留下郵箱哦~~
到這里編碼的UI測試的入門篇就完結(jié)了,接下來會進(jìn)入進(jìn)階篇,以實(shí)際的例子描述如何對一個(gè)項(xiàng)目進(jìn)行測試
附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 客戶端應(yīng)用程序 | 不支持 |
Dynamics (Ax) | 部分支持 |
SAP | 不支持 |
Citrix/終端服務(wù) | 部分支持 |
注:Silverlight4 現(xiàn)在已支持,詳情見http://www.silverlightshow.net/news/Coded-UI-testing-for-Silverlight-4-now-available-.aspx,
原文鏈接:http://www.cnblogs.com/realdigit/archive/2011/03/02/1968454.html
【編輯推薦】