UIAutomation 自动化

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

如下图所示:

UIAutomation 自动化_第1张图片

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
using System.Diagnostics;

  3
using System.Threading;

  4
using System.Windows.Automation.Provider;

  5
using System.Windows.Automation.Text;

  6
using System.Windows.Automation;

  7

  8
namespace UIAutomationTest

  9
{

 10
    class Program

 11
    {

 12
        static void Main(string[] args)

 13
        {

 14
            try

 15
            {

 16
                Console.WriteLine("\nBegin WinForm UIAutomation test run\n");

 17
                // launch Form1 application

 18
                // get refernce to main Form control

 19
                // get references to user controls

 20
                // manipulate application

 21
                // check resulting state and determine pass/fail

 22

 23
                Console.WriteLine("\nBegin WinForm UIAutomation test run\n");

 24
                Console.WriteLine("Launching WinFormTest application");

 25
                //启动被测试的程序

 26
                Process p = Process.Start(@"E:\Project\WinFormTest\WinFormTest\bin\Debug\WinFormTest.exe");

 27

 28
                //自动化根元素

 29
                AutomationElement aeDeskTop = AutomationElement.RootElement;

 30

 31
                Thread.Sleep(2000);

 32
                AutomationElement aeForm = AutomationElement.FromHandle(p.MainWindowHandle);

 33
                //获得对主窗体对象的引用,该对象实际上就是 Form1 应用程序(方法一)

 34
                //if (null == aeForm)

 35
                //{

 36
                //    Console.WriteLine("Can not find the WinFormTest from.");

 37
                //}

 38

 39
                //获得对主窗体对象的引用,该对象实际上就是 Form1 应用程序(方法二)

 40
                int numWaits = 0;

 41
                do

 42
                {

 43
                    Console.WriteLine("Looking for WinFormTest……");

 44
                    //查找第一个自动化元素

 45
                    aeForm = aeDeskTop.FindFirst(TreeScope.Children, new PropertyCondition(

 46
                        AutomationElement.NameProperty, "Form1"));

 47
                    ++numWaits;

 48
                    Thread.Sleep(100);

 49
                } while (null == aeForm && numWaits < 50);

 50
                if (null == aeForm)

 51
                    throw new NullReferenceException("Failed to find WinFormTest.");

 52
                else

 53
                    Console.WriteLine("Found it!");

 54

 55
                Console.WriteLine("Finding all user controls");

 56
                //找到第一次出现的Button控件

 57
                AutomationElement aeButton = aeForm.FindFirst(TreeScope.Children,

 58
                  new PropertyCondition(AutomationElement.NameProperty, "button1"));

 59

 60
                //找到所有的TextBox控件

 61
                AutomationElementCollection aeAllTextBoxes = aeForm.FindAll(TreeScope.Children,

 62
                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));

 63

 64
                // 控件初始化的顺序是先初始化后添加到控件

 65
                // this.Controls.Add(this.textBox3);                  

 66
                // this.Controls.Add(this.textBox2);

 67
                // this.Controls.Add(this.textBox1);

 68

 69
                AutomationElement aeTextBox1 = aeAllTextBoxes[2];

 70
                AutomationElement aeTextBox2 = aeAllTextBoxes[1];

 71
                AutomationElement aeTextBox3 = aeAllTextBoxes[0];

 72

 73
                Console.WriteLine("Settiing input to '30'");

 74
                //通过ValuePattern设置TextBox1的值

 75
                ValuePattern vpTextBox1 = (ValuePattern)aeTextBox1.GetCurrentPattern(ValuePattern.Pattern);

 76
                vpTextBox1.SetValue("30");

 77
                Console.WriteLine("Settiing input to '50'");

 78
                //通过ValuePattern设置TextBox2的值

 79
                ValuePattern vpTextBox2 = (ValuePattern)aeTextBox2.GetCurrentPattern(ValuePattern.Pattern);

 80
                vpTextBox2.SetValue("50");

 81
                Thread.Sleep(1500);

 82
                Console.WriteLine("Clickinig on button1 Button.");

 83
                //通过InvokePattern模拟点击按钮

 84
                InvokePattern ipClickButton1 = (InvokePattern)aeButton.GetCurrentPattern(InvokePattern.Pattern);

 85
                ipClickButton1.Invoke();

 86
                Thread.Sleep(1500);

 87

 88
                //验证计算的结果与预期的结果是否相符合

 89
                Console.WriteLine("Checking textBox3 for '80'");

 90
                TextPattern tpTextBox3 = (TextPattern)aeTextBox3.GetCurrentPattern(TextPattern.Pattern);

 91
                string result = tpTextBox3.DocumentRange.GetText(-1);//获取textbox3中的值

 92
                //获取textbox3中的值

 93
                //string result = (string)aeTextBox2.GetCurrentPropertyValue(ValuePattern.ValueProperty);

 94
                if ("80" == result)

 95
                {

 96
                    Console.WriteLine("Found it.");

 97
                    Console.WriteLine("TTest scenario: *PASS*");

 98
                }

 99
                else

100
                {

101
                    Console.WriteLine("Did not find it.");

102
                    Console.WriteLine("Test scenario: *FAIL*");

103
                }

104

105
                Console.WriteLine("Close application in 5 seconds.");

106
                Thread.Sleep(5000);

107
                //实现关闭被测试程序

108
                WindowPattern wpCloseForm = (WindowPattern)aeForm.GetCurrentPattern(WindowPattern.Pattern);

109
                wpCloseForm.Close();

110

111
                Console.WriteLine("\nEnd test run\n");

112
            }

113
            catch (Exception ex)

114
            {

115
                Console.WriteLine("Fatal error: " + ex.Message);

116
            }

117
        }

118
    }

119
}

120

使用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中有如下几个重要属性:

  1. AutomationIdProperty: 通过AutomationId来查找AutomationElement。
  2. NameProperty:通过控件的Name属性来查找AutomationElement。
  3. ControlType:通过控件的类型来查找AutomationElement
  4. AutomationId: 唯一地标识自动化元素,将其与同级相区分。
  5. Name:  WPF 按钮的Content 属性、Win32 按钮的Caption 属性以及 HTML 图像的ALT 属性都映射到 UI 自动化视图中的同一个属性 Name。

注:PropertyCondition类是用来对相关属性进行条件匹配,在控件树中查找控件时,可以通过最佳匹配来找到相应的控件。

如下代码列出了使用不同的属性来构建PropertyCondition,通过PropertyCondition来查找控件树中的控件.


public class PropertyConditions
    {
        static PropertyCondition propertyCondition;
        /// 
        /// Create PropertyCondition by AutomationId
        /// 

        /// Control AutomationId
        /// Return PropertyCondition instance
        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
        /// Target automation element
        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
        /// DockPattern 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
        /// DockPosition 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。

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, "comboBox1");
            ExpandCollapsePattern currentPattern = GetExpandCollapsePattern(element);
            currentPattern.Expand();
            Thread.Sleep(1000);
            currentPattern.Collapse();
        }
        /// 
        /// Get the automation elemention of current form.
        /// 
        /// Process Id
        /// Target element
        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
        /// Automatin element searched by 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;
        }
        ExpandCollapsePattern helper
    }
}

      以下代码为被测程序的xaml文件:


 1

 2
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

 3
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

 4
    Title="Window1" Height="219" Width="353">

 5
    

 6
        

 7
            kaden

 8
            sam

 9
        

10
    

11

使用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
        /// Target element
        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
        /// Automatin element searched by 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
        /// InvokePattern 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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="219" Width="353">
    
        Button
    


对应的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        /// Target element
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        /// Automatin element searched by automation Id
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设计:


12    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4    Title="Window1" Height="219" Width="353">
5    
6        textBox text
7    

8
9

     本文通过简单的实例介绍了UI Automation中的ValuePattern及其使用方法。

使用UI Automation实现自动化测试--4.5 (WindowPattern)

WindowPattern 控件模式用于支持在传统的 图形用户界面 (GUI) 内提供基于基本窗口的功能的控件。必须实现此控件模式的控件的示例包括顶级应用程序窗口、多文档界面 (MDI) 子窗口、大小可调的拆分窗格控件、模式对话框以及气球状帮助窗口。可以使用WindowPattern来对window进行操作,例如验证window是否激活,是否最大化、最小化、正常模式以及关闭window等。
     下面的代码演示了WindowPattern的使用方法: 


 1
using System;

 2
using System.Text;

 3
using System.Diagnostics;

 4
using System.Threading;

 5
using System.Windows.Automation;

 6

 7
namespace 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 = FindWindowByProcessId(processId);

16
            WindowPattern currentPattern = GetWindowPattern(element);

17
            

18
            //Set window visual state to Maximized

19
            currentPattern.SetWindowVisualState(WindowVisualState.Maximized);

20
            Thread.Sleep(1000);

21

22
            //Set window visual state to Normal

23
            currentPattern.SetWindowVisualState(WindowVisualState.Normal);

24
            Thread.Sleep(1000);

25

26
            //Set window visual state to Minimized

27
            currentPattern.SetWindowVisualState(WindowVisualState.Minimized);

28
            

29
            //Close window

30
            currentPattern.Close();            

31
        }

32

33
        /// 

34
        /// Get the automation elemention of current form.

35
        /// 

36
        /// Process Id

37
        /// Target element

38
        public static AutomationElement FindWindowByProcessId(int processId)

39
        {

40
            AutomationElement targetWindow = null;

41
            int count = 0;

42
            try

43
            {

44
                Process p = Process.GetProcessById(processId);

45
                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);

46
                return targetWindow;

47
            }

48
            catch (Exception ex)

49
            {

50
                count++;

51
                StringBuilder sb = new StringBuilder();

52
                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();

53
                if (count > 5)

54
                {

55
                    throw new InvalidProgramException(message, ex);

56
                }

57
                else

58
                {

59
                    return FindWindowByProcessId(processId);

60
                }

61
            }

62
        }

63

64
        WindowPattern helper

83
    }

84
}

使用UI Automation实现自动化测试--4.6.1 (SelectionItemPattern)

SelectionItemPattern

支持SelectionItemPattern的控件有ListView、ListBox、RadioButton、GridView等。

  1. 1.         SelectionItemPattern的三个重要方法:
  2. 1.         AddToSelection:将当前元素添加到所选项的集合。
  3. 2.         RemoveFromSelection: 从选定项的集合中移除当前元素。
  4. 3.         Select: 取消所有已选中的项,然后选择当前元素。
  5. 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        /// Target element
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        /// Automatin element searched by automation Id
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:


12    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4    Title="Window1" Height="219" Width="353">
5    
6        RadioButton
7    

8
9

    本文简单介绍了SelectionItemPattern以及使用SelectionItemPattern来操作RadioButton。

使用UI Automation实现自动化测试--4.6.2 (SelectItemPattern Demo)

 如下代码演示了使用SelectionItemPattern来实现listview item 的多选操作:


  1
using System;

  2
using System.Text;

  3
using System.Diagnostics;

  4
using System.Threading;

  5
using System.Windows.Automation;

  6

  7
namespace 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
            MutlSelect(new int[] { 0, 1 }, processId, false);

 18
        }

 19

 20
        /// 

 21
        /// Get the automation elemention of current form.

 22
        /// 

 23
        /// Process Id

 24
        /// Target element

 25
        public static AutomationElement FindWindowByProcessId(int processId)

 26
        {

 27
            AutomationElement targetWindow = null;

 28
            int count = 0;

 29
            try

 30
            {

 31
                Process p = Process.GetProcessById(processId);

 32
                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);

 33
                return targetWindow;

 34
            }

 35
            catch (Exception ex)

 36
            {

 37
                count++;

 38
                StringBuilder sb = new StringBuilder();

 39
                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();

 40
                if (count > 5)

 41
                {

 42
                    throw new InvalidProgramException(message, ex);

 43
                }

 44
                else

 45
                {

 46
                    return FindWindowByProcessId(processId);

 47
                }

 48
            }

 49
        }

 50

 51

 52
        /// 

 53
        /// Get the automation element by automation Id.

 54
        /// 

 55
        /// Window name

 56
        /// Control automation Id

 57
        /// Automatin element searched by automation Id

 58
        public static AutomationElement FindElementById(int processId, string automationId)

 59
        {

 60
            AutomationElement aeForm = FindWindowByProcessId(processId);

 61
            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,

 62
            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));

 63
            return tarFindElement;

 64
        }

 65
        

 66
        /// 

 67
        /// Bulk select the list item

 68
        /// 

 69
        /// List item index collection

 70
        /// Application process Id

 71
        /// Is select all or not

 72
        public static void MutlSelect(int[] indexes, int processId, bool isSelectAll)

 73
        {

 74
            AutomationElement targetElement = FindElementById(processId, "listView1");

 75

 76
            AutomationElementCollection rows =

 77
                targetElement.FindAll(TreeScope.Descendants,

 78
                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));

 79

 80
            object multiSelect;

 81

 82
            if (isSelectAll)

 83
            {

 84
                for (int i = 1; i < rows.Count - 1; i++)

 85
                {

 86
                    if (rows[i].TryGetCurrentPattern(SelectionItemPattern.Pattern, out multiSelect))

 87
                    {

 88
                        (multiSelect as SelectionItemPattern).AddToSelection();

 89
                    }

 90
                }

 91
            }

 92
            else

 93
            {

 94
                if (indexes.Length > 0)

 95
                {

 96
                    for (int j = 0; j < indexes.Length; j++)

 97
                    {

 98
                        int tempIndex = indexes[j];

 99
                        if (rows[tempIndex].TryGetCurrentPattern(SelectionItemPattern.Pattern, out multiSelect))

100
                        {

101
                            (multiSelect as SelectionItemPattern).AddToSelection();

102
                        }

103
                    }

104
                }

105
            }

106
        }

107

108
        SelectItemPattern

127
    }

128
}

      如下代码为对应的XAML:


 1

 2
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

 3
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

 4
    Title="Window2" Height="412" Width="585">

 5
    

 6
        

 7
            Kaden

 8
            KangYi

 9
            John

10
        

11
    

12

13

使用UI Automation实现自动化测试--4.7 (TogglePattern)

TogglePattern

支持TogglePattern的控件有CheckBox,TreeView中的button控件等。

  1. 1.       TogglePattern的方法

Toggle方法用于操作可以循环通过的一组状态并在设置后保持某种状态。

  1. 2.       TogglePattern属性

Current属性中的ToggleState有如下三种状态:

  1. 1.         On
  2. 2.         Off
  3. 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        /// Target element
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        /// Automatin element searched by automation Id
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:


12    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4    Title="Window1" Height="219" Width="353">
5    
6        CheckBox
7    

8

使用UI Automation实现自动化测试--4.8 (GridPattern)

GridPattern

支持GridPattern的最常见的控件为GridView, 在WPF中使用ListView和GridView组合即可得到相应的GridView。

GridPattern的方法

GetItem:此方法有两个参数,即DataGrid的Row和Column。

通过GridPattern的GetItem方法可以获取DataGrid中的某个确定的单元格,进而对单元进行操作。

对单元格的操作主要有以下几个方面:

  1. 1.       编辑单元个中的数据。
  2. 2.       获取单元格中的数据。
  3. 3.       获取单元格中嵌套的AutomationElement(一般使用与自定义控件中)。

GridPattern的属性

GridPattern的Current属性中有如下两个属性:

  1. 1.       RowCount属性:GridPattern二维表格的行数。
  2. 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        /// Target element
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        /// Automatin element searched by automation Id
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 2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 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. 1.         Scroll 水平和垂直滚动内容区域的可见区域滚动, Scroll有两个参数,其类型为ScrollAmount枚举类型。
  2. 2.         ScrollHorizontal 按指定的 ScrollAmount 水平滚动内容区域的当前可见区域滚动。
  3. 3.         ScrollVertical 按指定的 ScrollAmount 垂直滚动内容区域的当前可见区域滚动。

ScrollPattern属性

  1. VerticallyScrollable 属性用于判定是否可以垂直滚动。
  2. HorizontallyScrollable 属性用于判定是否可以水平滚动。
  3. HorizontalScrollPercent 获取当前水平滚动条的位置。
  4. 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        /// Target element
 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        /// Automatin element searched by automation Id
 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 2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 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来操作垂直水平滚动条。

你可能感兴趣的:(java,c#,.net,wpf,stream)