关于UI Automation中Cache性能的疑惑

本文探讨了在自动化测试框架中使用缓存机制提高元素查找效率的方法,通过对比带缓存与不带缓存的两种实现,揭示了在访问元素多次后性能提升的显著效果。实验证明,对于频繁访问的元素,使用缓存可以大幅减少查找时间,尤其在处理大量元素的场景下更为有效。

之前花了数周的时间搭了个基于UI Automation的自动化框架。期间发现一个问题,当被测试程序中的element非常多的时候,恰巧要寻找的element位于tree的末端的话,可能性能会比较的低(不知道微软对FindFirst方法有没有做性能上的优化)。于是乎想寻找有没有效率比较高的方法,在MSDN中查询了一下,发现提供了Cache的功能(链接)。后来才发现高效的原理是在进行FindFirst之时将element相应的propertypattern进行cache处理,以后再对elementpropertypatter进行查询的时候会比较高效,而且还特别强调了对与服务器相连的WPF程序特别有效。虽然和我本意有点出入,但是也算个提高效率的技能,研究一下先:

编写了个两个函数,一个采用了cache,另一个没有,功能都是寻找被测试程序上的一个element,然后再得到其property(选择得到其property的结果也类似),来看看其效率到底差多少。为了使其结果更加明显,故采用了循环来进行高次数访问下的效率区别。

class Program

{

        static void Main(string[] args)

        {

            AutomationElement aeDesktop = AutomationElement.RootElement;

            AutomationElement appElement = aeDesktop.FindFirst(TreeScope.Children,

                new PropertyCondition(AutomationElement.AutomationIdProperty, "_RVMainWindow"));

 

            SearchElememtWithoutCache(appElement);

            SearchElementWithCache(appElement);

 

            Console.ReadLine();

        }

 

        static void SearchElememtWithoutCache(AutomationElement appElement)

        {

            Stopwatch stopwatch = new Stopwatch();

            AutomationElement aeName =

                    appElement.FindFirst(TreeScope.Subtree,

                    new PropertyCondition(AutomationElement.AutomationIdProperty, "name"));

            stopwatch.Start();

            string nameID="";

            for (int i = 0; i < 10; i++)

            {

                nameID = aeName.Current.AutomationId;

            }

 

            stopwatch.Stop();

            Console.WriteLine("Without cache used milliseconds: " + stopwatch.ElapsedMilliseconds);

        }

 

        static void SearchElementWithCache(AutomationElement appElement)

        {

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

 

            CacheRequest cacheRequest = new CacheRequest();

            cacheRequest.AutomationElementMode = AutomationElementMode.None;

            cacheRequest.TreeFilter = Automation.ControlViewCondition;

            cacheRequest.Add(AutomationElement.AutomationIdProperty);

 

            AutomationElement aeName = null;

 

            using (cacheRequest.Activate())

            {

                aeName =

                    appElement.FindFirst(TreeScope.Subtree,

                    new PropertyCondition(AutomationElement.AutomationIdProperty, "name"));

            }

 

            stopwatch.Start();

            string nameId="";

            for (int i = 0; i < 10; i++)

            {

                nameId = aeName.Cached.AutomationId;

            }

 

            stopwatch.Stop();

            Console.WriteLine("With cache used milliseconds: " + stopwatch.ElapsedMilliseconds);

 

        }

}

 

运行结果如下:

·         进行10次循环:

Without cache used milliseconds: 2

With cache used milliseconds: 310

·         进行100次循环:

Without cache used milliseconds: 23

With cache used milliseconds: 312

·         进行1000次循环:

Without cache used milliseconds: 252

With cache used milliseconds: 305

·         进行10000次循环:

Without cache used milliseconds: 2430

With cache used milliseconds: 315

结果令我大吃一惊,在elememt被的属性被访问1000次之前,其效率都是差于普通方式访问的,当访问次数达到10000次的时候,其效率的提高的是比较明显的,难道说如果被测试程序element操作次数少于1000次的话,不建议采用cache?不知道事实的真相是不是如此!

根据UIAutomation封装了很多自定义方法 现在只需要实例化之后 直接调用方法即可完成。比如单击某个按钮,现在只需要直接调用ClickElement,非常实用。 ClickElement 单击指定的自动化元素 DisselectAllDataGridRow 不选中所有行 DisselectDataGridRow 不选中特定的某一行 FocusWindow 获取窗口焦点 GetAllElement 获取指定父自动化元素下的所有激活的控件 GetAllElementDetails 获取指定自动化元素下的详细信息包括AutomationID,ControlType以及Name GetAllMenus 获取所有菜单项 GetAllSubMenus 获取某个菜单下的所有子菜单项 GetColumnsFromGridLine 获取指定行的所有列 GetColumnValuesFromGridLine 获取行的每一列数据 GetControlType(AutomationElement) 获取制动自动化元素的控件类型 GetControlType(TypeOfControl) 获取UIAutomation的控件类型 GetDocumentText 获取document控件的值 GetElementByID 获取父自动化元素下指定元素控件ID的引用 GetElementByName 获取父自动化元素下的指定子元素的引用 GetElementsByControlType 获取父自动化元素下的特定类型的所有自动化元素 GetGridLinesFromDataGrid 获取网格控件的全部行元素的引用 GetHeaderFromDataGrid 获取指定网格控件的标题栏引用 GetMenuBar 获取菜单栏控件 GetMenuByName 通过特定的名称去获取菜单UI自动化元素 GetName 获取指定自动化元素的名称 GetSubMenuByName 获取主菜单下的指定子菜单项的引用 GetValue 获取指定自动化元素的值 GetWindowByName(String) 获取desktop下的指定窗口名称的子UI自动化元素 GetWindowByName(String, AutomationElement) 获取特定父UI自动化元素下的制定窗口名称的子UI自动化元素 GetWindowList() 获取当前桌面根下所有的UI自动化元素下 GetWindowList(AutomationElement) 获取特定父UI自动化元素下的所有窗口的名称 RefindMainApplication 重新获取desktop下的指定窗口的自动化元素引用 SelectAllDataGridRow 选中所有行 SelectDataGridRow(AutomationElement) 选中特定的某一行 SelectDataGridRow(AutomationElement, Boolean) 将特定的DateGridRow加入选中项中 SelectValueInComboBox 从下拉框中选中指定值的项 SelectValueInListBox 从列表中选中指定值的项 SetValue 给予指定自动化元素赋值 以上的方法还不是很完善 正在完善中。如果有什么意见和建议,请发送邮件获取 chenxu7601257@qq.com 如果你看了这个帮助文件之后觉得有用的,请发邮件获取,我将把dll文件给你。谢谢。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值