• UIAutomation调用计算器模拟自动执行


    UIAutomation和WPF

        UIAutomation是微软从Windows Vista开始推出的一套全新UI自动化测试技术, 简称UIA。在最新的Windows SDK中,UIA和MSAA等其它支持UI自动化技术的组件放在一起发布,叫做Windows Automation API。

        和前面的介绍相比,我倾向于认为UIA是一项自动化测试“技术”,而MSAA和Win32 API只是实现自动化测试的两种“方法”。这里区分“技术”和 “方法”的原因是, 一项“技术”往往有独立的模型,体贴的开发接口,用来专门解决某一类的问题,同时允许不同的实现细节。UIA可以被看作“技术”,是因为:

        UIA定义了全新的、针对UI自动化的接口和模式。 分别是支持对UI元素进行遍历和条件化查询的TreeWalker/FindAll。定义了读写UI元素属性的UIA Property, 包括Name、 ID、Type、ClassName、Location、 Visibility等等。定义了UI元素行为的UIA Pattern, 比如Select、Expand、Resize、 Check、Value等等。 还引入了UIA Event接口,可以让测试程序在某些事件发生后得到通知,比如新窗口打开事件等。 

        以往的Win32和MSAA 设计出发点并不是为解决UI自动化。Win32旨在提供的通用开发接口, MSAA旨在提供程序的多种访问方式。相反,UIA的设计目的,以及新引入的模式和接口都完全是针对UI自动化测试的。

        在后面的文章中我们会详细分析UIA的内部实现。可以看到,UIA这一套接口和模式,可以在不同平台,不同开发工具中实现和使用。其内部实现方式也因地制宜, 前后的兼容性都照顾得很好。 同时,UIA提供了托管的和非托管两种API,这些都是Win32和MSAA无法比拟的。

    UIAutomtion中主要用AutomationElement 类来 表示 UI 自动化目录树中的一个 UI 自动化元素,并包含由 UI 自动化客户端应用程序用作标识符的值。

     

    添加UIAutomation

    在reference中添加UIAutomationClient,UIAutomationTypes,UIAutomationProvider 和UIAutomationClientsideProviders。

    (Donet 3.0以上的项目中才有)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Automation;
    using System.Windows;
    namespace ConsoleApplication2
    {
        class Cal
        {
            AutomationElement calcWindow = null;
            string resultTextAutoId = "150";
            string btn5AutoId = "135";
            string btn3 = "133";
            string btn2 = "132";
            string btnPlus = "93";
            string btnSub = "94";
            string btnEqual = "121";
            static void Main(string[] args)
            {
                Cal autoClient = new Cal();
                //创建新窗口打开事件的回调,只有等计算器窗口打开后,测试开始执行
                AutomationEventHandler eventHandler = new AutomationEventHandler(autoClient.OnWindowOpenOrClose);
                //把事件挂接在桌面根元素,开始监听
                Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, eventHandler);
                //启动计算器程序,当计算器窗口打开后,新窗口事件得到触发
                System.Diagnostics.Process.Start("calc.exe");
                Console.ReadLine();
            }
            void OnWindowOpenOrClose(object src, AutomationEventArgs e)
            {
                if (e.EventId != WindowPattern.WindowOpenedEvent)
                {
                    return;
                }
                AutomationElement sourceElement;
                try
                {
                    sourceElement = src as AutomationElement;
                    //监察印发新窗口打开事件的窗口是否是计算器
                    //在正式代码中,为了支持本地化测试,字符串应该从资源文件中读取
                    if (sourceElement.Current.Name == "计算器")
                    {
                        calcWindow = sourceElement;
                    }
                }
                catch (ElementNotAvailableException)
                {
    
                    return;
                }
                //开始执行测试
                ExecuteTest();
            }
    
            private void ExecuteTest()
            {
                //执行3+5-2
                //调用函数执行按钮点击
                ExecuteButtonInvoke(btn3);
                ExecuteButtonInvoke(btnPlus);
                ExecuteButtonInvoke(btn5AutoId);
                ExecuteButtonInvoke(btnSub);
                ExecuteButtonInvoke(btn2);
                ExecuteButtonInvoke(btnEqual);
                //调用getcurrentresult函数,获取计算器输出窗口的值
                if (GetCurrentResult() == "6")
                {
                    Console.WriteLine("execute pass!");
                    return;
                }
                Console.WriteLine("execute faile");
            }
            //调用函数执行按钮点击
            private void ExecuteButtonInvoke(string automationId)
            { 
                //创建捕获按钮条件。该条件中有两个判断
                //分别判断automationid是否为指定字符串
                //以及控件类型是否为按钮
                System.Windows.Automation.Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.AutomationIdProperty,automationId),
                    new PropertyCondition(AutomationElement.ControlTypeProperty,ControlType.Button));
                AutomationElement btn = calcWindow.FindFirst(TreeScope.Descendants,conditions); 
                //获取按钮的invokepattern接口
                InvokePattern invokeptn = (InvokePattern)btn.GetCurrentPattern(InvokePattern.Pattern);
                //调用invoke接口,完成按钮点击
                invokeptn.Invoke();
            }
            private string GetCurrentResult()
            {
                System.Windows.Automation.Condition conditions = 
                    new AndCondition(new PropertyCondition(AutomationElement.AutomationIdProperty,resultTextAutoId),
                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text));
                AutomationElement btn = calcWindow.FindFirst(TreeScope.Descendants, conditions);
                //得去text控件的名字,改名字就是输出字符串
                return btn.Current.Name;
            }
    
        }
    }
  • 相关阅读:
    Markdown语法
    window环境下获取python安装的路径
    JS 获取当天所在月的第一天的日期,最后一天日期,所在周的每天的日期,时间,所在每月日期,时间的计算
    Vue中父组件向子组件echarts传值问题
    echarts修改X、 Y坐标轴字体的颜色
    Ultibo--树莓派嵌入式系统开发工具
    mORMot使用synDBDataSet时字段类型不正确引起的问题
    UNIGUI接收普通消息和被动回复用户消息
    unigui验证微信服务器的有效性
    unigui不是单个网页相应的链接,而是整体Web Application,如何把webApp的子功能映射到微信公众号菜单?
  • 原文地址:https://www.cnblogs.com/zhanying/p/4722446.html
Copyright © 2020-2023  润新知