Introduction
UI Automation是Microsoft .NET 3.0框架下提供的一种用于自动化测试的技术,是在MSAA基础上建立的,MSAA就是Microsoft Active Accessibility。UI Automation在某些方面超过了MSAA,UI自动化提供了Windows Vista中,微软Windows XP的全部功能,和Windows Server 2003。
在UI Automation中,所有的窗体、控件都表现为一个AutomationElement, AutomationElement 中包含此控件或窗体的属性,在实现自动化的过程中,我们通过其相关属性进行对控件自动化操作。对于UI用户界面来说,所有显示在桌面上的UI,其实际是一个UI Tree,根节点是desktop。我们可以使用UI Spy或者是SPY++来获得Window和Control的相关信息。在UI Automation里,根节点表示为AutomationElemnet.RootElement. 通过根节点,我们可以通过窗体或控件的Process Id、Process Name或者Window Name找到相应的子AutomationElement,例如Dialog、Button、TextBox、Checkbox等标准控件,通过控件所对应的Pattern进行相关的操作。
UI Automation structure
如下图所示:
1. 在服务端由UIAutomationProvider.dll和UIAutomationTypes.dll提供。
2. 在客户端由UIAutomationClient.dll和UIAutomationTypes.dll提供。
3. UIAutomationCore.dll为UI自动化的核心部分,负责Server端和Client端的交互。
4. UIAUtomationClientSideProvides.dll为客户端程序提供自动化支持。
使用UI Automation实现自动化测试--2
本文通过一个实例来介绍怎样使用UI Automation实现软件的自动化测试。
1. 首先建立一个待测试的winform程序,即UI Automation的服务端。
下面是button事件处理程序。
private void button1_Click(object sender, EventArgs e)
{
int i = int.Parse(textBox1.Text);
int j = int.Parse(textBox2.Text);
textBox3.Text = (i + j).ToString();
}
2. 建立一个测试程序,做UI Automaion的客户端。
添加引用:UIAutomationClient.dll 和 UIAutomationTypes.dll
2
![](http://img.e-com-net.com/image/info8/0233617edf8a4ecbb342f0e817ba8574.gif)
3
![](http://img.e-com-net.com/image/info8/5e16a2182e284de38b90e2387161c751.gif)
4
![](http://img.e-com-net.com/image/info8/c42f039a39ae4751b8fa7c499cbc0d5b.gif)
5
![](http://img.e-com-net.com/image/info8/ba50c842f66a4eb1ae6f5ff9c475f0ad.gif)
6
![](http://img.e-com-net.com/image/info8/62adca8eb57c4a24a691238d0d8d8b90.gif)
7
![](http://img.e-com-net.com/image/info8/d7cb6506cfa84650813da5e0d9fc2cef.gif)
8
![](http://img.e-com-net.com/image/info8/e92790760eeb470ba40629cf9031e9be.gif)
9
![](http://img.e-com-net.com/image/info8/681f9a6991df4a36a11b43382eaa512f.gif)
10
![](http://img.e-com-net.com/image/info8/ca8386a922ec4f739997d64a69457fc6.gif)
11
![](http://img.e-com-net.com/image/info8/0e2d6fb60ea7401e8fe224aced2e5070.gif)
12
![](http://img.e-com-net.com/image/info8/a609ae68aa884a58be710951698216c9.gif)
13
![](http://img.e-com-net.com/image/info8/8b7b1769569f46b59139c18224b66119.gif)
14
![](http://img.e-com-net.com/image/info8/487469e7a9474cd6a407cb97f9789d88.gif)
15
![](http://img.e-com-net.com/image/info8/6e54b7df59e44cda933a79e52ad9580a.gif)
16
![](http://img.e-com-net.com/image/info8/98f848a93e704eec9b39327459b876f3.gif)
17
![](http://img.e-com-net.com/image/info8/96af72f0f88c4255ad5fe51bb59d18ec.gif)
18
![](http://img.e-com-net.com/image/info8/173cb85aab74452880873a833d071091.gif)
19
![](http://img.e-com-net.com/image/info8/258cde4be813440988bfff647c3cfe72.gif)
20
![](http://img.e-com-net.com/image/info8/fe942a21515841458002eca553d2b3a9.gif)
21
![](http://img.e-com-net.com/image/info8/76464036d7c949428acf7607cc1d0b0b.gif)
22
![](http://img.e-com-net.com/image/info8/e7e4f3b7148e4b32bd40482f0e104998.gif)
23
![](http://img.e-com-net.com/image/info8/f33c8a68cfac4362b0d10563fc55e9d6.gif)
24
![](http://img.e-com-net.com/image/info8/1b7b365af30d477d9bafda2bca52443c.gif)
25
![](http://img.e-com-net.com/image/info8/7fcb4272046946e8a922ba42deca7712.gif)
26
![](http://img.e-com-net.com/image/info8/6322ae592508454486f022c4487886b1.gif)
27
![](http://img.e-com-net.com/image/info8/9bfb0a1398fd47d8ad6816ef9f1b0844.gif)
28
![](http://img.e-com-net.com/image/info8/ed0647e78c50483c97311f894025e1ca.gif)
29
![](http://img.e-com-net.com/image/info8/3a1b78e2bf2f442b83c36108ba785ece.gif)
30
![](http://img.e-com-net.com/image/info8/107b2cc0522a4a3d946b6ac5ff4dc97f.gif)
31
![](http://img.e-com-net.com/image/info8/1341fc05c471460d8b8475dff930ef7c.gif)
32
![](http://img.e-com-net.com/image/info8/d7bbe9aca7984b41a548384d8905149c.gif)
33
![](http://img.e-com-net.com/image/info8/e15a6484718a4f5a9e0205ca88e5973e.gif)
34
![](http://img.e-com-net.com/image/info8/963535a13dbc41b49115f7e067b0b96d.gif)
35
![](http://img.e-com-net.com/image/info8/43ffb042d5414128914d5ac86da3cdb8.gif)
36
![](http://img.e-com-net.com/image/info8/3c07cc85e3104a3f963160b1e8a851de.gif)
37
![](http://img.e-com-net.com/image/info8/c26ed17d0cc64f41abd4028074a7a813.gif)
38
![](http://img.e-com-net.com/image/info8/17e853650a0f4f618857f005e2c84485.gif)
39
![](http://img.e-com-net.com/image/info8/85b1c230bd5c4cd183f83050f9e05eb8.gif)
40
![](http://img.e-com-net.com/image/info8/175c6e2244594abaafd6c193ae7f53a2.gif)
41
![](http://img.e-com-net.com/image/info8/715ef69f416742b1a689ff3132f34a63.gif)
42
![](http://img.e-com-net.com/image/info8/8aff84a2cbb54ee4bac94fea26f7c4c6.gif)
43
![](http://img.e-com-net.com/image/info8/5e4965cf24f744a1aa4c1462080e7bb7.gif)
44
![](http://img.e-com-net.com/image/info8/c701ac75a84d4b73a560dc7b60283cc5.gif)
45
![](http://img.e-com-net.com/image/info8/f086f507676e4d03996ae3ff5d6e830d.gif)
46
![](http://img.e-com-net.com/image/info8/a3e5a484fff348fd8c213f510736232c.gif)
47
![](http://img.e-com-net.com/image/info8/4641342708fc403cad48d143d1ee0a7f.gif)
48
![](http://img.e-com-net.com/image/info8/069cb606bbb245bc84e8886e8bead1c2.gif)
49
![](http://img.e-com-net.com/image/info8/2d0c1b0c5c294bf5990797ac3a1adb26.gif)
50
![](http://img.e-com-net.com/image/info8/777e8777b0d44e80b31c5a1ad897f2a5.gif)
51
![](http://img.e-com-net.com/image/info8/97d0757dd1984bb8bebd652042014f38.gif)
52
![](http://img.e-com-net.com/image/info8/cd65e8df11b6481ba199c834d4c547cb.gif)
53
![](http://img.e-com-net.com/image/info8/9f54f2e49fde485b8fbd99e7cd4b780f.gif)
54
![](http://img.e-com-net.com/image/info8/8b7d1dba39384d71b89d165eb5458ab5.gif)
55
![](http://img.e-com-net.com/image/info8/8e5cc136e8bc4027bb8cd183727e511e.gif)
56
![](http://img.e-com-net.com/image/info8/98841cd5dce74cc5a7428061b17a926f.gif)
57
![](http://img.e-com-net.com/image/info8/1b7603bf7ed34d019992c6c1dd09f841.gif)
58
![](http://img.e-com-net.com/image/info8/dcfd9212ac0d490b88b89dbaca3796ab.gif)
59
![](http://img.e-com-net.com/image/info8/7846d276b82c4985b6729e60e67825e3.gif)
60
![](http://img.e-com-net.com/image/info8/9be8721bf4f54c3eb13942f75e540b43.gif)
61
![](http://img.e-com-net.com/image/info8/9c0ecb4e8063497bb88fe9d8c4f63229.gif)
62
![](http://img.e-com-net.com/image/info8/a744db64818647bda0798a8af8988361.gif)
63
![](http://img.e-com-net.com/image/info8/f7c91890de4b4fefb4c75a990ad8edde.gif)
64
![](http://img.e-com-net.com/image/info8/d6e411f2aa4243f08adb40c084c8d52f.gif)
65
![](http://img.e-com-net.com/image/info8/000e64dfa5ac4c9eb775f9fd6f48c131.gif)
66
![](http://img.e-com-net.com/image/info8/62ee883f152043e2b7253181d806de7b.gif)
67
![](http://img.e-com-net.com/image/info8/a429d189a9f64dcabe36f91b4d567ce8.gif)
68
![](http://img.e-com-net.com/image/info8/b3330c78a24d43b38f3c7efa3fd989b1.gif)
69
![](http://img.e-com-net.com/image/info8/b812dc3bff5b4c668be2acffb5f7958e.gif)
70
![](http://img.e-com-net.com/image/info8/a5248f7751d84991b1c187e6f3d3d0a7.gif)
71
![](http://img.e-com-net.com/image/info8/4d6bc5760d924ff880cf04466dcc6d7e.gif)
72
![](http://img.e-com-net.com/image/info8/ccbc825eb6194ab2857f789051347ccb.gif)
73
![](http://img.e-com-net.com/image/info8/f8194478d6014c13ac499744115d646c.gif)
74
![](http://img.e-com-net.com/image/info8/efe7bd8d79f9484e8e6b7359829bc792.gif)
75
![](http://img.e-com-net.com/image/info8/a4e69a97c2b84486b402d09650eebb5f.gif)
76
![](http://img.e-com-net.com/image/info8/e4f93032b82e45f2b6d5aba3023013da.gif)
77
![](http://img.e-com-net.com/image/info8/98fcd672e4e7452d8c4db6d7e9f70bea.gif)
78
![](http://img.e-com-net.com/image/info8/e9ff95b34f8146e0964c7b7a1eebe71e.gif)
79
![](http://img.e-com-net.com/image/info8/466e9df6d8ca4910884c0ad21c4499a7.gif)
80
![](http://img.e-com-net.com/image/info8/ea6ce822e6ee49c8960b0c5c89951d50.gif)
81
![](http://img.e-com-net.com/image/info8/913854080ec348e2840cc94e3428b970.gif)
82
![](http://img.e-com-net.com/image/info8/221baecbcfaa4d97b07e64b3f6331a84.gif)
83
![](http://img.e-com-net.com/image/info8/215dfaa011ac410cba571b3b5f2fa074.gif)
84
![](http://img.e-com-net.com/image/info8/af5b6fceea4240a0a53820e242d9526d.gif)
85
![](http://img.e-com-net.com/image/info8/fa9556d525aa478baff7b8b40eb4be36.gif)
86
![](http://img.e-com-net.com/image/info8/b203611728f6410b9cdd7e220653afbd.gif)
87
![](http://img.e-com-net.com/image/info8/6f8e8441236c45d485ad792a159bab73.gif)
88
![](http://img.e-com-net.com/image/info8/98f08356391443cdb701a81d84cadcc4.gif)
89
![](http://img.e-com-net.com/image/info8/cfaad1da3dff4499a2822d0431ab8e59.gif)
90
![](http://img.e-com-net.com/image/info8/7be669087f4d435d8773e982fbfdff2a.gif)
91
![](http://img.e-com-net.com/image/info8/22c92b478f4846499e6ee5e9d3e1ae2b.gif)
92
![](http://img.e-com-net.com/image/info8/571414dcfdf8499ab23acf1f3cc5d371.gif)
93
![](http://img.e-com-net.com/image/info8/9aa22ec1177f4fa18d44e2c86e513f25.gif)
94
![](http://img.e-com-net.com/image/info8/b23b368d9542488086d84cc5a1513040.gif)
95
![](http://img.e-com-net.com/image/info8/57b8d3c4656e4da38806a2f3341c0696.gif)
96
![](http://img.e-com-net.com/image/info8/e892e11932ac4f0f80d7aeac282f1c32.gif)
97
![](http://img.e-com-net.com/image/info8/eea7b26b6ff24af28a9afc9f8166bed3.gif)
98
![](http://img.e-com-net.com/image/info8/9f24e3e613084648ac047599419dcdfb.gif)
99
![](http://img.e-com-net.com/image/info8/e45bde058cf244ae8bd93553e73c85c0.gif)
100
![](http://img.e-com-net.com/image/info8/83108b6143a34daab18781d0dd465a3b.gif)
101
![](http://img.e-com-net.com/image/info8/09d717a6f1b442c598d6d221b7be5ecf.gif)
102
![](http://img.e-com-net.com/image/info8/1e73aeb5bb224e5a97c54255b0f62e5e.gif)
103
![](http://img.e-com-net.com/image/info8/9cab1a09c6e14d7cbaf7576f65681359.gif)
104
![](http://img.e-com-net.com/image/info8/c7e48642fadf4133ba1719b7565bc3f3.gif)
105
![](http://img.e-com-net.com/image/info8/dca538039d924a5998870a9768532ef4.gif)
106
![](http://img.e-com-net.com/image/info8/4327117d69da4aa0b332f2a6e9c16200.gif)
107
![](http://img.e-com-net.com/image/info8/cefe3f37c3914799becdc730a232f0c5.gif)
108
![](http://img.e-com-net.com/image/info8/e57778b441274c47994328ad37ec19b1.gif)
109
![](http://img.e-com-net.com/image/info8/3608a3ebd163449597b4f1e0f7f3f90b.gif)
110
![](http://img.e-com-net.com/image/info8/7cd8cd863d78402c871d4d1e559bff86.gif)
111
![](http://img.e-com-net.com/image/info8/6cb68f4459274678b0fdb4f3c1ad5289.gif)
112
![](http://img.e-com-net.com/image/info8/02bd8a222848463e96e87a912e53bed6.gif)
113
![](http://img.e-com-net.com/image/info8/ce6e606c36d34df48a6c25a27493c203.gif)
114
![](http://img.e-com-net.com/image/info8/7694e17d1ab249afa3ab5806f06efa7d.gif)
115
![](http://img.e-com-net.com/image/info8/50573f45274d40d9894ca73088f34d2a.gif)
116
![](http://img.e-com-net.com/image/info8/80d0d29cda124fbea5713097478d0f19.gif)
117
![](http://img.e-com-net.com/image/info8/5f9ac08373bb4ebeba93f8624e66cff9.gif)
118
![](http://img.e-com-net.com/image/info8/555ada61c2564c5bb6ad08eb0ee7fb62.gif)
119
![](http://img.e-com-net.com/image/info8/37ac18cfb0204b82a33bdd3afef1c868.gif)
120
![](http://img.e-com-net.com/image/info8/34e08ca069ae49b283ee7fa7386b05c7.gif)
使用UI Automation实现自动化测试--3
Chapter 3 UI Automation中的几个重要属性
Control Tree of the AutomationElement
在UI Automation控件树中,根节点为Desktop window, 其他运行在用户桌面的窗体都作为Desktop window的子节点。
如下图所示:
Desktop window可通过AutomationElement.RootElement属性获取,子节点中的窗体或对话框可通过
AutomationElement.RootElement.FindAll(TreeScope.Descendants, condition)
或
AutomationElement.RootElement.FindFirt(TreeScope.Descendants, condition)来获取.
AutomationElement property
在UI Automation中有如下几个重要属性:
- AutomationIdProperty: 通过AutomationId来查找AutomationElement。
- NameProperty:通过控件的Name属性来查找AutomationElement。
- ControlType:通过控件的类型来查找AutomationElement
- AutomationId: 唯一地标识自动化元素,将其与同级相区分。
- Name: WPF 按钮的Content 属性、Win32 按钮的Caption 属性以及 HTML 图像的ALT 属性都映射到 UI 自动化视图中的同一个属性 Name。
注:PropertyCondition类是用来对相关属性进行条件匹配,在控件树中查找控件时,可以通过最佳匹配来找到相应的控件。
如下代码列出了使用不同的属性来构建PropertyCondition,通过PropertyCondition来查找控件树中的控件.
public class PropertyConditions
{
static PropertyCondition propertyCondition;
///
/// Create PropertyCondition by AutomationId
///
/// Control AutomationId
///
public static PropertyCondition GetAutomationIdProperty(object automationId)
{
propertyCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, automationId);
return propertyCondition;
}
///
///
///
///
///
public static PropertyCondition GetControlTypeProperty(object controlType)
{
propertyCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, controlType);
return propertyCondition;
}
///
///
///
///
///
public static PropertyCondition GetNameProperty(object controlName)
{
propertyCondition = new PropertyCondition(AutomationElement.NameProperty, controlName);
return propertyCondition;
}
///
/// Find element by specific PropertyCondition
///
/// PropertyCondition instance
///
public static AutomationElement FindElement(PropertyCondition condition)
{
return AutomationElement.RootElement.FindFirst(TreeScope.Descendants, condition);
}
}
使用UI Automation实现自动化测试--4.1 (DockPattern)
DockPattern用于操作可停靠容器控件,我们最熟悉的VS2005/2008中的ToolBox,Solution Explorer都可以设置不同的DockPosition, 但是目前并不支持DockPattern,所以无法做为实例来讲。使用DockPattern的前提为控件支持DockPattern。 DockPattern中的DockPosition有六个枚举变量,即Bottom、Left、Right、Top、Fill和None。如果控件支持DockPattern, 则可以获取相对应的DockPosition以及设置控件的DockPosition。
如下代码是获取控件的DockPattern、获取控件当前的DockPosition以及设置控件的DockPosition。
#region DockPattern helper
///
/// Get DockPattern
///
/// AutomationElement instance
///
public static DockPattern GetDockPattern(AutomationElement element)
{
object currentPattern;
if (!element.TryGetCurrentPattern(DockPattern.Pattern, out currentPattern))
{
throw new Exception(string.Format("Element with AutomationId '{0}' and Name '{1}' does not support the DockPattern.",
element.Current.AutomationId, element.Current.Name));
}
return currentPattern as DockPattern;
}
///
/// Get DockPosition
///
/// AutomationElement instance
///
public static DockPosition GetDockPosition(AutomationElement element)
{
return GetDockPattern(element).Current.DockPosition;
}
///
/// Set DockPosition
///
/// AutomationElement instance
public static void SetDockPattern(AutomationElement element, DockPosition dockPosition)
{
GetDockPattern(element).SetDockPosition(dockPosition);
}
#endregion
使用UI Automation实现自动化测试--4.2 (ExpandCollapsePattern)
ExpandCollapsePattern
表示以可视方式进行展开(以显示内容)和折叠(以隐藏内容)的控件。例如ComboBox控件支持ExpandCollapsePattern。
ExpandCollapsePattern有两个主要方法:
Expand()方法:隐藏 AutomationElement 的全部子代节点、控件或内容。
Collapse()方法:显示 AutomationElement 的全部子节点、控件或内容。
以下代码是用ExpandCollapsePattern来测试ComboBox控件的Expand和Collapse。
![](http://img.e-com-net.com/image/info8/6763adbd045e45078a39d2e38ec26efd.gif)
![](http://img.e-com-net.com/image/info8/329e14766e28499bae560f2bdd87590c.gif)
![](http://img.e-com-net.com/image/info8/6ccea6f4bcf848fe9c1086a254693d9d.gif)
![](http://img.e-com-net.com/image/info8/cbdaab62c10e437ebd70bbca6f4ff941.gif)
![](http://img.e-com-net.com/image/info8/f9cb4d01b0ea4b79a882045eb8bf8527.gif)
![](http://img.e-com-net.com/image/info8/602a260979ca4a63929ae44013cb447e.gif)
![](http://img.e-com-net.com/image/info8/570a3a6274454444a406d0e5e9eda426.gif)
![](http://img.e-com-net.com/image/info8/88e00513f74c4e7093b60a581de4c39e.gif)
![](http://img.e-com-net.com/image/info8/297e15be917b417eb068e3fdea72a911.gif)
![](http://img.e-com-net.com/image/info8/6b2692f7da554c3999e0655ecaf38b79.gif)
![](http://img.e-com-net.com/image/info8/00e7e2e886bf4a568d2b72f5b233714b.gif)
![](http://img.e-com-net.com/image/info8/de5f3f0addc147f1aeb7b24b5a14d8dc.gif)
![](http://img.e-com-net.com/image/info8/a5c94dd175e6432bbce89c834d0bf2fc.gif)
![](http://img.e-com-net.com/image/info8/e259096063cb4fae9fd69b3d733d52a6.gif)
![](http://img.e-com-net.com/image/info8/0a926331b8134cd496538dd4ed9e9b71.gif)
![](http://img.e-com-net.com/image/info8/d2c95cd0e0d64ad69dcce77f11602d2d.gif)
![](http://img.e-com-net.com/image/info8/03b4b8efb9c74943b06a65a15e973438.gif)
![](http://img.e-com-net.com/image/info8/349a26e0d78a4e0f8beba1037d3da321.gif)
![](http://img.e-com-net.com/image/info8/f89df6093e1445fca8c981c60f858556.gif)
![](http://img.e-com-net.com/image/info8/2706d1492d9e45d9b32845bca5ab6917.gif)
![](http://img.e-com-net.com/image/info8/ca09a622f28b4803a9b4988474b314a2.gif)
![](http://img.e-com-net.com/image/info8/0b91871bb144407f980084134a194fc6.gif)
![](http://img.e-com-net.com/image/info8/0ad9785048a04b4fbcd02e565667497b.gif)
![](http://img.e-com-net.com/image/info8/d464ba3b8dc748ebbbaff860f58a085d.gif)
![](http://img.e-com-net.com/image/info8/658feef3a7af432cb82c802933978d5c.gif)
![](http://img.e-com-net.com/image/info8/ed4668d5460249119ec6fafddd4d15ed.gif)
![](http://img.e-com-net.com/image/info8/0edd117ebd1a42219424113141fc8aba.gif)
![](http://img.e-com-net.com/image/info8/f9680e8f47cb4de3b68bd73bf4002d1b.gif)
![](http://img.e-com-net.com/image/info8/617e116132804efe87620ba76b161195.gif)
![](http://img.e-com-net.com/image/info8/0e1961692b1848c0b7cfe9ff760312ce.gif)
![](http://img.e-com-net.com/image/info8/79bc007f130d46feb6e52b21bb6975e2.gif)
![](http://img.e-com-net.com/image/info8/29163f8408c6475a8f945f86f8c7536a.gif)
![](http://img.e-com-net.com/image/info8/ed5e80598ef04a29b5a3b899bca05b49.gif)
![](http://img.e-com-net.com/image/info8/c64ff7ed2d384289bb96c64e14192995.gif)
![](http://img.e-com-net.com/image/info8/ce7f804ef02c4f79a4f26afc44264fc3.gif)
![](http://img.e-com-net.com/image/info8/d0a016dfb2134e778994b26bbf728710.gif)
![](http://img.e-com-net.com/image/info8/bdebcf2ee39941e093d0490c5c3cf23c.gif)
![](http://img.e-com-net.com/image/info8/cf014928464b4f2dad1b895694d00d9d.gif)
![](http://img.e-com-net.com/image/info8/8883e6567604496a87ac74bb220184df.gif)
![](http://img.e-com-net.com/image/info8/57a1a431fee447fd9c46e2abbb27527d.gif)
![](http://img.e-com-net.com/image/info8/28a43e43129e4f76973d35ead3527018.gif)
![](http://img.e-com-net.com/image/info8/9cd26c56aded461e8594194d07dc40c2.gif)
![](http://img.e-com-net.com/image/info8/f1a9a3eb31fe42d1928e0a898a478b3a.gif)
![](http://img.e-com-net.com/image/info8/356bdb53164549b1bae9d217797eaa21.gif)
![](http://img.e-com-net.com/image/info8/207a5da931324bd09fa89a6690c85fef.gif)
![](http://img.e-com-net.com/image/info8/663c4af134f840cdb41b22c34aa8490a.gif)
![](http://img.e-com-net.com/image/info8/fe3be390e2d14c8781495f2ef73882fc.gif)
![](http://img.e-com-net.com/image/info8/bff09a97de9e4070a30f91eaac96ffc7.gif)
![](http://img.e-com-net.com/image/info8/68898edf85f347648ea6750d87734c89.gif)
![](http://img.e-com-net.com/image/info8/30457e3a1b3f4469bbaa55f446255f5e.gif)
![](http://img.e-com-net.com/image/info8/0a4195edfe1545a0bd4c4255f4b6e775.gif)
![](http://img.e-com-net.com/image/info8/32a789ba35b14425acf168ac677182f2.gif)
![](http://img.e-com-net.com/image/info8/ba953f657ea64ff4ab5b0fadd2305b0a.gif)
![](http://img.e-com-net.com/image/info8/4de1336d7db04d3ab493dfec65ccc60b.gif)
![](http://img.e-com-net.com/image/info8/0cc389af034c438faac946406e7a66ae.gif)
![](http://img.e-com-net.com/image/info8/285f9bc19c4c48bea810d427763ba44c.gif)
![](http://img.e-com-net.com/image/info8/378968d2d9f84fa68647abdfda6beacd.gif)
![](http://img.e-com-net.com/image/info8/2900c732f8d34d54ab59a8e2a0aa6ed3.gif)
![](http://img.e-com-net.com/image/info8/229cfe16b1d44c59a5bc8887c40b0395.gif)
![](http://img.e-com-net.com/image/info8/d78fb04d8d8f4cc6a121a671060758bf.gif)
![](http://img.e-com-net.com/image/info8/4a7389af834d41ae9fdcfba9ab8c28f4.gif)
![](http://img.e-com-net.com/image/info8/07be5bf67b64427188966ef96e894c72.gif)
![](http://img.e-com-net.com/image/info8/8ce80373e98146a6bc147c46498c9140.gif)
![](http://img.e-com-net.com/image/info8/f8b17655051e42789bbae907eed89c4b.gif)
![](http://img.e-com-net.com/image/info8/ee8a41c50e6b4d199b7c1889acf17390.gif)
![](http://img.e-com-net.com/image/info8/eaab6419c741494a968ee6c95777cacd.gif)
![](http://img.e-com-net.com/image/info8/36f2f9e665584205b7d4182900fc0559.gif)
![](http://img.e-com-net.com/image/info8/f4292a6d430643d08f913a6ccbc5097d.gif)
![](http://img.e-com-net.com/image/info8/9f84c51c83334b6e978015d114859327.gif)
![](http://img.e-com-net.com/image/info8/dba9be87192c4fe79adc5005f38d669f.gif)
![](http://img.e-com-net.com/image/info8/236a4c3129a048faa44d3a945c78272e.gif)
![](http://img.e-com-net.com/image/info8/a0f6caaad94f48e682fe82e959461067.gif)
以下代码为被测程序的xaml文件:
![](http://img.e-com-net.com/image/info8/03f1dda1f80a40b5991ecfc344d2d69e.gif)
1
![](http://img.e-com-net.com/image/info8/d0b47aa954ac46c8a12d9f296183bea8.gif)
2
![](http://img.e-com-net.com/image/info8/65147238d9d5455e846f8167d6c13f86.gif)
3
![](http://img.e-com-net.com/image/info8/cafcf9d224b04486b07fe7e85be79dc1.gif)
4
![](http://img.e-com-net.com/image/info8/95e6f2d285b0478c891d6327d10dc460.gif)
5
![](http://img.e-com-net.com/image/info8/34f7f83175ee44f8bcad82fbb32f9ff2.gif)
6
![](http://img.e-com-net.com/image/info8/83fd33b3b85f4a62bef6bbdec7e0389a.gif)
7
![](http://img.e-com-net.com/image/info8/14e8e4df37554fd2b125fabfc90e1732.gif)
8
![](http://img.e-com-net.com/image/info8/7ae947a6b3084bebb50341cedf4d169f.gif)
9
![](http://img.e-com-net.com/image/info8/290300cb2a354588bfdc09a30a96998e.gif)
10
![](http://img.e-com-net.com/image/info8/317789b1f6ef41e09f9e8344278e44e3.gif)
11
![](http://img.e-com-net.com/image/info8/567c2817b4d840b58d3f683c361cf4eb.gif)
使用UI Automation实现自动化测试--4.3 (InvokePattern)
InvokePattern
InvokePattern是UIA中最常用的Pattern之一,WPF和Winform中的button控件都支持InvokePattern。
对InvokePattern的Invoke()方法的调用应立即返回,没有出现阻止情况。但是,此行为完全依赖于 Microsoft UI 自动化提供程序实现。在调用 Invoke() 会引起阻止问题(如Winform中的模式对话框,但是WPF中的对话框的处理方式和winform不同,所以可以使用Invoke()方法来操作WPF中的模式对话框,因为WPF中的模式对话框不会出现阻止的问题)的情况下,要调用此方法,则需要另起线程来操作。
using System;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;
namespace UIATest
{
class Program
{
static void Main(string[] args)
{
Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
int processId = process.Id;
AutomationElement element = FindElementById(processId, "button1");
InvokePattern currentPattern = GetInvokePattern(element);
currentPattern.Invoke();
}
///
/// Get the automation elemention of current form.
///
/// Process Id
///
public static AutomationElement FindWindowByProcessId(int processId)
{
AutomationElement targetWindow = null;
int count = 0;
try
{
Process p = Process.GetProcessById(processId);
targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
return targetWindow;
}
catch (Exception ex)
{
count++;
StringBuilder sb = new StringBuilder();
string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
if (count > 5)
{
throw new InvalidProgramException(message, ex);
}
else
{
return FindWindowByProcessId(processId);
}
}
}
///
/// Get the automation element by automation Id.
///
/// Window name
/// Control automation Id
///
public static AutomationElement FindElementById(int processId, string automationId)
{
AutomationElement aeForm = FindWindowByProcessId(processId);
AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
return tarFindElement;
}
#region InvokePattern helper
///
/// Get InvokePattern
///
/// AutomationElement instance
///
public static InvokePattern GetInvokePattern(AutomationElement element)
{
object currentPattern;
if (!element.TryGetCurrentPattern(InvokePattern.Pattern, out currentPattern))
{
throw new Exception(string.Format("Element with AutomationId '{0}' and Name '{1}' does not support the InvokePattern.",
element.Current.AutomationId, element.Current.Name));
}
return currentPattern as InvokePattern;
}
#endregion
}
}
被测程序xaml代码如下:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="219" Width="353">
对应的cs文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp
{
///
/// Interaction logic for Window1.xaml
///
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Use InvokePattern invoke button.");
}
}
}
本文主要针对InvokePattern的Invoke方法来操作button控件。
使用UI Automation实现自动化测试--4.4 (ValuePattern)
ValuePattern是UI Automation中最常见的Pattern之一,Winform和WPF的TextBox控件都支持ValuePattern。
ValuePattern的一个重要的方法是SetValue,在允许调用 SetValue 之前,控件应将其 IsEnabledProperty 设置为 true 并将其 IsReadOnlyProperty 设置为 false。
通过ValuePattern的Current属性可以获得控件的value和IsReadOnly属性。
实现 Value 控件模式时,请注意以下准则和约定:
如果任何项的值是可编辑的,则诸如 ListItem 和 TreeItem 等控件必须支持 ValuePattern,而不管控件的当前编辑模式如何。如果子项是可编辑的,则父控件还必须支持ValuePattern。
下面的例子是通过ValuePattern来给TextBox设置和获取值:
1using System;
2using System.Text;
3using System.Diagnostics;
4using System.Threading;
5using System.Windows.Automation;
6
7namespace UIATest
8{
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14 int processId = process.Id;
15 AutomationElement element = FindElementById(processId, "textBox1");
16 ValuePattern currentPattern = GetValuePattern(element);
17 Console.WriteLine("Is read only:'{0}', TextBox text is:'{1}'", currentPattern.Current.IsReadOnly, currentPattern.Current.Value);
18 currentPattern.SetValue("KadenKang");
19 Console.WriteLine("After using the SetValue, the TextBox value is '{0}'", currentPattern.Current.Value);
20
21 }
22
23 ///
24 /// Get the automation elemention of current form.
25 ///
26 /// Process Id
27 ///
28 public static AutomationElement FindWindowByProcessId(int processId)
29 {
30 AutomationElement targetWindow = null;
31 int count = 0;
32 try
33 {
34 Process p = Process.GetProcessById(processId);
35 targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
36 return targetWindow;
37 }
38 catch (Exception ex)
39 {
40 count++;
41 StringBuilder sb = new StringBuilder();
42 string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
43 if (count > 5)
44 {
45 throw new InvalidProgramException(message, ex);
46 }
47 else
48 {
49 return FindWindowByProcessId(processId);
50 }
51 }
52 }
53
54 ///
55 /// Get the automation element by automation Id.
56 ///
57 /// Window name
58 /// Control automation Id
59 ///
60 public static AutomationElement FindElementById(int processId, string automationId)
61 {
62 AutomationElement aeForm = FindWindowByProcessId(processId);
63 AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
64 new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
65 return tarFindElement;
66 }
67
68 ValuePattern helper
87 }
88}
89
下面的代码是xaml设计:
1
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="Window1" Height="219" Width="353">
5
6
7
8
9
本文通过简单的实例介绍了UI Automation中的ValuePattern及其使用方法。
使用UI Automation实现自动化测试--4.5 (WindowPattern)
WindowPattern 控件模式用于支持在传统的 图形用户界面 (GUI) 内提供基于基本窗口的功能的控件。必须实现此控件模式的控件的示例包括顶级应用程序窗口、多文档界面 (MDI) 子窗口、大小可调的拆分窗格控件、模式对话框以及气球状帮助窗口。可以使用WindowPattern来对window进行操作,例如验证window是否激活,是否最大化、最小化、正常模式以及关闭window等。
下面的代码演示了WindowPattern的使用方法:
![](http://img.e-com-net.com/image/info8/10abdd7bd1254f0d901838d8c613c3e0.gif)
1
![](http://img.e-com-net.com/image/info8/95a5ec5b230f48dc951c3dc99e223e7f.gif)
2
![](http://img.e-com-net.com/image/info8/0a81acb08f794effb7e98e3852ccffb3.gif)
3
![](http://img.e-com-net.com/image/info8/51a30ce7609e441286f5c2155c4292d4.gif)
4
![](http://img.e-com-net.com/image/info8/b714bfcd7dc84484b143f1a70f61f75f.gif)
5
![](http://img.e-com-net.com/image/info8/52829e4aa8174801a89c90042788109e.gif)
6
![](http://img.e-com-net.com/image/info8/a3c6633fc49c48369d72797a5e9dfb87.gif)
7
![](http://img.e-com-net.com/image/info8/76a5778222534fc698a86022970c9431.gif)
8
![](http://img.e-com-net.com/image/info8/ceb98171332a49b99182f036f187a581.gif)
9
![](http://img.e-com-net.com/image/info8/2897047195b6441db59c25383fc13b4d.gif)
10
![](http://img.e-com-net.com/image/info8/0186127bb7f9442c974f71a1dac40950.gif)
11
![](http://img.e-com-net.com/image/info8/813b6d32df3141db8d786a67e1112de2.gif)
12
![](http://img.e-com-net.com/image/info8/9c164987c23d468fad67a413f95d1cfe.gif)
13
![](http://img.e-com-net.com/image/info8/1294e7a128e34a3f8223611e4a0b50eb.gif)
14
![](http://img.e-com-net.com/image/info8/7fed4a9f38fa46f0b5bd6525eadafc76.gif)
15
![](http://img.e-com-net.com/image/info8/13cae51dfe6444118fcd03f936b21038.gif)
16
![](http://img.e-com-net.com/image/info8/fc3b64ba911a48a79fd6877e5b3a2a05.gif)
17
![](http://img.e-com-net.com/image/info8/5a8095d1c858438488c6c96158969478.gif)
18
![](http://img.e-com-net.com/image/info8/9ebfca753a7b4cf7a98b8b51fbec1878.gif)
19
![](http://img.e-com-net.com/image/info8/abaaac72bf0e4a989724b1f3d96c9a52.gif)
20
![](http://img.e-com-net.com/image/info8/0fc9fca7f30b420b8d673cade6808127.gif)
21
![](http://img.e-com-net.com/image/info8/4a2d567b25e14c039d7571439ba8a0be.gif)
22
![](http://img.e-com-net.com/image/info8/4443007349974897af2d9a36c1617ab2.gif)
23
![](http://img.e-com-net.com/image/info8/26db56786c4a4b968c2e2567cc57be5f.gif)
24
![](http://img.e-com-net.com/image/info8/7d00ef2bd0ee4cd7bd4e082c96913442.gif)
25
![](http://img.e-com-net.com/image/info8/ff4f386eefbe4b1c9bdd17aef1a4c727.gif)
26
![](http://img.e-com-net.com/image/info8/c70f6bbd97614db5b3c30bd2d3bb3fdd.gif)
27
![](http://img.e-com-net.com/image/info8/cb64a2be6e0b440cbd1f58ac5cb448b9.gif)
28
![](http://img.e-com-net.com/image/info8/e16c60a0518a4459a94d9ffcc8174a7d.gif)
29
![](http://img.e-com-net.com/image/info8/51cdea5b692e4d36a5a806904c186689.gif)
30
![](http://img.e-com-net.com/image/info8/7363bae5a1af469888cb2299a6cddafd.gif)
31
![](http://img.e-com-net.com/image/info8/20306adc3e164442a1eea38b05b9f72b.gif)
32
![](http://img.e-com-net.com/image/info8/b8a5cb17d87740e79fe8e23ad1f79649.gif)
33
![](http://img.e-com-net.com/image/info8/55183507e836477181c4706f73da4502.gif)
34
![](http://img.e-com-net.com/image/info8/8e98e0c600a2407bb61472ed4986bd55.gif)
35
![](http://img.e-com-net.com/image/info8/7250abf7d7ec4815986ad4a6228d06d8.gif)
36
![](http://img.e-com-net.com/image/info8/651d978c343a48cea4471b2e57a98747.gif)
37
![](http://img.e-com-net.com/image/info8/45c9cda6ccc84d5c8c04a0654ff40001.gif)
38
![](http://img.e-com-net.com/image/info8/d30bcf05625e4ae3bc3f444f19ee0e5a.gif)
39
![](http://img.e-com-net.com/image/info8/fcdaf65f104c44aea8cd85b370ecabca.gif)
40
![](http://img.e-com-net.com/image/info8/ee7ad5f24a7d4ddcbf06469c0cfc09f4.gif)
41
![](http://img.e-com-net.com/image/info8/ed378b8d140f4217b85716a622b4715c.gif)
42
![](http://img.e-com-net.com/image/info8/3632c824e63d4e1c90f980ba24a15431.gif)
43
![](http://img.e-com-net.com/image/info8/4a4a793e8e664077a2f276ff0ba7890f.gif)
44
![](http://img.e-com-net.com/image/info8/d3dbe8908354413a9ea6ddc8dece817f.gif)
45
![](http://img.e-com-net.com/image/info8/b14bf2e0aaaf4f6b9a0b81ec8c9770cf.gif)
46
![](http://img.e-com-net.com/image/info8/caccb7d554c64ba58b7be1581e5835d6.gif)
47
![](http://img.e-com-net.com/image/info8/a0c36a97037b4d65a08c48cc1a828d44.gif)
48
![](http://img.e-com-net.com/image/info8/fb0fe119a3a0413790a69d111431b0de.gif)
49
![](http://img.e-com-net.com/image/info8/c60d8624bc1d426b954a05226576889b.gif)
50
![](http://img.e-com-net.com/image/info8/40fffdd9cc9c4b23b6ac4c777780988b.gif)
51
![](http://img.e-com-net.com/image/info8/63776c269bc94011a3649f7187d612b7.gif)
52
![](http://img.e-com-net.com/image/info8/d7a84d0f65b3444db66f4d79f20ca60e.gif)
53
![](http://img.e-com-net.com/image/info8/91c1ee9b72314058a7d39f544b2c9637.gif)
54
![](http://img.e-com-net.com/image/info8/d4192ed5dcec4bc792a8d66911a02947.gif)
55
![](http://img.e-com-net.com/image/info8/646278f09cd443839d69c040cdd5fbf8.gif)
56
![](http://img.e-com-net.com/image/info8/75c18a1a5d6741c980f519b19f7716ac.gif)
57
![](http://img.e-com-net.com/image/info8/0d22afbc3f8740c28256db31909c802a.gif)
58
![](http://img.e-com-net.com/image/info8/97178494581f49bd9085668f2e6ae2b3.gif)
59
![](http://img.e-com-net.com/image/info8/371c3952d117411ba76a0e986a1a15ad.gif)
60
![](http://img.e-com-net.com/image/info8/e9d0a429d3424c59ad6e41cafd34db25.gif)
61
![](http://img.e-com-net.com/image/info8/a486ba16393a4e5c8fdbc9c65ce3e252.gif)
62
![](http://img.e-com-net.com/image/info8/0b1bac5e915641bc8fd582a365ca7231.gif)
63
![](http://img.e-com-net.com/image/info8/9313c3bf6ce14d61a34d642da257085a.gif)
64
![](http://img.e-com-net.com/image/info8/bd099b987b5d4ecfa9f866d755f3d013.gif)
83
![](http://img.e-com-net.com/image/info8/b9de4126c541486c94d54c098b0de642.gif)
84
![](http://img.e-com-net.com/image/info8/a2654d9f1eee4eed8d54b164a44a3899.gif)
使用UI Automation实现自动化测试--4.6.1 (SelectionItemPattern)
SelectionItemPattern
支持SelectionItemPattern的控件有ListView、ListBox、RadioButton、GridView等。
- 1. SelectionItemPattern的三个重要方法:
- 1. AddToSelection:将当前元素添加到所选项的集合。
- 2. RemoveFromSelection: 从选定项的集合中移除当前元素。
- 3. Select: 取消所有已选中的项,然后选择当前元素。
- 2. SelectionItemPattern的Current属性可通过Current属性的IsSelected属性来判断AutomationElement是否被selected.
如下代码演示了使用SelectionItemPattern来操作RadioButton控件。
1using System;
2using System.Text;
3using System.Diagnostics;
4using System.Threading;
5using System.Windows.Automation;
6
7namespace UIATest
8{
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14 int processId = process.Id;
15
16 AutomationElement element = FindElementById(processId, "radioButton1");
17 SelectionItemPattern selectionItemPattern = GetSelectionItemPattern(element);
18 selectionItemPattern.Select();
19 }
20
21 ///
22 /// Get the automation elemention of current form.
23 ///
24 /// Process Id
25 ///
26 public static AutomationElement FindWindowByProcessId(int processId)
27 {
28 AutomationElement targetWindow = null;
29 int count = 0;
30 try
31 {
32 Process p = Process.GetProcessById(processId);
33 targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
34 return targetWindow;
35 }
36 catch (Exception ex)
37 {
38 count++;
39 StringBuilder sb = new StringBuilder();
40 string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
41 if (count > 5)
42 {
43 throw new InvalidProgramException(message, ex);
44 }
45 else
46 {
47 return FindWindowByProcessId(processId);
48 }
49 }
50 }
51
52
53 ///
54 /// Get the automation element by automation Id.
55 ///
56 /// Window name
57 /// Control automation Id
58 ///
59 public static AutomationElement FindElementById(int processId, string automationId)
60 {
61 AutomationElement aeForm = FindWindowByProcessId(processId);
62 AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
63 new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
64 return tarFindElement;
65 }
66
67 SelectItemPattern
86 }
87}
88
以下代码为XAML:
1
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="Window1" Height="219" Width="353">
5
6
7
8
9
本文简单介绍了SelectionItemPattern以及使用SelectionItemPattern来操作RadioButton。
使用UI Automation实现自动化测试--4.6.2 (SelectItemPattern Demo)
如下代码演示了使用SelectionItemPattern来实现listview item 的多选操作:
![](http://img.e-com-net.com/image/info8/91de059682144c6385af7a31557f6354.gif)
1
![](http://img.e-com-net.com/image/info8/a74837e87a624d9fab74666e6ff3c1df.gif)
2
![](http://img.e-com-net.com/image/info8/41e017bd5a544f6e9516f3fb5f92a002.gif)
3
![](http://img.e-com-net.com/image/info8/09dc42fffab244258fb41b1907a9dcad.gif)
4
![](http://img.e-com-net.com/image/info8/3fe0490b16ae44f88a1c9adfbc603064.gif)
5
![](http://img.e-com-net.com/image/info8/760b9453a9734d87a2b746da837c0f64.gif)
6
![](http://img.e-com-net.com/image/info8/721691645d194dc6b42c58d7cced43de.gif)
7
![](http://img.e-com-net.com/image/info8/41e95267912849dba27f2bd3e4a25858.gif)
8
![](http://img.e-com-net.com/image/info8/299559164408437cb591e702168c0510.gif)
9
![](http://img.e-com-net.com/image/info8/44833418174b4268a169d523eb52d5f8.gif)
10
![](http://img.e-com-net.com/image/info8/150cae19bbbb4b398b6809b85b9258eb.gif)
11
![](http://img.e-com-net.com/image/info8/9521f87430c44e19a053622dfa48c29b.gif)
12
![](http://img.e-com-net.com/image/info8/2e02be5cb70949c89edd4c029a720d9f.gif)
13
![](http://img.e-com-net.com/image/info8/efb8628b4cad4c81808d28f586b5a9ba.gif)
14
![](http://img.e-com-net.com/image/info8/9bb44bba653e45f281b2fa93369fce4f.gif)
15
![](http://img.e-com-net.com/image/info8/ce8a7ea3a518444aab59eca6dc62f575.gif)
16
![](http://img.e-com-net.com/image/info8/2d3b15efdef54335906f6cabead0db54.gif)
17
![](http://img.e-com-net.com/image/info8/6074055b41594d65aab4ab351c62585c.gif)
18
![](http://img.e-com-net.com/image/info8/2cb8e5f0c92b4a569a0a5e3d8bd06327.gif)
19
![](http://img.e-com-net.com/image/info8/e3499f466f584ae28dee4d882c43fe04.gif)
20
![](http://img.e-com-net.com/image/info8/32d419ab241f47669a510608b940fa01.gif)
21
![](http://img.e-com-net.com/image/info8/908400cd34194106b199c4e3ad74dfa1.gif)
22
![](http://img.e-com-net.com/image/info8/50f007349d784749b03954d8370bc190.gif)
23
![](http://img.e-com-net.com/image/info8/6118d8a42a0e4438a187d29f879fabd3.gif)
24
![](http://img.e-com-net.com/image/info8/c860e994f6624a17b4e430ce7a3ea7ff.gif)
25
![](http://img.e-com-net.com/image/info8/b207ef264c334f0ea66135f0356e1252.gif)
26
![](http://img.e-com-net.com/image/info8/b05b4ffb3a754b62bb68821788e9d42b.gif)
27
![](http://img.e-com-net.com/image/info8/c62d182fb6e64d12bfe7d7b1061a6e83.gif)
28
![](http://img.e-com-net.com/image/info8/b2f2ea8ec35e48b4b5de2180a09251c5.gif)
29
![](http://img.e-com-net.com/image/info8/0cf3b623d8e94a52b299a2d65ddb4dc6.gif)
30
![](http://img.e-com-net.com/image/info8/5126f8d91bae4d039c963c2ec3b58b70.gif)
31
![](http://img.e-com-net.com/image/info8/bd8e27f28c9b461da872de0e97723675.gif)
32
![](http://img.e-com-net.com/image/info8/6184f07d6bb04be2ab72f6d81b50f2b8.gif)
33
![](http://img.e-com-net.com/image/info8/00d0def411f64a6b937dfad036afb8d3.gif)
34
![](http://img.e-com-net.com/image/info8/5ef6f5056676422b96eeab10b2330b53.gif)
35
![](http://img.e-com-net.com/image/info8/a4d74844299841ff80099090930a8052.gif)
36
![](http://img.e-com-net.com/image/info8/00c4f60cd62f45e698cf508ad968ec9f.gif)
37
![](http://img.e-com-net.com/image/info8/120d054fbca94de5b992d0bd154b8f1a.gif)
38
![](http://img.e-com-net.com/image/info8/ccef78396be449a8868d1c76ac7f89d8.gif)
39
![](http://img.e-com-net.com/image/info8/4717ee17857649aba2e917e2603b83bd.gif)
40
![](http://img.e-com-net.com/image/info8/f6546b750f3441f5b7fb1300370d22e1.gif)
41
![](http://img.e-com-net.com/image/info8/a016e458b042442cbee8881827ee7588.gif)
42
![](http://img.e-com-net.com/image/info8/ba26d05816e74e0583aded30066bad89.gif)
43
![](http://img.e-com-net.com/image/info8/af4e31c04b20488c962cf45f0c8eb123.gif)
44
![](http://img.e-com-net.com/image/info8/cd0367fe41f040a5b703b2d2db388478.gif)
45
![](http://img.e-com-net.com/image/info8/80426fed24ac4374a6a141ab89a7428d.gif)
46
![](http://img.e-com-net.com/image/info8/bc106eff5eac4e0c8ee78339b7295e4f.gif)
47
![](http://img.e-com-net.com/image/info8/a4ab1859920148b0b4d063d13c5822f0.gif)
48
![](http://img.e-com-net.com/image/info8/a881b254ddd34257866a1fa9b02962ef.gif)
49
![](http://img.e-com-net.com/image/info8/18e58cf3288e4b86866e2db73baf68fa.gif)
50
![](http://img.e-com-net.com/image/info8/d9eb33465fd24dbba13163ff5e6658e1.gif)
51
![](http://img.e-com-net.com/image/info8/22670d74710d43b3a315d77028344445.gif)
52
![](http://img.e-com-net.com/image/info8/989ccc21181d4c8b82e60bd423f4e098.gif)
53
![](http://img.e-com-net.com/image/info8/26aa5186f91049f79b5718d9ebe0ae5f.gif)
54
![](http://img.e-com-net.com/image/info8/2ace8cf73eea4a0c917b761eefd361bf.gif)
55
![](http://img.e-com-net.com/image/info8/f26a86a11bfd4e23896b5a4575c337a1.gif)
56
![](http://img.e-com-net.com/image/info8/ed272beece7a4944bb835a0d9507337e.gif)
57
![](http://img.e-com-net.com/image/info8/77ba9b1fab3f4567bb0af0f3f9a721db.gif)
58
![](http://img.e-com-net.com/image/info8/83902bb0987b4339a3626ea435f93064.gif)
59
![](http://img.e-com-net.com/image/info8/a2f3323e5326496f8060c81f828675a3.gif)
60
![](http://img.e-com-net.com/image/info8/5e1a36e40e394c91b7b9d6bf526ff8a1.gif)
61
![](http://img.e-com-net.com/image/info8/5eac98c7c6b14deca4969416ce8a225f.gif)
62
![](http://img.e-com-net.com/image/info8/fd3f699f1d164751b2aac00b1b9ebd2e.gif)
63
![](http://img.e-com-net.com/image/info8/8ac17489f39547289bc7dacf0a54eac2.gif)
64
![](http://img.e-com-net.com/image/info8/14f9f219be3248e59286506c407be30d.gif)
65
![](http://img.e-com-net.com/image/info8/6e73ad0d7fd2487abb543dd29bc7a424.gif)
66
![](http://img.e-com-net.com/image/info8/39272cc9ae60459b99e9b76811b5b9d0.gif)
67
![](http://img.e-com-net.com/image/info8/0924bb7891ad461ca2138d9fed42eb17.gif)
68
![](http://img.e-com-net.com/image/info8/b99230c8d7704ca4b41b1ba7e36c9751.gif)
69
![](http://img.e-com-net.com/image/info8/244d33a5369c4ea4aa08441b58db8cc7.gif)
70
![](http://img.e-com-net.com/image/info8/53e7e5c9e82544f4a58a97d0c5606ed0.gif)
71
![](http://img.e-com-net.com/image/info8/a0f7cc92de8b469f85695e1b82426cb2.gif)
72
![](http://img.e-com-net.com/image/info8/6e9f0dff5d36454aa7f34ab320a517ac.gif)
73
![](http://img.e-com-net.com/image/info8/9a0e9e9e3bfe4eac88e94039fcbbc4f9.gif)
74
![](http://img.e-com-net.com/image/info8/4b1267ef230f4a2791ec7fa10e3b0e3f.gif)
75
![](http://img.e-com-net.com/image/info8/929e8a19aa854f46a7d32d76ebf3e061.gif)
76
![](http://img.e-com-net.com/image/info8/9bf3fb6938b84d1295e7c489a99eeb08.gif)
77
![](http://img.e-com-net.com/image/info8/a3ded48be30748cbb2bea633480cd323.gif)
78
![](http://img.e-com-net.com/image/info8/31ae01ede00e48aaba3616c1ae1e8152.gif)
79
![](http://img.e-com-net.com/image/info8/cff8fb46d6b94de0bd26b991c282ebb6.gif)
80
![](http://img.e-com-net.com/image/info8/214647114f984ee0a769f09c6519e152.gif)
81
![](http://img.e-com-net.com/image/info8/b376af06a3754d35aaac3e5a34528d19.gif)
82
![](http://img.e-com-net.com/image/info8/9c0beea40d464e99bc75b56a06f29202.gif)
83
![](http://img.e-com-net.com/image/info8/cfe2333cb4584711bfa9ed108a6481d4.gif)
84
![](http://img.e-com-net.com/image/info8/9bba4195301e49a1b56c3b53d64cea95.gif)
85
![](http://img.e-com-net.com/image/info8/008b1d00b3164ba291d0c6dbdfd2b2f4.gif)
86
![](http://img.e-com-net.com/image/info8/c490e74273d34107adafa996cf6f8754.gif)
87
![](http://img.e-com-net.com/image/info8/5af5171c799f42a4999991ac2f30b466.gif)
88
![](http://img.e-com-net.com/image/info8/3dec461a83a446ae81d1f711e4491b2c.gif)
89
![](http://img.e-com-net.com/image/info8/8bbb92bbefb147ea9dd9c733307ae4f6.gif)
90
![](http://img.e-com-net.com/image/info8/06e763d36cf04c5cbb7c37c4cae608e3.gif)
91
![](http://img.e-com-net.com/image/info8/c1c460a422c04ff1aaa82cf166f29bc3.gif)
92
![](http://img.e-com-net.com/image/info8/e17a4174b8224090a1027332459a0187.gif)
93
![](http://img.e-com-net.com/image/info8/7ed8275ca393460abbda781d39f533d8.gif)
94
![](http://img.e-com-net.com/image/info8/100b5aff2d564f0a879c5b58c60e322c.gif)
95
![](http://img.e-com-net.com/image/info8/346c2316d3a142a99d696f57e46773da.gif)
96
![](http://img.e-com-net.com/image/info8/eb379e2e297d4820922ba75ac64b03a4.gif)
97
![](http://img.e-com-net.com/image/info8/d909dcde10f3499ab8b32569d5f8b5cb.gif)
98
![](http://img.e-com-net.com/image/info8/dd29b0291a674bd0ab45ef11d98c7cfe.gif)
99
![](http://img.e-com-net.com/image/info8/b0a649ed15ee43949effcce3b05301e5.gif)
100
![](http://img.e-com-net.com/image/info8/b2a9a5ba85c84cfdba8b4cd50c97fa45.gif)
101
![](http://img.e-com-net.com/image/info8/3c232fdeaa814e72b1c289d4a2fd6ae3.gif)
102
![](http://img.e-com-net.com/image/info8/9926a2ae60ce4247885406ffb21b32fd.gif)
103
![](http://img.e-com-net.com/image/info8/0ed62573005a42aca9930dce83453ee4.gif)
104
![](http://img.e-com-net.com/image/info8/6d73129bfb704d68a58ee0f7e51465d4.gif)
105
![](http://img.e-com-net.com/image/info8/18d90ca0268d4bb1998601d431b4561f.gif)
106
![](http://img.e-com-net.com/image/info8/b93b356ceaac45b18e338a925e3cd2b3.gif)
107
![](http://img.e-com-net.com/image/info8/021bdc8531b048018b528ac76fa7b9b5.gif)
108
![](http://img.e-com-net.com/image/info8/febfa2c6d3924d6b873a09cfd1d6a6ec.gif)
127
![](http://img.e-com-net.com/image/info8/6e9ba7a1fb034e2da99422ca12e6c449.gif)
128
![](http://img.e-com-net.com/image/info8/359d76752a634a9da58c69f80e425afa.gif)
如下代码为对应的XAML:
![](http://img.e-com-net.com/image/info8/687f18f63f664ab594ad1db381f02532.gif)
1
![](http://img.e-com-net.com/image/info8/a91e0f588bfd4a028aa8c9c3053cc159.gif)
2
![](http://img.e-com-net.com/image/info8/3f9b7978e422444f921b372b76fa2de4.gif)
3
![](http://img.e-com-net.com/image/info8/6fdcaafb932f4a6ab836e1796444eab8.gif)
4
![](http://img.e-com-net.com/image/info8/3f8837cf17074ff9ba52542252790039.gif)
5
![](http://img.e-com-net.com/image/info8/16883857641f4e1fac3dff8eb6a76df9.gif)
6
![](http://img.e-com-net.com/image/info8/d1d4b3d09d8644668864023efd6d8f90.gif)
7
![](http://img.e-com-net.com/image/info8/6d49583cc4f442359bc7a7e20005028a.gif)
8
![](http://img.e-com-net.com/image/info8/a279b757288c4e58ad6b6fcdce2b7463.gif)
9
![](http://img.e-com-net.com/image/info8/2594cd7f13714ef7b8cd839085826c19.gif)
10
![](http://img.e-com-net.com/image/info8/b2d97ed2538943bf81926337d7a9c0ec.gif)
11
![](http://img.e-com-net.com/image/info8/0bdbbc7b250e4afd8e200a86a80e9c35.gif)
12
![](http://img.e-com-net.com/image/info8/271ad4f411fe40c189215e9efdfef0de.gif)
13
![](http://img.e-com-net.com/image/info8/1a9ee4c206f344cc8e3b897ba8358363.gif)
使用UI Automation实现自动化测试--4.7 (TogglePattern)
TogglePattern
支持TogglePattern的控件有CheckBox,TreeView中的button控件等。
- 1. TogglePattern的方法
Toggle方法用于操作可以循环通过的一组状态并在设置后保持某种状态。
- 2. TogglePattern属性
Current属性中的ToggleState有如下三种状态:
- 1. On
- 2. Off
- 3. Indeterminate
如下代码演示了使用TogglePattern来操作CheckBox控件。
1using System;
2using System.Text;
3using System.Diagnostics;
4using System.Threading;
5using System.Windows.Automation;
6
7namespace UIATest
8{
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14 int processId = process.Id;
15
16 Thread.Sleep(1000);
17 AutomationElement element = FindElementById(processId, "checkBox1");
18 TogglePattern togglePattern = GetTogglePattern(element);
19 togglePattern.Toggle();
20 }
21
22 ///
23 /// Get the automation elemention of current form.
24 ///
25 /// Process Id
26 ///
27 public static AutomationElement FindWindowByProcessId(int processId)
28 {
29 AutomationElement targetWindow = null;
30 int count = 0;
31 try
32 {
33 Process p = Process.GetProcessById(processId);
34 targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
35 return targetWindow;
36 }
37 catch (Exception ex)
38 {
39 count++;
40 StringBuilder sb = new StringBuilder();
41 string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
42 if (count > 5)
43 {
44 throw new InvalidProgramException(message, ex);
45 }
46 else
47 {
48 return FindWindowByProcessId(processId);
49 }
50 }
51 }
52
53 ///
54 /// Get the automation element by automation Id.
55 ///
56 /// Window name
57 /// Control automation Id
58 ///
59 public static AutomationElement FindElementById(int processId, string automationId)
60 {
61 AutomationElement aeForm = FindWindowByProcessId(processId);
62 AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
63 new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
64 return tarFindElement;
65 }
66
67 TogglePattern helper
83 }
84}
85
如下代码为对应的XAML:
1
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="Window1" Height="219" Width="353">
5
6
7
8
使用UI Automation实现自动化测试--4.8 (GridPattern)
GridPattern
支持GridPattern的最常见的控件为GridView, 在WPF中使用ListView和GridView组合即可得到相应的GridView。
GridPattern的方法
GetItem:此方法有两个参数,即DataGrid的Row和Column。
通过GridPattern的GetItem方法可以获取DataGrid中的某个确定的单元格,进而对单元进行操作。
对单元格的操作主要有以下几个方面:
- 1. 编辑单元个中的数据。
- 2. 获取单元格中的数据。
- 3. 获取单元格中嵌套的AutomationElement(一般使用与自定义控件中)。
GridPattern的属性
GridPattern的Current属性中有如下两个属性:
- 1. RowCount属性:GridPattern二维表格的行数。
- 2. ColumnCount属性:GridPattern二维表格列数。
下面我们通过一个实例来演示自动化测试中如何使用GridPattern来测试GridView的方法:
1using System;
2using System.Text;
3using System.Diagnostics;
4using System.Threading;
5using System.Windows.Automation;
6
7namespace UIATest
8{
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14 int processId = process.Id;
15 Thread.Sleep(1000);
16
17 GridPattern Test
30 }
31
32 ///
33 /// Get the automation elemention of current form.
34 ///
35 /// Process Id
36 ///
37 public static AutomationElement FindWindowByProcessId(int processId)
38 {
39 AutomationElement targetWindow = null;
40 int count = 0;
41 try
42 {
43 Process p = Process.GetProcessById(processId);
44 targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
45 return targetWindow;
46 }
47 catch (Exception ex)
48 {
49 count++;
50 StringBuilder sb = new StringBuilder();
51 string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
52 if (count > 5)
53 {
54 throw new InvalidProgramException(message, ex);
55 }
56 else
57 {
58 return FindWindowByProcessId(processId);
59 }
60 }
61 }
62
63 ///
64 /// Get the automation element by automation Id.
65 ///
66 /// Window name
67 /// Control automation Id
68 ///
69 public static AutomationElement FindElementById(int processId, string automationId)
70 {
71 AutomationElement aeForm = FindWindowByProcessId(processId);
72 AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
73 new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
74 return tarFindElement;
75 }
76
77 GridPattern helper
95 }
96}
97
对应的XAML代码如下:
1
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="GridView" Height="426" Width="558">
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
GridView窗体后台代码如下:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Windows;
6using System.Windows.Controls;
7using System.Windows.Data;
8using System.Windows.Documents;
9using System.Windows.Input;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12using System.Windows.Shapes;
13using System.Data.SqlClient;
14using System.Data;
15
16namespace WpfApp
17{
18 ///
19 /// Interaction logic for GridView.xaml
20 ///
21 public partial class GridView : Window
22 {
23 public GridView()
24 {
25 InitializeComponent();
26 getData();
27 }
28 SqlDataAdapter sda;
29 DataTable dt;
30 void getData()
31 {
32 //Northwind database download path:http://download.csdn.net/down/845087/beyondchina123
33 //init sqlconnection
34 SqlConnectionStringBuilder connbuilder = new SqlConnectionStringBuilder();
35 connbuilder.DataSource = ".";//本地服务器
36 connbuilder.IntegratedSecurity = true;//Windows集成验证
37 connbuilder.InitialCatalog = "Northwind";//数据库为Northwind
38 SqlConnection conn = new SqlConnection(connbuilder.ConnectionString);
39 sda = new SqlDataAdapter("select EmployeeID,FirstName,LastName,Address from Employees ", conn);
40 SqlCommandBuilder commbuilder = new SqlCommandBuilder(sda);
41 dt = new DataTable();
42 sda.Fill(dt);
43 listview1.ItemsSource = dt.DefaultView;
44 }
45 }
46}
47
48
本文主要简单介绍了GridPattern以及GridPattern在测试中是使用方法。
使用UI Automation实现自动化测试--4.9 (ScrollPattern)
ScrollPattern
ScrollPattern是用来操作控件的滚动条,目前支持ScrollPattern的控件有ListBox,listView,GridView,TreeView.
ScrollPattern主要方法
- 1. Scroll 水平和垂直滚动内容区域的可见区域滚动, Scroll有两个参数,其类型为ScrollAmount枚举类型。
- 2. ScrollHorizontal 按指定的 ScrollAmount 水平滚动内容区域的当前可见区域滚动。
- 3. ScrollVertical 按指定的 ScrollAmount 垂直滚动内容区域的当前可见区域滚动。
ScrollPattern属性
- VerticallyScrollable 属性用于判定是否可以垂直滚动。
- HorizontallyScrollable 属性用于判定是否可以水平滚动。
- HorizontalScrollPercent 获取当前水平滚动条的位置。
- VerticalScrollPercent 获取当前垂直滚动条的位置。
下面我们通过一个实例来演示自动化测试中如何使用ScrollPattern来测试GridView中滚动条的方法:
1using System;
2using System.Text;
3using System.Diagnostics;
4using System.Threading;
5using System.Windows.Automation;
6
7namespace UIATest
8{
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14 int processId = process.Id;
15 Thread.Sleep(1000);
16
17 ScrollPattern
31
32 }
33
34 ///
35 /// Get the automation elemention of current form.
36 ///
37 /// Process Id
38 ///
39 public static AutomationElement FindWindowByProcessId(int processId)
40 {
41 AutomationElement targetWindow = null;
42 int count = 0;
43 try
44 {
45 Process p = Process.GetProcessById(processId);
46 targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
47 return targetWindow;
48 }
49 catch (Exception ex)
50 {
51 count++;
52 StringBuilder sb = new StringBuilder();
53 string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
54 if (count > 5)
55 {
56 throw new InvalidProgramException(message, ex);
57 }
58 else
59 {
60 return FindWindowByProcessId(processId);
61 }
62 }
63 }
64
65
66 ///
67 /// Get the automation element by automation Id.
68 ///
69 /// Window name
70 /// Control automation Id
71 ///
72 public static AutomationElement FindElementById(int processId, string automationId)
73 {
74 AutomationElement aeForm = FindWindowByProcessId(processId);
75 AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
76 new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
77 return tarFindElement;
78 }
79
80 GetScrollPattern helper
98 }
99}
100
XAML源码:
1
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="GridView" Height="280" Width="467">
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
后台CS源码:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Windows;
6using System.Windows.Controls;
7using System.Windows.Data;
8using System.Windows.Documents;
9using System.Windows.Input;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12using System.Windows.Shapes;
13using System.Data.SqlClient;
14using System.Data;
15
16namespace WpfApp
17{
18 ///
19 /// Interaction logic for GridView.xaml
20 ///
21 public partial class GridView : Window
22 {
23 public GridView()
24 {
25 InitializeComponent();
26 getData();
27 }
28 SqlDataAdapter sda;
29 DataTable dt;
30 void getData()
31 {
32 //init sqlconnection
33 SqlConnectionStringBuilder connbuilder = new SqlConnectionStringBuilder();
34 connbuilder.DataSource = ".";//本地服务器
35 connbuilder.IntegratedSecurity = true;//Windows集成验证
36 connbuilder.InitialCatalog = "TestDB";//数据库为Northwind
37 SqlConnection conn = new SqlConnection(connbuilder.ConnectionString);
38 sda = new SqlDataAdapter("select EmployeeID,FirstName,LastName,Address from Employees ", conn);
39 SqlCommandBuilder commbuilder = new SqlCommandBuilder(sda);
40 //sda.UpdateCommand = commbuilder.GetUpdateCommand();
41 dt = new DataTable();
42 //sda.AcceptChangesDuringUpdate = true;
43 sda.Fill(dt);
44 listview1.ItemsSource = dt.DefaultView;
45 }
46 }
47}
48
49
数据库及数据库表源码:
1USE [master]
2GO
3/****** Object: Database TestDB Script Date: 10/17/2009 16:08:09 ******/
4IF EXISTS (SELECT name FROM sys.databases WHERE name = N'TestDB')
5DROP DATABASE [TestDB]
6CREATE DATABASE TestDB ON PRIMARY
7( NAME = N'TestDB', FILENAME = N'C:\TestDB.mdf' , SIZE = 2688KB , MAXSIZE = UNLIMITED, FILEGROWTH = 80KB )
8 LOG ON
9( NAME = N'TestDB_log', FILENAME = N'C:\TestDB.ldf' , SIZE = 1024KB , MAXSIZE = UNLIMITED, FILEGROWTH = 10%)
10GO
11
12use TestDB
13
14CREATE TABLE [dbo].[Employees](
15 [EmployeeID] [int] IDENTITY(1,1) primary key NOT NULL,
16 [LastName] [varchar](20) NOT NULL,
17 [FirstName] [varchar](10) NOT NULL,
18 [Address] [varchar](60) NULL
19)
20
21GO
22truncate table employees
23declare @i int
24set @i = 1
25while @i<25
26begin
27
28insert into Employees
29(
30 LastName,
31 FirstName,
32 [Address]
33)
34values
35('Kaden'+cast(@i as varchar), 'Kang'+cast(@i as varchar), 'Nanjing, Jiangsu, China'+cast(@i as varchar))
36set @i=@i+1
37end
38
39
本文简单介绍了ScrollPattern以及使用ScrollPattern来操作垂直水平滚动条。