最近由于项目需要,需要做一个自动化测试项目,网上找了很多资料,但完善的资料都很少,做个一个简单的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; } } } }
调试效果如下