擴充套件 Rational Functional Tester 的物件識別技術
從開發的角度看,GUI 通常都是基於某一 GUI 開發庫(SWT/SWING/AWT),這些庫通常是按照面向物件的方式進行建模的,它將每一個 GUI 元素對映成該庫中某一個類的物件。
從測試的角度看,所有的 GUI 元素,無論基於何種 GUI 庫,都被 RFT 對映成物件,RFT 提供一個物件模型框架管理各種 GUI 元素。
圖 1 是一個典型的基於 SWT 開發的 GUI,對於其中的一個按鈕,在開發者看來,它就是 SWT 庫中 Button 類的一個物件;但是 RFT 並不區分這是 SWT 庫中的按鈕,或者是其他 GUI 庫的按鈕,它都被對映成 RFT 物件模型中 GuiTestObject 物件。
在用 RFT 提供的 Inspector 工具獲取 GUI 元素時,需要用到開發模型。而進行 RFT 指令碼開發時,又需要用到 RFT 物件模型。熟練掌握兩種物件模型,對提高 RFT 自動化測試效率非常有幫助。
基於 RFT 的自動化測試,都會採用 IBM 推薦的 ITCL 框架。在這個框架下,所有的指令碼被劃分為三個層次:物件層,任務層,用例層。物件識別就是在 RFT 的物件模型框架下,得到被測程式的 GUI 物件。它是物件層開發中最核心的任務。
常用的 RFT 的物件識別技術可以分為兩大類:靜態識別與動態識別。動態和靜態方法各有優缺點,靜態方法識別效率高、開發成本比較低,但是指令碼的可維護性比較差;而動態方法剛好相反。
採用常用的物件識別技術,可以識別出大部分的 GUI 元素,但有時也會遇到 RFT 無法識別的 GUI 元素,事實上識別這類用常用物件識別技術無法識別的 GUI 元素佔用了 RFT 指令碼開發的大部分時間。
RFT 中一個非常重要的根介面是 IGraphical 介面,它定義了針對 GUI 元素的所有標準操作(click,doubleclick,drag 等)。另外一個非常重要的根類是 GuiTestObject,它繼承自 TestObject 並實現了 IGraphical 介面。常用物件識別技術中 GUI 元素都是被對映為 GuiTestObject 物件。它們在 RFT 物件模型中的位置如圖 2 所示。靈活運用這些類、介面及其方法,能夠極大地擴充套件 RFT 物件識別的功能。
- 問題描述
使用 RFT 經常聽到的一個謬論就是 RFT 只能測試基於 java 的 GUI 程式,對於 C/C++ 或者 windows 標準控制元件,RFT 無法識別。事實上,RFT 提供了 IWindow 介面用於識別平臺相關的控制元件。
- IWindow 介面介紹
從圖 2 中可以看出,IWindow 介面也繼承自 IGraphical 介面,從這點看,IWindow 介面具有與 GuiTestObject 類似的功能。
使用 IWindow 介面能夠識別平臺相關的 GUI 控制元件,但是其介面函式的具體實現與平臺相關,windows 與 linux 上的實現就不一樣,可以通過下述方法判斷具體的平臺,本文將主要分析 windows 上的應用。
- 典型應用
圖 3 是記事本的“頁面設定”對話方塊,是一個 windows 原始窗體。如何識別這個窗體,並點選“確定”按鈕呢?基於 RFT 的實現方法如下:
確定物件識別的起始點。通常選取最上層窗體作為物件識別的起始點,具體方法如下所示:
這些方法都返回一個 IWindow 介面的陣列,每一個數組元素代表一個頂層視窗,並且這些視窗之間是互相獨立的。
識別符合要求的頂層視窗,即“頁面設定”對話方塊。IWindow 介面提供了兩個方法:getText() 與 getWindowClassName() 來實現。對於窗體,getText() 返回窗體的標題;對於控制元件,getText() 返回控制元件的文字。getWindowClassName() 返回 win32 標準控制元件名。如何知道被測程式的標準控制元件名呢?在 windows 上有許多工具,例如下文中將提到的 AutoIt 以及 Visual Studio 提供的 Spy++。圖 4 是用 AutoIt 得到的 GUI 元素的屬性。
對頂層窗體陣列根據文字值和標準控制元件名進行匹配,則可以識別出符合要求的頂層窗體。這兩個方法均返回字串,為了提高識別的效率,通常對這些字串進行正則表示式匹配。具體用法如下,引數 sCaption 表示窗體的標題,sWindowClassName 表示窗體的 Win32 標準類名。
識別窗體內的控制元件,即“確定”按鈕。以頂層視窗為起點,通過 IWindow 提供的 getChildren() 函式可以得到內嵌在頂層窗體的 GUI 控制元件(如 button,label 等),該方法返回 IWindow 介面的陣列,對陣列元素根據文字值和標準控制元件名進行匹配,即可識別出內嵌的控制元件。識別內嵌控制元件的方法如下,引數 iTopwin 表示頂層窗體,sCtrlText 表示控制元件的文字值,sCtrlClassName 表示控制元件的 Win32 標準類名。
IWindow 還提供了 getOwned() 方法,可以得到出頂層窗體擁有的子窗體(如模式對話方塊等)。
完成點選“頁面設定”窗體中“確定”按鈕的 RFT 指令碼如下。
- 問題描述
在進行 GUI 自動化測試時,一個經常遇到的問題就是如何測試開發者定製的控制元件?通常一組定製的控制元件,是作為一個整體被 RFT 識別出來,你可以對這個整體作一些操作,但是如何識別出每一個具體的定製控制元件呢?可以使用 TestObject 類提供的方法:Invoke 函式。
- Invoke 方法介紹
Invoke 方法類似於 java 中的反射機制,它可以在執行時而不是編譯時呼叫函式。通俗地說,在 RFT 中,它可以根據字串來呼叫相應的函式。這使得不僅可以呼叫某些確定的方法(如 GuiTestObject 的方法),還可以主動查詢定製控制元件本身提供的方法,大大加強了物件識別能力。
- 典型應用
使用 Invoke 函式的一個典型例子就是測試 Notes 8 的 tab 項。Notes 8 的 tab 項是一個定製的 java 控制元件。RFT 會將多個 tab 項識別為一個 GuiTestObject 物件,如何識別出每一個 tab 項呢?並執行關閉 tab 項的操作呢?
首先採用 Object map 方法識別出 RFT 能夠識別出的最小的定製控制元件的集合。如下圖 2 紅色方框所示的 GUI 元素是 RFT 所能識別出的最小的物件。在本例中它被識別為 GuiTestObject 的物件:sTabFolderObject。
圖 5 Notes 8 中定製控制元件
確定需要呼叫的方法。呼叫 Invoke 方法需要事先知道方法的名稱,TestObject 提供了另外一個方法:getMethods 它能夠返回控制元件所有的方法,你可以按照如下的方式呼叫它。
按照這種方式,能夠在控制檯列印該控制元件所有可用的方法,從中分析出需要的方法。在本例中發現 getItems 能夠返回所有的 tab 項。
呼叫 Invoke 方法識別出具體的定製控制元件。完整的用法如下所示,引數 name 表示希望識別的 tab 項的文字值,sTabFolderObject 為上述紅色方框表示的物件。
完成關閉 tab 項操作。利用 Invoke 可以很便捷的操作 GUI 物件,但是一定要避免使用使用者所不能操作的方式來操作控制元件,因為這違背了測試的原則。從 getMethods 返回的方法中發現 dispose 方法也可以關閉 tab 項,但很顯然使用者不能這樣操作,而使用者關閉 tab 項的操作就是點選 tab 項的“X”。因此在 RFT 指令碼中,可以首先得到“X”的座標,然後在該點執行單擊操作。具體的方法如下所示。
- 問題描述
使用 RFT 進行自動化測試時,經常遇到這樣的尷尬,一方面 RFT 在識別某些物件時遇到一些問題,比如無法識別,識別效率低,開發識別指令碼代價很高。另一方面又有大量的第三方 GUI 自動化工具對某些特定的領域有很好的效能。如果能夠結合 RFT 與其他自動化工具,就能夠極大地提高自動化測試的效率,更加適應敏捷開發與測試。
- AutoIt 介紹
AutoIt 是一種在 windows 平臺上,針對 C/C++ 以及 windows 標準控制元件的,免費、開源的自動化管理工具。AutoIt 本身有一種非常簡單的指令碼語言,這種指令碼語言類於 Basic,並且其指令碼可以直接轉化為可執行程式且不依賴於任何庫。事實上,AutoIt 的這些功能,RFT 提供的 IWindow 介面也能夠完成,但 AutoIt 具有更高的效率。
- 典型應用一
仍然以 IWindow 介面中點選“頁面設定”對話方塊中的“確定”按鈕為例。介紹如何結合 RFT 與 AutoIt 完成上述操作。
- 開發 AutoIt 指令碼。AutoIt 對 GUI 物件的識別區分 windows 和 controls。對於 windows 是通過 title/text 方式進行物件識別;對於 controls 是通過 title/text/controlID 方式進行識別。ControlID 是 AutoIt 中特有的概念,它不是一個特定的值,可以是:內部 ID,text,class,instance,classmn 以及它們的組合。在本例中,最終需要識別的物件是“確定”按鈕,同時它又位於“頁面設定”窗體中。具體的 AutoIt 指令碼如下。
- 在 RFT 中呼叫 AutoIt 指令碼。RFT 提供了多種啟動其它程序的方法,其中類 RationalTestScript 提供的 startApp 和 Run 方法比較常用。使用 startApp 需要事先在 IDE 中進行配置,而 Run 方法具有更多的普遍性,具體的呼叫方法如下。
- 典型應用二
在 RFT 中一類經常遇到的問題就是如何處理那些非預期的活動窗體。例如,點選安全網頁上的 link,而這個 link 所指向的卻是一個非安全的網頁,如果瀏覽器對安全性要求較高的話,就會彈出一個對話方塊詢問你是否仍然開啟這個頁面,如果選擇“是”則下次重複這樣的操作將不再會彈出對話方塊進行詢問,否則下次仍然會詢問。因此是否會出現這個窗體取決於是否建立了信任關係,而在指令碼開發時是無法預見的。
採用常用的物件識別技術,其典型的處理方法如下所示。
上述處理方法採用了常用的物件識別技術識別那些非預期的窗體,如果這些窗體無法用常用方法識別,如何來處理這類問題呢?
圖 6 是開啟網頁前,系統彈出的一個對話方塊,它是一個 windows 原始窗體,無法採用常用方法識別(當然可以用 IWindow 來識別),以下結合 RFT 和 AutoIt 來處理。
- 開發 AutoIt 指令碼。AutoIt 指令碼的任務是點選“Security Alert”對話方塊中的“Yes”按鈕。這可以分為兩步,第一步判斷對話方塊是否已經存在;第二步點選“Yes”按鈕。具體的 AutoIt 指令碼如下所示。
- 開發 RFT 指令碼。RFT 指令碼有三個任務,第一是點選安全網頁上的 link 使得“Security Alert”對話框出現。第二是呼叫 AutoIt 指令碼關閉彈出的對話方塊。第三是判斷非安全網頁是否已經開啟。具體的 RFT 指令碼如下所示。
從以上可以看出,相比單純使用 RFT,基於 RFT 與 AutoIt 的混合解決方案需要的指令碼顯著減少,大大提高了指令碼開發效率。當然這種混合解決方案需要你對 AutoIt 有一定的瞭解,增加了學習的負擔,但是一旦掌握,對於提高自動化測試效率是很明顯的。
本文闡述了各種不同的物件識別技術,其中 IWindow 介面用於識別 windows 標準控制元件;Invoke 方法用於識別應用程式定製的 GUI 控制元件;此外還介紹了 windows 平臺上一款優秀的自動化工具 AutoIt 以及如何與 RFT 結合進行自動化測試。將 RFT 常用的物件識別技術與這些特定條件下的物件識別技術相結合,能夠使得 GUI 自動化測試更加敏捷。
轉載:http://www.ibm.com/developerworks/cn/rational/r-cn-extendsrftobj/index.html