2012-07-16 65 views
0

我想在編碼UI測試中選擇一個樹項目,但我不知道整個層次結構。當我不知道確切樹層次結構時搜索樹項目

實施例:

  • MSSQL連接
      • 未知

有沒有一種方法來搜索這個名字的樹項目,並指定它是如此的多層次深,不用給出完整的路徑?

它看起來不像任何搜索配置屬性會這樣做。

+0

理論上智能搜索會找到它,但在更大的樹它很可能將首次出(如果不知道是根本不同的,可能忽略它)。有一個MaxDepth搜索屬性可能有助於減少錯誤搜索路徑的數量,假設您知道它始終會深入X控件。 – stoj 2012-07-17 11:53:36

回答

1

如果名字是樹中的唯一的,那麼你可以使用PInvoke的,你就不會需要指定深度:

public static List<IntPtr> GetChildWindows(IntPtr parent) 
    { 
     var result = new List<IntPtr>(); 
     var listHandle = GCHandle.Alloc(result); 
     try 
     { 
      var childProc = new User32.EnumWindowsProc(EnumWindow); 
      User32.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); 
     } 
     finally 
     { 
      if (listHandle.IsAllocated) 
       listHandle.Free(); 
     } 
     return result; 
    } 

    private static bool EnumWindow(IntPtr handle, IntPtr pointer) 
    { 
     var gch = GCHandle.FromIntPtr(pointer); 
     var list = gch.Target as List<IntPtr>; 
     if (list == null) 
     { 
      throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); 
     } 
     list.Add(handle); 
     // Modify this to check to see if you want to cancel the operation, then return a null here 
     return true; 
    } 

    public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); 

    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    public static extern bool EnumChildWindows(IntPtr window, EnumWindowsProc callback, IntPtr i); 

    // sample usage: 
    public void findWindowUser32() 
    { 
     foreach (IntPtr child in GetChildWindows(User32.FindWindow(null, "Untitled - Notepad"))) 
     { 
      StringBuilder sb = new StringBuilder(100); 
      User32.GetClassName(child, sb, sb.Capacity); 

      if (sb.ToString() == "Edit") 
      { 
       uint wparam = 0 << 29 | 0; 
       User32.PostMessage(child, WindowsConstants.WM_KEYDOWN, (IntPtr)Keys.H, (IntPtr)wparam); 
      } 
     } 
    } 
+0

+1以查看問題的不同方式。使用PInvoke比較使用內置測試框架的速度如何? – stoj 2012-07-23 12:02:26

+0

有趣的你應該問。性能原來是我喜歡這個解決方案的原因之一。性能要好得多,很可能是因爲GetChildWindows調用只收集窗口句柄。額外的獲取名稱(GetClassName)的調用也不會增加很多開銷。使用UIAutomation類並使用TreeScope設置爲Descendants來調用GetChildren也行得通,但收集的數據更多,速度也更慢。 – chrismead 2012-07-23 14:33:57

+0

注意:我認爲CodedUI使用MSAA,UIAutomation類以及可能更多的技術。 – chrismead 2012-07-23 14:34:56

0

當你的控制是在UI映射中,也許是完整的層次被使用,例如

MSSQL連接 -tables --Unknown1 ---姓

導致4映射的控制。

您可以手動編輯uimap .xml文件,小心刪除-Unknown1元素,並確保關閉MatchExactHierarchy。 這樣,搜索將最初失敗,繼續使用啓發式查找比直接的孩子更深的樹中的元素,並應該找到你的控制。

0
public static UITestControl GetTreeItem(UITestControl TreeControl, string ItemName, bool ContainsTrue = true) 
    { 
     AutomationElement tree = AutomationElement.FromHandle(TreeControl.WindowHandle); 
     System.Windows.Automation.ControlType controlType = tree.Current.ControlType; 
     //Get collection of tree nodes. 
     AutomationElementCollection treeNodeCollection = null; 
     treeNodeCollection = tree.FindAll(TreeScope.Descendants, 
       new System.Windows.Automation.PropertyCondition(AutomationElement.ControlTypeProperty, 
         System.Windows.Automation.ControlType.TreeItem)); 
     UITestControl ReqTreeItem = new UITestControl(); 
     foreach (AutomationElement item in treeNodeCollection) 
     { 
      if ((item.Current.Name == ItemName) && (!ContainsTrue)) 
      { 
       ReqTreeItem = UITestControlFactory.FromNativeElement(item, "UIA"); 
       break; 
      } 
      if ((item.Current.Name.Contains(ItemName)) && (ContainsTrue)) 
      { 
       ReqTreeItem = UITestControlFactory.FromNativeElement(item, "UIA"); 
       break; 
      } 
     } 
     return ReqTreeItem; 
    }