zoukankan      html  css  js  c++  java
  • 关于UI Automation框架

    微软提供的UI Automation框架给开发windows平台的自动化测试带来了很大的便利,这里就总结一下相关的代码。

    首先,直接使用UI Automation框架,完成一个NotePad的about窗口中的 “OK” button的点击:

    复制代码
     1 AutomationElement root = AutomationElement.RootElement;
     2 AutomationElement about_notepad_windows = root.FindFirst(
     3     TreeScope.Descendants,
     4     new AndCondition(
     5         new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window),
     6         new PropertyCondition(AutomationElement.NameProperty, "About Notepad")));
     7 if (about_notepad_windows == null)
     8 {
     9     Console.WriteLine("About Notepad window doesn't exist!!");
    10     return;
    11 }
    12 
    13 AutomationElement ok_button = about_notepad_windows.FindFirst(
    14     TreeScope.Children,
    15     new AndCondition(
    16         new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button),
    17         new PropertyCondition(AutomationElement.NameProperty, "OK")));
    18 Object invokePatternObject;
    19 if (ok_button.TryGetCurrentPattern(InvokePattern.Pattern, out invokePatternObject))
    20 {
    21     (invokePatternObject as InvokePattern).Invoke();
    22 }
    复制代码

    好吧,上面是面向过程的代码,不利于复用,那么让我们来将其抽象成类,

    首先定义一个基类UIAControl,它包含有搜索的根节点searchRoot,搜索范围searchScope和条件searchConditions,使用这三个对象来搜索一个AutomationElement对象并将其赋给innerElement,由于默认使用的是AndCondition来关联所有传入的condition对象,所以将CombineCondition方法设为虚方法,以便如果有子类想要使用其他关联条件处理condition的时候可以覆盖:

    复制代码
      1 public abstract class UIAControl
      2 {
      3     private UIAControl searchRoot;
      4     private TreeScope searchScope;
      5     private List<Condition> searchConditions;
      6 
      7     protected void AddSearchCondition(Condition condition)
      8     {
      9         this.searchConditions.Add(condition);
     10     }
     11 
     12     public UIAControl()
     13     {
     14         searchConditions = new List<Condition>();
     15         searchScope = TreeScope.Descendants;
     16     }
     17 
     18     public UIAControl(UIAControl searchRoot)
     19         : this()
     20     {
     21         this.searchRoot = searchRoot;
     22     }
     23 
     24     public UIAControl(IntPtr hwnd)
     25         : this()
     26     {
     27         searchConditions.Add(PropertyConditionFactory.GetHandleCondition(hwnd));
     28     }
     29 
     30     public AutomationElement.AutomationElementInformation? ControlInformation
     31     {
     32         get
     33         {
     34             if (Exists())
     35             {
     36                 return InnerElement.Current;
     37             }
     38             return null;
     39         }
     40     }
     41 
     42     private AutomationElement innerElement;
     43     public AutomationElement InnerElement
     44     {
     45         get
     46         {
     47             if (innerElement == null)
     48             {
     49                 innerElement = SearchElement();
     50             }
     51             return innerElement;
     52         }
     53     }
     54 
     55     protected virtual AutomationElement SearchElement()
     56     {
     57         AutomationElement ele = null;
     58         if (searchRoot == null)
     59         {
     60             ele = AutomationElement.RootElement;
     61         }
     62         else
     63         {
     64             ele = searchRoot.InnerElement;
     65         }
     66 
     67         if (ele == null || 0 == searchConditions.Count)
     68         {
     69             return ele;
     70         }
     71         else
     72         {
     73             Condition conditions = CombineAllConditions();
     74             try
     75             {
     76                 return ele.FindFirst(searchScope, conditions);
     77             }
     78             catch(Exception ex)
     79             {
     80                 Console.WriteLine("Getting exception when searching element: " + ex.Message);
     81                 return null;
     82             }
     83         }
     84     }
     85 
     86     //Can override this method to return other type conditions, default will return AndCondition
     87     protected virtual Condition CombineAllConditions()
     88     {
     89         if (searchConditions.Count > 1)
     90         {
     91             return new AndCondition(searchConditions.ToArray());
     92         }
     93         else if (searchConditions.Count == 1)
     94         {
     95             return searchConditions.First();
     96         }
     97         else
     98         {
     99             return null;
    100         }
    101 
    102     }
    103 
    104     public virtual bool Exists()
    105     {
    106         //Before checking existence, set innerElement to null to trigger fresh search.
    107         return null != SearchElement();
    108     }
    109 
    110     public bool WaitTillExist(int timeout, int interval = 2000)
    111     {
    112         Stopwatch stopwatch = new Stopwatch();
    113         stopwatch.Start();
    114         while (stopwatch.ElapsedMilliseconds < timeout)
    115         {
    116             if (this.Exists())
    117             {
    118                 return true;
    119             }
    120 
    121             Thread.Sleep(interval);
    122         }
    123 
    124         return false;
    125     }
    126 
    127     protected bool CallPattern<T>(T pattern, Action<T> action) where T : BasePattern
    128     {
    129         if (pattern != null)
    130         {
    131             try
    132             {
    133                 action(pattern);
    134                 return true;
    135             }
    136             catch (Exception ex)
    137             {
    138                 Console.WriteLine(ex.Message);
    139             }
    140         }
    141         return false;
    142     }
    143 
    144     protected T GetPattern<T>() where T : BasePattern
    145     {
    146         var ele = InnerElement;
    147         if (ele != null)
    148         {
    149             try
    150             {
    151                 var patternIdentifier = (AutomationPattern)(typeof(T).GetField("Pattern").GetValue(null));
    152                 return ele.GetCurrentPattern(patternIdentifier) as T;
    153             }
    154             catch (Exception ex)
    155             {
    156                 Console.WriteLine(ex.Message);
    157             }
    158         }
    159         return null;
    160     }
    161 
    162     public bool Invoke()
    163     {
    164         return CallPattern(GetPattern<InvokePattern>(), (pattern) => pattern.Invoke());
    165     }
    166 }
    复制代码

    之后,就可以定义其他控件类型了,下面定义了一个button的对象,只有一个click方法:

    复制代码
     1     public class UIAButton : UIAControl
     2     {
     3         public UIAButton(UIAControl root, string name)
     4             : base(root)
     5         {
     6             AddSearchCondition(PropertyConditionFactory.GetNameCondition(name));
     7             AddSearchCondition(PropertyConditionFactory.GetControlTypeCondition(ControlType.Button));
     8         }
     9 
    10         public void Click()
    11         {
    12             this.Invoke();
    13         }
    14     }
    复制代码

    再定义一个window对象:

    复制代码
     1     public class UIAWindow : UIAControl
     2     {
     3         public UIAWindow(string name)
     4         {
     5             AddSearchCondition(PropertyConditionFactory.GetNameCondition(name));
     6             AddSearchCondition(PropertyConditionFactory.GetControlTypeCondition(ControlType.Window));
     7         }
     8 
     9         public bool Close()
    10         {
    11             return CallPattern(GetPattern<WindowPattern>(), (pattern) => pattern.Close());
    12         }
    13 
    14         public bool Maximize()
    15         {
    16             return CallPattern(GetPattern<WindowPattern>(), (pattern) => pattern.SetWindowVisualState(WindowVisualState.Maximized));
    17         }
    18 
    19         public bool Minimize()
    20         {
    21             return CallPattern(GetPattern<WindowPattern>(), (pattern) => pattern.SetWindowVisualState(WindowVisualState.Minimized));
    22         }
    23 
    24         public bool Resize(int width, int height)
    25         {
    26             return CallPattern(GetPattern<TransformPattern>(), (pattern) => pattern.Resize(width, height));
    27         }
    28     }
    复制代码

    最后,使用上面两个控件类型来完成Ok按钮的点击:

    复制代码
    1 UIAWindow windows = new UIAWindow("About Notepad");
    2 UIAButton ok_button = new UIAButton(windows, "OK");
    3 if (windows.WaitTillExist(3000))
    4 {
    5     ok_button.Click();
    6 }
    复制代码

    当然,如果是稍微上点规模的项目,就需要利用这些控件抽象出一个对应产品功能的produc类了。

    如果不想从头写起的话,可以看看开源工具White, 一个优秀的基于UI Automation的测试框架。

  • 相关阅读:
    JID 2.0 RC4 发布,高性能的 Java 序列化库
    FBReaderJ 1.6.3 发布,Android 电子书阅读器
    Arquillian 1.0.3.Final 发布,单元测试框架
    JavaScript 的宏扩展 Sweet.js
    Hypertable 0.9.6.5 发布,分布式数据库
    JRuby 1.7.0 发布,默认使用 Ruby 1.9 模式
    httppp 1.4.0 发布,HTTP响应时间监控
    Redis 2.6.0 正式版发布,高性能K/V服务器
    OfficeFloor 2.5.0 发布,IoC 框架
    XWiki 4.3 首个里程碑发布
  • 原文地址:https://www.cnblogs.com/soundcode/p/15406375.html
Copyright © 2011-2022 走看看