VS2010测试功能之旅
——编码的UI测试系列之二:操作动作的录制原理(下)
RealZhao,2011年2月23日
回顾
在本章上部分介绍了操作动作的录制原理,描述了操作动作是如何录制,UIMap.uitest和UIMap.Designer.cs的代码如何生成,以及他们的结构。在这个部分,将着重说明如何通过修改UIMap1.uitest文件的操作动作部分的代码来控制UIMap1.Designer.cs操作动作部分代码的生成,实现第一种方式的自定义编码。
内容简介
在上个部分,已经说明了UIMap.uitest文件的结构如下
![](https://i-blog.csdnimg.cn/blog_migrate/5056181d6b446f1b5514d7508567a551.png)
其中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文件,可以发现代码如下
2
3 < 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" >
4
5 </ UITest >
6
7
3. 关闭录制生成器(注:一定要先关闭才能修改,以后也是一样),编码初始化代码InitializeActions
假设现在如果要操作它,首先需要将其打开,在之前已经简单介绍过编码的UI测试支持的Action,可以把打开这个程序的操作作为InitializeActions(初始化操作)的一员,并为其生成一个方法,那么按照这个思路,在参照前面的Actions列表,可以发现需要两个Action
a. LaunchApplicationAction 打开应用程序
b. TestStepMarkerAction 为该步骤生成一个方法
现在我们开始编写代码,将其直接插入UITest节点内
2
3 <! —打开示例文件,文件路径按实际情况填写-- >
4
5 < LaunchApplicationAction >
6
7 < FileName > D:\RightDemo.exe </ FileName >
8
9 </ LaunchApplicationAction >
10
11
12
13 <!-- 为之前所有的操作步骤生成¦一个方法,名称为LaunchApplication() -->
14
15 < TestStepMarkerAction MarkerInformation ="LaunchApplication" >
16
17 < ParameterName />
18
19 < StepId > -1 </ StepId >
20
21 < Direction > Start </ Direction >
22
23 < Outcome />
24
25 < Disabled > false </ Disabled >
26
27 </ TestStepMarkerAction >
28
29 </ InitializeActions >
30
31
编写之后,我们打开录制生成器,点击“生成代码”,可以发现在UIMap1.Designer.cs对应生成了几句代码,其中已经按照要求生成了LaunchApplication()方法和加载应用程序的语句ApplicationUnderTest.Launch(this.LaunchApplicationParams.ExePath, this.LaunchApplicationParams.AlternateExePath),语句如下
2 /// LaunchApplication - Use 'LaunchApplicationParams' to pass parameters into this method.
3 /// </summary>
4 public void LaunchApplication()
5 {
6
7 // Launch 'D:\RightDemo.exe'
8 ApplicationUnderTest rightDemoApplication = ApplicationUnderTest.Launch( this .LaunchApplicationParams.ExePath, this .LaunchApplicationParams.AlternateExePath);
9 }
4. 编码执行代码ExecuteActions
添加了初始化的InitializeActions,之后,我们需要给他添加ExecuteActions,用于执行界面上的操作,在编写操作之前,假设我们需要输入正确的用户名(Admin)和正确的密码(123456),然后点击登陆,检测是否弹出“登陆成功”的对话框。那么进行操作前,首先需要的是先捕获用户名文本框,密码文本框,登录按钮,弹出框文本这4个对象,之后再对这4个对象进行操作
添加对象的方法如下:
首先,打开录制生成器,点上面的准星
![](https://i-blog.csdnimg.cn/blog_migrate/a7ba14fefbc8be89c20c4ad7b600b6ae.png)
之后,一直按住鼠标左键不放,将鼠标拖到用户名文本框,再松开
![](https://i-blog.csdnimg.cn/blog_migrate/1ba76d0559338b15adb6546b48393807.png)
然后,我们可以看到对象库已经自动打开,其中UITbx_uidEdit就是被我们捕获的用户名文本框,
![](https://i-blog.csdnimg.cn/blog_migrate/a577ee20f0a24d77efe99637b1db4e3b.png)
这个时候我们点击 ,之后对象就被添加到对象库了,接下来按照同样的方法,依次将密码文本框,登录按钮,弹出框文本分别加入对象库,如图:
![](https://i-blog.csdnimg.cn/blog_migrate/66962ded28b5de6952ce67d30613b826.png)
之后点击“生成代码”,然后关闭录制生成器,可以看到在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属性,该属性表示被操作的对象是谁,也就是刚才捕获到对象库里面的对象名称)
2 <!-- UIObjectName表示被操作的对象是谁 -->
3 < SetValueAction UIObjectName ="UIMap1.UI系统登录Window.UITbx_uidWindow.UITbx_uidEdit" >
4 < Value Encoded ="false" > Admin </ Value >
5 </ SetValueAction >
6 < SetValueAction UIObjectName ="UIMap1.UI系统登录Window.UITbx_pwdWindow.UITbx_pwdEdit" >
7 < Value Encoded ="false" > 123456 </ Value >
8 </ SetValueAction >
9 < MouseAction UIObjectName ="UIMap1.UI系统登录Window.UI登录Window.UI登录Button" >
10 < Location X ="1" Y ="1" />
11 < WheelDirection > 0 </ WheelDirection >
12 < ActionType > Click </ ActionType >
13 < MouseButton > Left </ MouseButton >
14 </ MouseAction >
15 < TestStepMarkerAction MarkerInformation ="InputRightUidPwd" >
16 < StepId > -1 </ StepId >
17 < Direction > Start </ Direction >
18 < Outcome />
19 < Disabled > false </ Disabled >
20 </ TestStepMarkerAction >
21 < AssertAction UIObjectName ="UIMap.UI提示Window.UI登陆成功Window.UI登陆成功Text" >
22 < PropertyName > Exists </ PropertyName >
23 < ExpectedValue > True </ ExpectedValue >
24 < Type > Boolean </ Type >
25 < PropertyCondition > AreEqual </ PropertyCondition >
26 </ AssertAction >
27 < TestStepMarkerAction MarkerInformation ="AssertRightWindow" >
28 < ParameterName />
29 < StepId > -1 </ StepId >
30 < Direction > Start </ Direction >
31 < Outcome />
32 < Disabled > false </ Disabled >
33 </ TestStepMarkerAction >
34 </ ExecuteActions >
编写完毕之后,打开录制生成器,点击生成代码,之后关闭录制生成器,可以看到UIMap.designer.cs文件中也生成了对应的代码
2 /// InputRightUidPwd - Use 'InputRightUidPwdParams' to pass parameters into this method.
3 /// </summary>
4 public void InputRightUidPwd()
5 {
6 #region Variable Declarations
7 WinEdit uITbx_uidEdit = this .UI系统登录Window.UITbx_uidWindow.UITbx_uidEdit;
8 WinEdit uITbx_pwdEdit = this .UI系统登录Window.UITbx_pwdWindow.UITbx_pwdEdit;
9 WinButton uI登录Button = this .UI系统登录Window.UI登录Window.UI登录Button;
10 #endregion
11
12 // Type 'Admin' in 'Tbx_uid' text box
13 uITbx_uidEdit.Text = this .InputRightUidPwdParams.UITbx_uidEditText;
14
15 // Type '123456' in 'Tbx_pwd' text box
16 uITbx_pwdEdit.Text = this .InputRightUidPwdParams.UITbx_pwdEditText;
17
18 // Click '登录' button
19 Mouse.Click(uI登录Button, new Point( 41 , 14 ));
20 }
21
22 /// <summary>
23 /// AssertRightWindow - Use 'AssertRightWindowExpectedValues' to pass parameters into this method.
24 /// </summary>
25 public void AssertRightWindow()
26 {
27 #region Variable Declarations
28 WinText uI登陆成功Text = this .UI提示Window.UI登陆成功Window.UI登陆成功Text;
29 #endregion
30
31 // Verify that '登陆成功!' label's property 'Exists' equals 'True'
32 Assert.AreEqual( this .AssertRightWindowExpectedValues.UI登陆成功TextExists, uI登陆成功Text.Exists);
33 }
5. 编码清理代码CleanupActions
清理代码仅仅执行两个操作,第一是点击弹出框,第二是关闭程序,然后则为其生成方法,执行操作前,首先需要捕获弹出框按钮对象,以及主窗体关闭按钮对象
![](https://i-blog.csdnimg.cn/blog_migrate/e44311f9758fc49aede27a1c06a75694.png)
然后用之前提到的方法将他们添加进对象库,然后生成代码,关闭录制生成器
![](https://i-blog.csdnimg.cn/blog_migrate/072d4a44374e8172ba758e7c99c65859.png)
按照思路编写3个action
a.MouseAction 鼠标点击确定按钮
b. MouseAction 鼠标点击关闭按钮
c.TestStepMarkerAction 生成方法ClearUpTest()
代码如下
2 < MouseAction UIObjectName ="UIMap1.UI提示Window.UIOKWindow.UIOKButton" >
3 < Location X ="1" Y ="1" />
4 < WheelDirection > 0 </ WheelDirection >
5 < ActionType > Click </ ActionType >
6 < MouseButton > Left </ MouseButton >
7 </ MouseAction >
8 < MouseAction UIObjectName ="UIMap1.UI系统登录Window.UI系统登录TitleBar.UICloseButton" >
9 < ParameterName />
10 < Location X ="1" Y ="1" />
11 < WheelDirection > 0 </ WheelDirection >
12 < ActionType > Click </ ActionType >
13 < MouseButton > Left </ MouseButton >
14 </ MouseAction >
15 < TestStepMarkerAction MarkerInformation ="ClearUpTest" >
16 < ParameterName />
17 < StepId > -1 </ StepId >
18 < Direction > Start </ Direction >
19 < Outcome />
20 < Disabled > false </ Disabled >
21 </ TestStepMarkerAction >
22 </ CleanupActions >
编写完代码之后,打开录制生成器,点击“生成代码”,可以看到UIMap1.Designer.cs文件也生成了相应的代码
2 /// ClearUpTest
3 /// </summary>
4 public void ClearUpTest()
5 {
6 #region Variable Declarations
7 WinButton uIOKButton = this .UI提示Window.UIOKWindow.UIOKButton;
8 WinButton uICloseButton = this .UI系统登录Window.UI系统登录TitleBar.UICloseButton;
9 #endregion
10
11 // Click 'OK' button
12 Mouse.Click(uIOKButton, new Point( 1 , 1 ));
13
14 // Click 'Close' button
15 Mouse.Click(uICloseButton, new Point( 1 , 1 ));
16 }
6.现在,我们就可以开始执行我们刚才编写的测试了,建立一个CodedUITest.cs文件,然后编写如下代码即可(注意这3个方法的标签,分别是TestInitialize,TestMethod,TestCleanup),之后便可以进行测试了
2 public class CodedUITest1
3 {
4
5 UIMap1 UIMapTest{ get ; set ;}
6
7 public CodedUITest1()
8 {
9 UIMapTest = new UIMap1(); // 这个UIMap1我们刚编写了操作
10 }
11
12 [TestInitialize] // 注意这里是TestInitialize标签
13 public void CodedUITestMethod1()
14 {
15 UIMapTest.LaunchApplication();
16 }
17
18 [TestMethod]//这里是Method标签
19 public void CodedUITestMethod2()
20 {
21 UIMapTest.InputRightUidPwd();
22 UIMapTest.AssertRightWindow();
23 }
24
25 [TestCleanup] // 这里是TestCleanup标签
26 public void CodedUITestMethod3()
27 {
28 UIMapTest.ClearUpTest();
29 }
30
31
32 public TestContext TestContext
33 {
34 get
35 {
36 return testContextInstance;
37 }
38 set
39 {
40 testContextInstance = value;
41 }
42 }
43 private TestContext testContextInstance;
44 }
总结
本章主要介绍了操作动作的录制原理,操作动作代码的生成,以及如何通过修改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不会被覆盖
附:发布计划
编码的UI测试系列之一:入门篇 一个简单的示例(Released)
编码的UI测试系列之二:入门篇 操作动作的录制原理(上)(Released)
编码的UI测试系列之二:入门篇 操作动作的录制原理(下)(Released)
编码的UI测试系列之三:入门篇 操作对象的识别原理 (Released)
编码的UI测试系列之四:进阶篇 通过编写测试代码的方式建立UI测试(上)(Released)
编码的UI测试系列之四:进阶篇 通过编写测试代码的方式建立UI测试(下)(Released)
编码的UI测试系列之五:进阶篇 常用测试要点和函数(1)
编码的UI测试系列之六:进阶篇 常用测试要点和函数(2)
编码的UI测试系列之七:进阶篇 UI测试之间的互相引用和测试组织
编码的UI测试系列之八:高级篇 远程调用其他机器进行测试
编码的UI测试系列之九:高级篇 使用MS测试管理器组织测试