摘 要: 分析了錄制回放技術的基本原理和缺陷,,運用WIN32API和.NET反射機制,,設計了一個改進的輕量級GUI自動化測試框架,解決了當前測試自動化中出現(xiàn)的一些棘手問題,。
關鍵詞: GUI,;自動化測試;反射
軟件測試是保證軟件質(zhì)量的有效手段,。目前,在GUI自動化測試中,,很多軟件體系都采用錄制回放技術,。這種技術要求測試者通過鼠標和鍵盤的點擊進行工作,腳本記錄事件,,然后以自動化測試的方式進行回放,。記錄下來的測試腳本必須經(jīng)過編輯和調(diào)試之后插入驗證和檢查點。產(chǎn)生的腳本通常是硬編碼,需要測試人員對腳本進行編輯以及參數(shù)化操作,。同時,,界面元素屬性的任何變化都會影響腳本的運行,有時甚至需要重新錄制腳本,。
1 .NET中的反射機制
通常,,應用程序(包括桌面程序和Web應用)都由一些基本的界面控件組成,所有的軟件指令都是通過控件以事件或消息的形式傳遞給后臺處理,。GUI自動化測試的本質(zhì)是對GUI中的控件元素提供編程手段[2],。在基于GUI對象識別和控制的自動化測試工具中,過去一直依賴于Windows API函數(shù)的調(diào)用,。而隨著新的編程語言和平臺的出現(xiàn),,涌現(xiàn)了很多新的語言特性,這些語言特性可用于自動化測試工具的設計,,例如反射機制就是其中一項技術,。
反射(Reflection)是.NET中的重要機制,通過反射可以在運行時獲得.NET中每一個類型(包括類,、結(jié)構,、委托、接口和枚舉等)的成員,,包括方法,、屬性、事件及構造函數(shù)等,,還可以獲得每個成員的名稱,、限定符和參數(shù)等。如果獲得了構造函數(shù)的信息,,即可直接創(chuàng)建對象,,即使這個對象的類型在編譯時還不知道。程序集包含模塊,,而模塊包含類型,,類型又包含成員,反射則提供了封裝程序集,、模塊和類型的對象,。可以使用反射動態(tài)地創(chuàng)建類型的實例,,將類型綁定到現(xiàn)有對象或從現(xiàn)有對象中獲取類型,,然后調(diào)用類型的方法或訪問其字段和屬性[3]。
2 框架的整體設計
自動化測試框架的搭建基本上占了整個自動化測試工作量的40%,,是自動化測試實施的一個重要組成部分,。軟件自動化框架從本質(zhì)看是一系列的策略思想,、規(guī)范文件和代碼的集合。本文提出一種改進的輕量級的GUI自動化測試框架,,該框架可以幫助用戶避免當前測試工具出現(xiàn)的缺陷,。此框架將具備以下五個特性:GUI控件自動搜索、自動生成和執(zhí)行測試腳本,、基于數(shù)據(jù)驅(qū)動的原則,、測試的自動驗證、使用編程語言開發(fā),??蚣艿恼w設計如圖1所示。從圖1可以看出,,該框架讓測試人員從繁重的錄制工作中解放出來,,將更多的時間和精力集中在測試用例的設計中。
3 框架具體開發(fā)
3.1 加載被測試程序
為了測試GUI應用程序,,必須在測試工具中運行被測程序使兩個程序交互,。使用Assembly定義和加載程序集,加載在程序集清單中列出模塊,,并從此程序集中查找類型,,創(chuàng)建該類型的實例。為了使這兩個應用程序?qū)崿F(xiàn)交互,,必須通過多線程機制實現(xiàn),。下面是通過反射加載被測程序的核心代碼[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控件搜索
大部分自動化功能測試工具,,尤其是商業(yè)的測試工具,,都是基于GUI對象識別技術設計的?;舅枷胧敲總€基于窗體的控件都是一個窗體,,每個控件或窗體都有一個句柄來進行訪問、操作和檢查,。
實現(xiàn)GUI測試自動化的困難之一是測試工具并不知道被測程序中存在哪些GUI部件,。錄制回放工具使用手工錄制過程暫時解決了這一問題。Win32 API中封裝了很多可用于自動化測試編程的函數(shù),,這些函數(shù)可在編程語言進行調(diào)用,,實現(xiàn)自動化測試編程。本文的自動化GUI測試工具將采用Win32 API對被測程序進行自動,、系統(tǒng),、全面的控件搜索。實現(xiàn)該搜索將用到Win32 API中封裝的可用于自動化測試編程的函數(shù),,包括:GetWindowRect,、mouse_event、GetCursorPos和WindowFromPoint函數(shù)等,。GetWindowRect函數(shù)返回指定窗口的邊框矩形的尺寸,。該尺寸以相對于屏幕坐標左上角的屏幕坐標給出。通過使用這個函數(shù)可以計算出窗口的寬度和高度,。mouse_event函數(shù)能模擬鼠標擊鍵和鼠標動作,。GetCursorPos函數(shù)檢取光標的位置,并以屏幕坐標來表示,。使用WindowFromPoint函數(shù)能獲得包含指定點的控件的句柄,。一旦得到了窗口的句柄,就能得到控件的文本,、類名以及父窗口的句柄,。為了對界面進行徹底的控件搜索,該框架將使用嵌套循環(huán),,從界面的左上角到界面的右下角依次移動鼠標進行控件識別,,并將結(jié)果保存到對象庫中[5]。
該模塊實現(xiàn)的偽代碼如下:
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 生成測試用例
實現(xiàn)GUI測試自動化的另一個問題是測試工具不能按事件發(fā)生的順序來選擇和操作控件。傳統(tǒng)的測試工具通過錄制的方法記錄程序運行的順序,,但是這種機制存在很多限制,。本文設計的自動化測試框架的思路是經(jīng)過界面控件的徹底搜索后,控件的詳細信息會保持到對象庫中,。此時,,測試人員可以通過測試用例的輸入/輸出模塊來編寫測試用例。該模塊是一個可視化編輯器,。測試用例編輯器從對象庫中導入對象信息,,該模塊根據(jù)測試用例設計人員的操作順序自動產(chǎn)生事件的順序并將測試步驟保存到XML文件中。按事件發(fā)生的順序存儲的相關事件可以形成一個測試場景,。測試用例編寫者可以對產(chǎn)生的測試場景進行編輯,,改變測試步驟的順序或者添加更多的事件。測試運行模塊將會從XML文件中讀取測試用例,,按事件的順序執(zhí)行相應的操作,。
3.4 執(zhí)行并驗證測試
基于數(shù)據(jù)驅(qū)動的原則,在測試用例產(chǎn)生之后,,測試用例文件驅(qū)動測試的執(zhí)行,。不同的控件類型將從測試類庫中調(diào)用不同的測試執(zhí)行方法。該模塊采用反射機制來模擬用戶的操作,。反射提供了延遲綁定,,能模擬用戶的常用操作,如編輯控件文本,、單擊按鈕等,。調(diào)用控件的事件方法的關鍵是要用到反射中的MethodInfo.Invoke方法。如果沒有潛在的其他問題,,可以像下面這樣調(diào)用控件的事件方法:
Type t1=testForm.GetType(),;
MethodInfo mi=t1.GetMethod(“button1_Click”,flags),;
mi.Invoke(testForm,,new object[]{null,EventArgs.Empty}),;
注意在調(diào)用該方法時要充分考慮線程的問題,。該方法不是從被測應用程序運行的線程被調(diào)用的,而是從測試工具本身的主線程中被調(diào)用的。因此,,應該通過調(diào)用Form.Invoke方法間接運行MethodInfo.Invoke方法[4],。
驗證測試過程中,為了得到控件的屬性或字段信息,,將用到反射中的Form.GetType,、Type.GetField、FieldInfo.GetValue,、PropertyInfo.GetValue等方法。通過比較測試用例的預期結(jié)果和實際運行結(jié)果來決定測試結(jié)果,。然后將測試用例的編號,、預期結(jié)果、實際結(jié)果以及時間信息保存到XML文件中,,同時可采用XSLT方式將測試結(jié)果以更友好的方式展現(xiàn)出來,。
3.5 使用Windows調(diào)度程序
測試人員可能希望測試工具能在指定時間自動地運行測試,例如晚上11:00點,。這樣,,整個測試工作可以在下班之后進行,到第二天就能看到測試運行的結(jié)果,。事實上,,Microsoft都包含一個能在給定時間執(zhí)行命令的程序。當前版本中,,這個程序是Scheduled Tasks,,位于控制面板上。打開這個文件夾,,會看到Add Scheduled Task 圖標,,單擊它可以啟動向?qū)АS幸粋€重要的選項是Task選項卡上的Run文本框,,如圖2所示,。可以在該文本框中添加相應的參數(shù)來完成自動化測試[6],。
本文設計了一個輕量級的GUI自動化測試框架,,該框架可以系統(tǒng)、全面,、主動地實現(xiàn)控件搜索,,避免了傳統(tǒng)測試工具中繁重的錄制過程。界面控件的任何改變也不會影響測試腳本的運行,。該框架讓測試人員從繁瑣的錄制工作,、測試腳本的編輯和驗證點的插入工作中解放出來,使測試人員能將更多的時間和精力集中到測試用例的設計中。
參考文獻
[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].王軼昆,,譯.北京:電子工業(yè)出版社,,2005.
[7] ROOT R, SWEENEY M R. A tester’s guide to .NET Programming[M].楊浩,,譯.北京:清華大學出版社,,2007:279-280.