VS2010測試功能之旅:編碼的UI測試(2)-操作動作的錄制原理(下)
回顧
在本章上部分介紹了操作動作的錄制原理,描述了操作動作是如何錄制,UIMap.uitest和UIMap.Designer.cs的代碼如何生成,以及他們的結構。在這個部分,將著重說明如何通過修改UIMap1.uitest文件的操作動作部分的代碼來控制UIMap1.Designer.cs操作動作部分代碼的生成,實現第一種方式的自定義編碼。
內容簡介
在上個部分,已經說明了UIMap.uitest文件的結構如下:

其中InitializeActions,ExecuteActions,CleanupActions,OnErrorAction都是對于操作動作的描述:
InitializeActions:指初始化需要執行的操作動作
ExecuteActions:指測試過程中的操作動作(通過錄制所生成的操作都默認放在ExecuteActions)
CleanupActions:指測試完畢需要清理資源的操作動作
OnErrorAction:指代異常處理的操作動作
他們都對UIMap1.Designer.cs操作動作部分代碼的生成和參數的生成有直接的影響。
嚴格的說,放在InitializeActions下的操作動作和放在ExecuteActions,CleanupActions,OnErrorAction的動作沒有任何本質上的區別,僅僅只是從一個代碼可讀性上的考慮。
編碼的UI測試所支持的Actions
如果我們仔細觀察過ExecuteActions錄制所生成的代碼,可以發現有一個共同特點,ExecuteActions的子節點都是以<Action>結尾形式的標簽,那么編碼的UI測試一共支持多少種的Action呢?這里我整理了一個列表,簡單的介紹了測試所支持的Action和功能簡介。
類 |
說明 |
為可以完成幾種任務中任何一種的所有操作提供基類。 |
|
表示要包含在測試中其他兩個操作之間的斷言。 |
|
表示可以完成幾種瀏覽器任務中的任何一種的測試操作。 |
|
指定執行用戶界面 (UI) 測試中的后續操作后的時間延遲。 |
|
表示鼠標拖動操作。 |
|
表示鼠標拖放操作。 |
|
表示一個操作,測試記錄器使用該操作報告它無法記錄某一操作。 |
|
表示所有基于文本的操作的基類。 |
|
表示單個的鍵盤用戶操作。 |
|
表示啟動一個應用程序的 UI 測試操作。 |
|
提供一種在操作序列中插入標記而不會在播放過程中導致任何操作的方法。 |
|
表示關于鼠標操作的信息。 |
|
表示移動到某一 URL 的操作。 |
|
表示不執行任何操作的用戶界面 (UI) 測試操作。 |
|
提供有關聚合測試操作聲明,從測試結果中移除此操作及之前的所有匹配鍵操作。 |
|
表示發送文本或鍵數組的測試操作。 |
|
為設置值或設置狀態的測試操作提供基類。 |
|
表示一個設置關聯元素狀態的測試操作。 |
|
表示用于設置值的測試操作。 |
|
為當前測試提供對一組共享步驟的引用。 |
|
表示一個字符串斷言。 |
|
表示測試操作序列中的一個標記,將記錄該標記,但播放框架不使用該標記。 |
|
為用于用戶界面 (UI) 測試的測試操作提供基類。 |
|
表示一個驗證屬性值的操作。 |
|
表示一個驗證配置的操作。 |
|
表示一個操作,UI 記錄器使用該操作報告它無法正確錄制某一操作。 |
|
表示一個報告 Web 對話框的操作。 |
在這里將抽取幾個主要的ACTION進行介紹。
通過編寫UIMap.uitest文件控制UIMap.designer.cs代碼的生成。
1.首先我們還是通過添加新項的方式建立一個新的Coded UI Test Map(編碼的UI測試映射)。
2.之后,直接進入UIMap1.uitest文件,可以發現代碼如下:
<UITest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="" Id="3efe829a-76df-439e-af0d-8d5c62727a1e" AssemblyVersion="10.0.21008.0" Version="1.0" xmlns="http://schemas.microsoft.com/VisualStudio/TeamTest/UITest/2010">
</UITest>
3. 關閉錄制生成器(注:一定要先關閉才能修改,以后也是一樣),編碼初始化代碼InitializeActions。
假設現在如果要操作它,首先需要將其打開,在之前已經簡單介紹過編碼的UI測試支持的Action,可以把打開這個程序的操作作為InitializeActions(初始化操作)的一員,并為其生成一個方法,那么按照這個思路,在參照前面的Actions列表,可以發現需要兩個Action:
a、LaunchApplicationAction 打開應用程序。
b、TestStepMarkerAction 為該步驟生成一個方法。
現在我們開始編寫代碼,將其直接插入UITest節點內:
<!— 打開示例文件,文件路徑按實際情況填寫-->
<LaunchApplicationAction>
<FileName>D:\RightDemo.exe</FileName>
</LaunchApplicationAction>
<!--為之前所有的操作步驟生成|一個方法,名稱為LaunchApplication()-->
<TestStepMarkerAction MarkerInformation="LaunchApplication">
<ParameterName />
<StepId>-1</StepId>
<Direction>Start</Direction>
<Outcome/>
<Disabled>false</Disabled>
</TestStepMarkerAction>
</InitializeActions>
編寫之后,我們打開錄制生成器,點擊“生成代碼”,可以發現在UIMap1.Designer.cs對應生成了幾句代碼,其中已經按照要求生成了LaunchApplication()方法和加載應用程序的語句ApplicationUnderTest.Launch(this.LaunchApplicationParams.ExePath, this.LaunchApplicationParams.AlternateExePath),語句如下:
/// LaunchApplication - Use 'LaunchApplicationParams' to pass parameters into this method.
/// </summary>
public void LaunchApplication()
{
// Launch 'D:\RightDemo.exe'
ApplicationUnderTest rightDemoApplication = ApplicationUnderTest.Launch(this.LaunchApplicationParams.ExePath, this.LaunchApplicationParams.AlternateExePath);
}
4. 編碼執行代碼ExecuteActions
添加了初始化的InitializeActions,之后,我們需要給他添加ExecuteActions,用于執行界面上的操作,在編寫操作之前,假設我們需要輸入正確的用戶名(Admin)和正確的密碼(123456),然后點擊登陸,檢測是否彈出“登陸成功”的對話框。那么進行操作前,首先需要的是先捕獲用戶名文本框,密碼文本框,登錄按鈕,彈出框文本這4個對象,之后再對這4個對象進行操作。
添加對象的方法如下:
首先,打開錄制生成器,點上面的準星:

之后,一直按住鼠標左鍵不放,將鼠標拖到用戶名文本框,再松開:

然后,我們可以看到對象庫已經自動打開,其中UITbx_uidEdit就是被我們捕獲的用戶名文本框:

這個時候我們點擊 ,之后對象就被添加到對象庫了,接下來按照同樣的方法,依次將密碼文本框,登錄按鈕,彈出框文本分別加入對象庫,如圖:

之后點擊“生成代碼”,然后關閉錄制生成器,可以看到在UIMap.uitest的<Maps>節點已經生成了相關的對象,而在UIMap.designer.cs的對象映射部分也添加了相應的代碼(具體對象識別原理會在第三章提到,這里只先使用對象進行操作)。
對象添加進入對象庫了,現在只需要編寫操作了。
我們需要輸入正確的用戶名(Admin)和正確的密碼(123456),然后點擊登陸,檢測是否彈出“登陸成功”的對話框,并生成兩個方法,InputRightUidPwd()用于輸入用戶名和密碼,AssertRightWindow()用于驗證是否彈出相應的彈出框文本,那么需要依次用到如下Action:
a.SetValueAction 設置用戶名文本框的值
b.SetValueAction設置密碼文本框的值
c.MouseAction 鼠標點擊登陸按鈕
d.TestStepMarkerAction 生成方法InputRightUidPwd()
e.AssertAction 為判斷是否彈出生成斷言
f. TestStepMarkerAction 生成方法AssertRightWindow()
按照這個思路,我們開始編寫如下代碼:
(這里可以看到某些操作都帶有UIObjectName屬性,該屬性表示被操作的對象是誰,也就是剛才捕獲到對象庫里面的對象名稱)
<!--UIObjectName表示被操作的對象是誰-->
<SetValueAction UIObjectName="UIMap1.UI 系統登錄Window.UITbx_uidWindow.UITbx_uidEdit">
<Value Encoded="false">Admin</Value>
</SetValueAction>
<SetValueAction UIObjectName="UIMap1.UI 系統登錄Window.UITbx_pwdWindow.UITbx_pwdEdit">
<Value Encoded="false">123456</Value>
</SetValueAction>
<MouseAction UIObjectName="UIMap1.UI 系統登錄Window.UI登錄Window.UI登錄Button">
<Location X="1" Y="1" />
<WheelDirection>0</WheelDirection>
<ActionType>Click</ActionType>
<MouseButton>Left</MouseButton>
</MouseAction>
<TestStepMarkerAction MarkerInformation="InputRightUidPwd">
<StepId>-1</StepId>
<Direction>Start</Direction>
<Outcome />
<Disabled>false</Disabled>
</TestStepMarkerAction>
<AssertAction UIObjectName="UIMap.UI 提示Window.UI登陸成功Window.UI登陸成功Text">
<PropertyName>Exists</PropertyName>
<ExpectedValue>True</ExpectedValue>
<Type>Boolean</Type>
<PropertyCondition>AreEqual</PropertyCondition>
</AssertAction>
<TestStepMarkerAction MarkerInformation="AssertRightWindow">
<ParameterName />
<StepId>-1</StepId>
<Direction>Start</Direction>
<Outcome />
<Disabled>false</Disabled>
</TestStepMarkerAction>
</ExecuteActions>
編寫完畢之后,打開錄制生成器,點擊生成代碼,之后關閉錄制生成器,可以看到UIMap.designer.cs文件中也生成了對應的代碼。
/// InputRightUidPwd - Use 'InputRightUidPwdParams' to pass parameters into this method.
/// </summary>
public void InputRightUidPwd()
{
#region Variable Declarations
WinEdit uITbx_uidEdit = this.UI 系統登錄Window.UITbx_uidWindow.UITbx_uidEdit;
WinEdit uITbx_pwdEdit = this.UI 系統登錄Window.UITbx_pwdWindow.UITbx_pwdEdit;
WinButton uI 登錄Button = this.UI系統登錄Window.UI登錄Window.UI登錄Button;
#endregion
// Type 'Admin' in 'Tbx_uid' text box
uITbx_uidEdit.Text = this.InputRightUidPwdParams.UITbx_uidEditText;
// Type '123456' in 'Tbx_pwd' text box
uITbx_pwdEdit.Text = this.InputRightUidPwdParams.UITbx_pwdEditText;
// Click ' 登錄' button
Mouse.Click(uI登錄Button, new Point(41, 14));
}
/// <summary>
/// AssertRightWindow - Use 'AssertRightWindowExpectedValues' to pass parameters into this method.
/// </summary>
public void AssertRightWindow()
{
#region Variable Declarations
WinText uI 登陸成功Text = this.UI提示Window.UI登陸成功Window.UI登陸成功Text;
#endregion
// Verify that ' 登陸成功!' label's property 'Exists' equals 'True'
Assert.AreEqual(this.AssertRightWindowExpectedValues.UI 登陸成功TextExists, uI登陸成功Text.Exists);
}
5. 編碼清理代碼CleanupActions
清理代碼僅僅執行兩個操作,第一是點擊彈出框,第二是關閉程序,然后則為其生成方法,執行操作前,首先需要捕獲彈出框按鈕對象,以及主窗體關閉按鈕對象。

然后用之前提到的方法將他們添加進對象庫,然后生成代碼,關閉錄制生成器:

按照思路編寫3個action:
a.MouseAction 鼠標點擊確定按鈕
b. MouseAction 鼠標點擊關閉按鈕
c.TestStepMarkerAction 生成方法ClearUpTest()
代碼如下:
<MouseAction UIObjectName="UIMap1.UI 提示Window.UIOKWindow.UIOKButton">
<Location X="1" Y="1" />
<WheelDirection>0</WheelDirection>
<ActionType>Click</ActionType>
<MouseButton>Left</MouseButton>
</MouseAction>
<MouseAction UIObjectName="UIMap1.UI 系統登錄Window.UI系統登錄TitleBar.UICloseButton">
<ParameterName />
<Location X="1" Y="1" />
<WheelDirection>0</WheelDirection>
<ActionType>Click</ActionType>
<MouseButton>Left</MouseButton>
</MouseAction>
<TestStepMarkerAction MarkerInformation="ClearUpTest">
<ParameterName />
<StepId>-1</StepId>
<Direction>Start</Direction>
<Outcome />
<Disabled>false</Disabled>
</TestStepMarkerAction>
</CleanupActions>
編寫完代碼之后,打開錄制生成器,點擊“生成代碼”,可以看到UIMap1.Designer.cs文件也生成了相應的代碼:
/// ClearUpTest
/// </summary>
public void ClearUpTest()
{
#region Variable Declarations
WinButton uIOKButton = this.UI 提示Window.UIOKWindow.UIOKButton;
WinButton uICloseButton = this.UI 系統登錄Window.UI系統登錄TitleBar.UICloseButton;
#endregion
// Click 'OK' button
Mouse.Click(uIOKButton, new Point(1, 1));
// Click 'Close' button
Mouse.Click(uICloseButton, new Point(1, 1));
}
6.現在,我們就可以開始執行我們剛才編寫的測試了,建立一個CodedUITest.cs文件,然后編寫如下代碼即可(注意這3個方法的標簽,分別是TestInitialize,TestMethod,TestCleanup),之后便可以進行測試了。
public class CodedUITest1
{
UIMap1 UIMapTest{get;set;}
public CodedUITest1()
{
UIMapTest = new UIMap1();//這個UIMap1我們剛編寫了操作
}
[TestInitialize]//注意這里是TestInitialize標簽
public void CodedUITestMethod1()
{
UIMapTest.LaunchApplication();
}
[TestMethod]//這里是Method標簽
public void CodedUITestMethod2()
{
UIMapTest.InputRightUidPwd();
UIMapTest.AssertRightWindow();
}
[TestCleanup]//這里是TestCleanup標簽
public void CodedUITestMethod3()
{
UIMapTest.ClearUpTest();
}
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
private TestContext testContextInstance;
}
總結
本章主要介紹了操作動作的錄制原理,操作動作代碼的生成,以及如何通過修改UIMap.uitest文件控制UIMap.designer.cs代碼的生成,大家如果感興趣,可以試試使用各個Action填充UIMap.uitest,看看究竟會在UIMap.designer.cs生成怎樣的代碼。
因為UIMap.uitest一旦添加新對象或操作,點擊自動生成后,都會對UIMap.designer.cs的代碼進行一次覆蓋,如果想要編寫自定義C#代碼,最好是將其寫在UIMap.cs文件,例如,可以把在UIMap.designer.cs生成的方法粘貼到UIMap.cs,然后在UIMap.cs添加自己的驗證邏輯,因為UIMap.cs不會被覆蓋。