摘 要: 分析了錄制回放技術的基本原理和缺陷,運用WIN32API和.NET反射機制,設計了一個改進的輕量級GUI自動化測試框架,解決了當前測試自動化中出現的一些棘手問題。
關鍵詞: GUI;自動化測試;反射
軟件測試是保證軟件質量的有效手段。目前,在GUI自動化測試中,很多軟件體系都采用錄制回放技術。這種技術要求測試者通過鼠標和鍵盤的點擊進行工作,腳本記錄事件,然后以自動化測試的方式進行回放。記錄下來的測試腳本必須經過編輯和調試之后插入驗證和檢查點。產生的腳本通常是硬編碼,需要測試人員對腳本進行編輯以及參數化操作。同時,界面元素屬性的任何變化都會影響腳本的運行,有時甚至需要重新錄制腳本。
1 .NET中的反射機制
通常,應用程序(包括桌面程序和Web應用)都由一些基本的界面控件組成,所有的軟件指令都是通過控件以事件或消息的形式傳遞給后臺處理。GUI自動化測試的本質是對GUI中的控件元素提供編程手段[2]。在基于GUI對象識別和控制的自動化測試工具中,過去一直依賴于Windows API函數的調用。而隨著新的編程語言和平臺的出現,涌現了很多新的語言特性,這些語言特性可用于自動化測試工具的設計,例如反射機制就是其中一項技術。
反射(Reflection)是.NET中的重要機制,通過反射可以在運行時獲得.NET中每一個類型(包括類、結構、委托、接口和枚舉等)的成員,包括方法、屬性、事件及構造函數等,還可以獲得每個成員的名稱、限定符和參數等。如果獲得了構造函數的信息,即可直接創建對象,即使這個對象的類型在編譯時還不知道。程序集包含模塊,而模塊包含類型,類型又包含成員,反射則提供了封裝程序集、模塊和類型的對象。可以使用反射動態地創建類型的實例,將類型綁定到現有對象或從現有對象中獲取類型,然后調用類型的方法或訪問其字段和屬性[3]。
2 框架的整體設計
自動化測試框架的搭建基本上占了整個自動化測試工作量的40%,是自動化測試實施的一個重要組成部分。軟件自動化框架從本質看是一系列的策略思想、規范文件和代碼的集合。本文提出一種改進的輕量級的GUI自動化測試框架,該框架可以幫助用戶避免當前測試工具出現的缺陷。此框架將具備以下五個特性:GUI控件自動搜索、自動生成和執行測試腳本、基于數據驅動的原則、測試的自動驗證、使用編程語言開發。框架的整體設計如圖1所示。從圖1可以看出,該框架讓測試人員從繁重的錄制工作中解放出來,將更多的時間和精力集中在測試用例的設計中。
3 框架具體開發
3.1 加載被測試程序
為了測試GUI應用程序,必須在測試工具中運行被測程序使兩個程序交互。使用Assembly定義和加載程序集,加載在程序集清單中列出模塊,并從此程序集中查找類型,創建該類型的實例。為了使這兩個應用程序實現交互,必須通過多線程機制實現。下面是通過反射加載被測程序的核心代碼[4]:
Assembly asm=Assembly.LoadFrom(path);
Type t1=asm.GetType(formName);
testForm=(Form)asmCreateInstance(t1.FullName);
ParameterizedThreadStart pt=new ParameterizedThreadStart(AppRun);
Thread thread=new Thread(pt);
thread.Start(testForm);
private void AppRun(Form theForm)
{
Application.Run(theForm);
}
3.2 GUI控件搜索
大部分自動化功能測試工具,尤其是商業的測試工具,都是基于GUI對象識別技術設計的。基本思想是每個基于窗體的控件都是一個窗體,每個控件或窗體都有一個句柄來進行訪問、操作和檢查。
實現GUI測試自動化的困難之一是測試工具并不知道被測程序中存在哪些GUI部件。錄制回放工具使用手工錄制過程暫時解決了這一問題。Win32 API中封裝了很多可用于自動化測試編程的函數,這些函數可在編程語言進行調用,實現自動化測試編程。本文的自動化GUI測試工具將采用Win32 API對被測程序進行自動、系統、全面的控件搜索。實現該搜索將用到Win32 API中封裝的可用于自動化測試編程的函數,包括:GetWindowRect、mouse_event、GetCursorPos和WindowFromPoint函數等。GetWindowRect函數返回指定窗口的邊框矩形的尺寸。該尺寸以相對于屏幕坐標左上角的屏幕坐標給出。通過使用這個函數可以計算出窗口的寬度和高度。mouse_event函數能模擬鼠標擊鍵和鼠標動作。GetCursorPos函數檢取光標的位置,并以屏幕坐標來表示。使用WindowFromPoint函數能獲得包含指定點的控件的句柄。一旦得到了窗口的句柄,就能得到控件的文本、類名以及父窗口的句柄。為了對界面進行徹底的控件搜索,該框架將使用嵌套循環,從界面的左上角到界面的右下角依次移動鼠標進行控件識別,并將結果保存到對象庫中[5]。
該模塊實現的偽代碼如下:
RECT rt=new RECT();
GetWindowRect(iHandle,ref rt);
width=rt.Right-rt.Left; //得到界面的寬度
height=rt.Bottom-rt.Top; //得到高度
step=8; //鼠標每次移動的像素
for (int x=0;x<width;x+=step)
{
for (int y=0;y<height;y+=step)
{
mouse_event(); //移動鼠標到相應的坐標
GetCursorPos(); //得到坐標點處的光標
WindowFromPointGet(); //得到此處的控件句柄
GetWindowText(); //得到窗體的文本
GetClassName(); //得到控件的類別
GetParent(); //得到父窗體的句柄
if (the handle does not exist in object repository)
then save the infomation.
}
}
通過對界面的徹底搜索,可以得出控件的句柄、文本、類名、父窗體的句柄以及GUI控件間的層次關系。
3.3 生成測試用例
實現GUI測試自動化的另一個問題是測試工具不能按事件發生的順序來選擇和操作控件。傳統的測試工具通過錄制的方法記錄程序運行的順序,但是這種機制存在很多限制。本文設計的自動化測試框架的思路是經過界面控件的徹底搜索后,控件的詳細信息會保持到對象庫中。此時,測試人員可以通過測試用例的輸入/輸出模塊來編寫測試用例。該模塊是一個可視化編輯器。測試用例編輯器從對象庫中導入對象信息,該模塊根據測試用例設計人員的操作順序自動產生事件的順序并將測試步驟保存到XML文件中。按事件發生的順序存儲的相關事件可以形成一個測試場景。測試用例編寫者可以對產生的測試場景進行編輯,改變測試步驟的順序或者添加更多的事件。測試運行模塊將會從XML文件中讀取測試用例,按事件的順序執行相應的操作。
3.4 執行并驗證測試
基于數據驅動的原則,在測試用例產生之后,測試用例文件驅動測試的執行。不同的控件類型將從測試類庫中調用不同的測試執行方法。該模塊采用反射機制來模擬用戶的操作。反射提供了延遲綁定,能模擬用戶的常用操作,如編輯控件文本、單擊按鈕等。調用控件的事件方法的關鍵是要用到反射中的MethodInfo.Invoke方法。如果沒有潛在的其他問題,可以像下面這樣調用控件的事件方法:
Type t1=testForm.GetType();
MethodInfo mi=t1.GetMethod(“button1_Click”,flags);
mi.Invoke(testForm,new object[]{null,EventArgs.Empty});
注意在調用該方法時要充分考慮線程的問題。該方法不是從被測應用程序運行的線程被調用的,而是從測試工具本身的主線程中被調用的。因此,應該通過調用Form.Invoke方法間接運行MethodInfo.Invoke方法[4]。
驗證測試過程中,為了得到控件的屬性或字段信息,將用到反射中的Form.GetType、Type.GetField、FieldInfo.GetValue、PropertyInfo.GetValue等方法。通過比較測試用例的預期結果和實際運行結果來決定測試結果。然后將測試用例的編號、預期結果、實際結果以及時間信息保存到XML文件中,同時可采用XSLT方式將測試結果以更友好的方式展現出來。
3.5 使用Windows調度程序
測試人員可能希望測試工具能在指定時間自動地運行測試,例如晚上11:00點。這樣,整個測試工作可以在下班之后進行,到第二天就能看到測試運行的結果。事實上,Microsoft都包含一個能在給定時間執行命令的程序。當前版本中,這個程序是Scheduled Tasks,位于控制面板上。打開這個文件夾,會看到Add Scheduled Task 圖標,單擊它可以啟動向導。有一個重要的選項是Task選項卡上的Run文本框,如圖2所示。可以在該文本框中添加相應的參數來完成自動化測試[6]。
本文設計了一個輕量級的GUI自動化測試框架,該框架可以系統、全面、主動地實現控件搜索,避免了傳統測試工具中繁重的錄制過程。界面控件的任何改變也不會影響測試腳本的運行。該框架讓測試人員從繁瑣的錄制工作、測試腳本的編輯和驗證點的插入工作中解放出來,使測試人員能將更多的時間和精力集中到測試用例的設計中。
參考文獻
[1] BECK K. Test driven development: by example[M]. Addison-Wesley Professional, 2002.
[2] DUSTIN E, RASHKA J, PAUL J. Automated software testing introduction, management, and performance[M]. Boston addison Wesley,1999.
[3] 柳勝.軟件自動化測試框架設計與實踐[M].北京:人民郵電出版社,2009.
[4] ZHOU R Z, WEI Z K. Study on Application of .NET Reflection in Automated Testing[J]. ICACT, 2010,7-10:(797-800).
[5] MCCAFFREY J D. .NET test automation recipes: a problem-solution approach[M]. Apress, 2006.
[6] LI K L, WU M Q. Effective GUI testing automation: developing an automated GUI testing tool[M].王軼昆,譯.北京:電子工業出版社,2005.
[7] ROOT R, SWEENEY M R. A tester’s guide to .NET Programming[M].楊浩,譯.北京:清華大學出版社,2007:279-280.