Luouy~羽林
学问如逆水行舟,不进则退; 有知识的人不实践,等于一只蜜蜂不酿蜜; 我们可以由读书而收集知识,但必须利用思考把糠和谷子分开

最近由于项目需要,需要做一个自动化测试项目,网上找了很多资料,但完善的资料都很少,做个一个简单的UI Automation方面的知识笔记

UIA 自动化树概述

UI 自动化树中有一个表示当前桌面的根元素 (RootElement),该元素的子元素表示应用程序窗口。 其中的每个子元素都可以包含表示 UI 各个部分(如菜单、按钮、工具栏和列表框)的元素。 这些子元素又可以包含列表项之类的元素。

UI 自动化树的结构不固定,由于它可能包含数千个元素,因此它很少全部显示出来。 您可以根据需要生成树的某些部分,当您添加、移动或移除元素时,树也会进行更改。

UI 自动化提供程序通过实现片段(由一个通常承载在窗口中的根元素和一个子树组成)中各项之间的导航来支持 UI 自动化树。 但是,提供程序并不参与控件之间的导航。 控件之间的导航是由 UI 自动化核心借助于默认窗口提供程序中的信息来管理的。

  

UIA的架构图

做一个例子

1. 在服务端由UIAutomationProvider.dll和UIAutomationTypes.dll提供。

     2. 在客户端由UIAutomationClient.dll和UIAutomationTypes.dll提供。

     3. UIAutomationCore.dll为UI自动化的核心部分,负责Server端和Client端的交互。

     4. UIAUtomationClientSideProvides.dll为客户端程序提供自动化支持。

新建个解决方案

我这里是添加一了个控制台项目和winF项目,为方便用控制台调用调试程序

可以添加下面程序集

        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();
        }

 控制台调用程序如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;

namespace ConsoleApplication.UIAutomation
{
    class Program
    {
        
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("\nBegin WinForm UIAutomation test run\n");
                Process p = Process.Start(@"F:\UIAutomationTest\WindowsFormsApplication.UIAutomation\bin\Debug\WindowsFormsApplication.UIAutomation.exe");
                AutomationElement aeDeskTop = AutomationElement.RootElement;
                Thread.Sleep(2000);

                AutomationElement aeForm = AutomationElement.FromHandle(p.MainWindowHandle);
                //获得对主窗体对象的引用,该对象实际上就是 Form1 应用程序(方法一)
                //if (null == aeForm)
                //{
                //    Console.WriteLine("Can not find the WinFormTest from.");
                 //}
            
                 //获得对主窗体对象的引用,该对象实际上就是 Form1 应用程序(方法二)
                 int numWaits = 0;
                 do
                 {
                     Console.WriteLine("Looking for WinFormTest……");
                     //查找第一个自动化元素
                     aeForm = aeDeskTop.FindFirst(TreeScope.Children, new PropertyCondition(
                         AutomationElement.NameProperty, "WinForm1"));
                     ++numWaits;
                     Thread.Sleep(100);
                 } while (null == aeForm && numWaits < 50);
                 if (null == aeForm)
                     throw new NullReferenceException("Failed to find WinFormTest.");
                 else
                     Console.WriteLine("Found it!");
 
                 Console.WriteLine("Finding all user controls");
                 //找到第一次出现的Button控件
                 AutomationElement aeButton = aeForm.FindFirst(TreeScope.Children,
                  new PropertyCondition(AutomationElement.NameProperty, "button1"));
 
                 //找到所有的TextBox控件
                 AutomationElementCollection aeAllTextBoxes = aeForm.FindAll(TreeScope.Children,
                     new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
 
                 // 控件初始化的顺序是先初始化后添加到控件
                 // this.Controls.Add(this.textBox3);                  
                 // this.Controls.Add(this.textBox2);
                 // this.Controls.Add(this.textBox1);
 
                 AutomationElement aeTextBox1 = aeAllTextBoxes[2];
                 AutomationElement aeTextBox2 = aeAllTextBoxes[1];
                 AutomationElement aeTextBox3 = aeAllTextBoxes[0];
 
                Console.WriteLine("Settiing input to '20'");
                 //通过ValuePattern设置TextBox1的值
                 ValuePattern vpTextBox1 = (ValuePattern)aeTextBox1.GetCurrentPattern(ValuePattern.Pattern);
                 vpTextBox1.SetValue("20");
                 Console.WriteLine("Settiing input to '30'");
                 //通过ValuePattern设置TextBox2的值
                ValuePattern vpTextBox2 = (ValuePattern)aeTextBox2.GetCurrentPattern(ValuePattern.Pattern);
                vpTextBox2.SetValue("30");
                 Thread.Sleep(1500);
                 Console.WriteLine("Clickinig on button1 Button.");
                 //通过InvokePattern模拟点击按钮
                 InvokePattern ipClickButton1 = (InvokePattern)aeButton.GetCurrentPattern(InvokePattern.Pattern);
                ipClickButton1.Invoke();
                 Thread.Sleep(1500);
 
                 //验证计算的结果与预期的结果是否相符合
                 Console.WriteLine("Checking textBox3 for '50'");
                 TextPattern tpTextBox3 = (TextPattern)aeTextBox3.GetCurrentPattern(TextPattern.Pattern);
                 string result = tpTextBox3.DocumentRange.GetText(-1);//获取textbox3中的值
                
                 if ("50" == result)
                 {
                     Console.WriteLine("Found it.");
                     Console.WriteLine("TTest scenario: *PASS*");
                 }
                 else
                {
                    Console.WriteLine("Did not find it.");
                    Console.WriteLine("Test scenario: *FAIL*");
                }

                Console.WriteLine("Close application in 5 seconds.");
                Thread.Sleep(5000);
                //实现关闭被测试程序
                WindowPattern wpCloseForm = (WindowPattern)aeForm.GetCurrentPattern(WindowPattern.Pattern);
                wpCloseForm.Close();

                Console.WriteLine("\nEnd test run\n");
            }
            catch (Exception)
            {
                
                throw;
            }
        }
    }
}

 调试效果如下

 

posted on 2014-10-23 15:21  羽林.Luouy  阅读(2737)  评论(0)    收藏  举报