Windows UI自動化 WIn32API以及MSAA


   Windows平台的桌面開發技術, 從最原始的Win32 SDK,發展到.NET WinForm,一直到今天的WPF和Silverlight, 發生了翻天覆地的變化,相對應的UI自動化測試技術,也隨之演變。

    微軟UI自動化技術揭秘將分兩個部分介紹Windows平台桌面程序的自動化技術。上篇將介紹從Win32 SDK至今的UI自動化技術演變,下篇將着重介紹最新的UI Automation(UIA)的內部實現和使用技巧。

    

    自動測試是指用一個程序自動地控制另外一個程序,模擬用戶的操作進行測試。通常自動化測試涉及到下面三個步驟:

 

測試源偵測

    測試源偵測是定位測試目標元素的過程。比如要測試Windows附件中的計算器,首先要把計算器窗口和其他程序比如寫字板區分開。進一步測試計算器窗口菜單的時候,需要首先定位菜單條的位置,獲取第二層子菜單等等。簡單地說,自動化測試首先要能夠獲取從桌面開始的整個UI樹結構,定位到特定測試目標。

 

用戶行為模擬

    用戶行為模擬指模擬用戶的輸入,比如鼠標、鍵盤和觸摸筆的操作,中間可能會涉及IME輸入法、組合鍵、特定用戶習慣,比如輸入速度的模擬等。

 

測試目標檢查

    指獲取測試元素的屬性,比如讀取窗口標題, Listbox的子元素, Checkbox的狀態等等,以便進行測試檢查。

 

Win32 SDK和Windows Message

    在.NET問世以前,Windows平台上的UI程序無外乎兩種技術:Win32 Windows SDK 或者DirectX。由於DirectX多用於專業領域如游戲和CAD,本文並不討論。

    無論是MFC,VCL還是VB6,Win32 SDK都是其根本,最終打交道的其實都是HWND和Windows Message。實現上述自動化的三個步驟 無外乎三件法寶,Win32 API,Windows Message和Windows Hook。

    測試程序首先通過 FindWindowEx和EnumWindow遍歷窗口和子窗口, 找到測試元素比如某個按鈕,然后可以通過Windows Message或者API檢查測試目標。比如通過WM_GETTEXT或者GetWindowText讀取窗口標題,通過GetWindowRect讀取按鈕坐標位置等等。對於用戶行為模擬,可以直接通過SendKey API來完成,當然也可以發送WM_CHAR或者WM_KEYDOWN通知等等。

    除此以外,Windows Hook更加豐富了技術的選取。通過Windows Hook,測試人員還可以直接監控、 截取、模擬目標程序的Windows消息,實現更靈活的模擬,檢查甚至錄制的功能。

    Windows Spy++(圖一)雖然不是測試工具,也算是使用這套技術的典型例子。通過Windows Spy++可以定位任意窗口, 讀取窗口屬性,監視窗口消息等等。

spyxx

圖一: Microsoft Spy++

    采用Win32 SDK和Windows Message的優點是直接靈活。由於直接使用Win32 API,沒有額外的學習曲線,遇上問題可以直接參考Win32 SDK解決。使用Message Hook使得測試程序可以靈活實現,直接對Window Message的操作不僅可以把很多情況化繁為簡,還方便test hook的實現。(所謂test hook,是指產品中為了方便測試而專門設計的隱藏功能,該功能對普通用戶不可見,只是為了方便測試。)

    缺點包括以下三個方面:

    使用復雜,實現成本高。Win32 AP的使用上有很多需要特別注意的細節, 比如有的Win32 API不能跨進程工作,有的Windows Message只能發給當前線程所創建的窗口,稍有不慎,就導致測試程序不穩定。

    過於底層,不便使用。為了方便測試用例調用,需要對API進行封裝,增加了實現成本。同時 Win32 API的也使得很多VB程序員不便調用。再者, 不同的開發工具,比如MFC, VCL,以及后來的.NET Framework,在內部實現上對Win32 API有很多細節的處理, 要實現出針對各種情況都通用的測試框架,並非易事。比如, .NET 中的WinForm Control對Win32 HWND的維護是動態的,同一個WinForm Control的HWND在程序的生命周期內是可能發生改變的,這一點對於依賴HWND作為唯一標識的Win32 API就是一個致命傷。

    無法操作自繪窗口。比如打開Excel的工作表,會發現表格中的每一個Cell並沒有對應到HWND上。Excel的cell都是通過代碼繪制,而不是依賴於現成的Win32 Control。這就使得Win32 API對於自繪窗口沒有用武之地。

 

MSAA

    MSAA的全稱是Microsoft Active Accessibility。這是類似DCOM技術。技術模型是這樣的,UI程序可以暴露出一個Interface,方便另一個程序對其進行控制。MSAA技術的初衷是為了方便殘疾人使用Windows 程序。比如盲人看不到窗口,但是盲人可以通過一個USB讀屏器連接到電腦上, 讀屏器通過UI程序暴露出來的這個Interface,就可以獲取程序信息,通過盲文或者其它形式傳遞給盲人。

    MSAA提供了如此方便的功能, UI自動化測試自然可以借用這項技術。MSAA暴露出來的Interface叫做IAccessible。測試程序和目標UI程序互操作流程如下:

    1. 測試程序調用Windows API: AccessibleObjectFromWindow,傳入目標UI程序HWND。

    2. AccessibleObjectFromWindow函數向UI程序發送WM_GETOBJECT消息。

    3. UI程序創建實現了IAccessible的內部類,然后通過LresultFromObject API把IAccessible 接口返回給測試程序。

    4. 測試程序拿到IAccessible接口,開始調用IAccessible接口函數操作測試目標。

    IAccessible接口里面的幾個關鍵函數是:

  • IAccessible::get_accChild/ IAccessible::get_accParent通過這兩個函數,調用者可以瀏覽目標程序的窗口關系樹,定位到UI元素。
  • IAccessible::accLocation/I Accessible::accHitTest讀取和分辨目標元素的屏幕位置。
  • IAccessible::accName/ I Accessible:: accSelect讀取元素的名字,對UI元素進行指定的操作,比如選取Listbox里面的某一項等等。
  • IAccessible::accValue 開發人員可以自定義value屬性的實現。比如針對折線圖控件,開發人員可以在accValue中返回折線的坐標數列。

    MSAA的理念類似於test hook。 通過主動讓UI程序暴露一個接口來讓調用者控制。在具體使用中,測試人員往往是結合MSAA和Win32 API操作,取長補短。一方面對於UI元素豐富的屬性,比如style,鈎選狀態,是否最大化和模擬用戶輸入等,繼續采用Win32 API。另一方面用MSAA的優勢來彌補Win32 API的一些不足,比如:

    由於MSAA有自己的get_accChild方法,使其控件樹關系並不一定要和Win32 HWNDd關系對應一致。對於自繪窗口,雖然說只有一個HWND,但是開發人員可以通過實現IAccessible接口來實現邏輯上的層次關系。比如Excel中就可以通過IAccessible把多個cell的子IAccessible接口暴露給調用者。

    IAccessible的實現是由開發者提供,開發者可以靈活地根據實際情況決定方法的實現。比如前面提到了折線圖控件可以返回坐標數列。對於.NET WinForm, 微軟在Framework中就提供了IAccessible的默認實現,這樣在具體實現中,就可以處理.NET動態維護HWND的細節等等。

    針對MSAA的工具也有很多,比如AccExplorer(圖二)可以像Spy++一樣對指定程序進行控件的樹形瀏覽,檢查MSAA屬性等。

AccExp

圖二: AccExplorer

    如果您是開發人員, 對於unmanaged UI程序的MSAA實現,參考MSDN中關於WM_GETOBJECT的說明返回IAccessible interface就可以了。對於managed程序, 實現方法更簡單, 現成的例子可以參考:

    對於測試程序如何直接獲取並使用IAccessible接口,並非本系列重點,所以並不提供更多介紹。在后面的文章中, 會介紹如何隱含使用IAccessible和MSAA。

    MSAA也有自身的缺點:

    1. 雖然說MSAA基於COM技術, 但IAccessible並不是一個COM標准接口。 比如使用者不需要調用CoInitialize即可使用,也無法通過QueryInterface進一步獲取更多的自定義接口。這局限了MSAA所能提供的功能。

    2. IAccessible接口的定義有缺陷。里面不少方法是可有可無的,但是又缺少一些支持UI自動化的關鍵方法。 比如它提供了accSelect支持控件的選取,但是卻沒有類似accExpand這樣的方法支持樹狀控件的展開等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM