《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 測(cè)試測(cè)量 > 設(shè)計(jì)應(yīng)用 > 基于.NET平臺(tái)GUI自動(dòng)化測(cè)試框架的設(shè)計(jì)
基于.NET平臺(tái)GUI自動(dòng)化測(cè)試框架的設(shè)計(jì)
來(lái)源:微型機(jī)與應(yīng)用2010年第19期
段 瑩,郭利剛
(武漢理工大學(xué) 計(jì)算機(jī)學(xué)院,湖北 武漢 430063)
摘要: 分析了錄制回放技術(shù)的基本原理和缺陷,運(yùn)用WIN32API和.NET反射機(jī)制,設(shè)計(jì)了一個(gè)改進(jìn)的輕量級(jí)GUI自動(dòng)化測(cè)試框架,解決了當(dāng)前測(cè)試自動(dòng)化中出現(xiàn)的一些棘手問(wèn)題。
Abstract:
Key words :

摘  要: 分析了錄制回放技術(shù)的基本原理和缺陷,運(yùn)用WIN32API和.NET反射機(jī)制,設(shè)計(jì)了一個(gè)改進(jìn)的輕量級(jí)GUI自動(dòng)化測(cè)試框架,解決了當(dāng)前測(cè)試自動(dòng)化中出現(xiàn)的一些棘手問(wèn)題。
關(guān)鍵詞: GUI;自動(dòng)化測(cè)試;反射

    軟件測(cè)試是保證軟件質(zhì)量的有效手段。目前,在GUI自動(dòng)化測(cè)試中,很多軟件體系都采用錄制回放技術(shù)。這種技術(shù)要求測(cè)試者通過(guò)鼠標(biāo)和鍵盤(pán)的點(diǎn)擊進(jìn)行工作,腳本記錄事件,然后以自動(dòng)化測(cè)試的方式進(jìn)行回放。記錄下來(lái)的測(cè)試腳本必須經(jīng)過(guò)編輯和調(diào)試之后插入驗(yàn)證和檢查點(diǎn)。產(chǎn)生的腳本通常是硬編碼,需要測(cè)試人員對(duì)腳本進(jìn)行編輯以及參數(shù)化操作。同時(shí),界面元素屬性的任何變化都會(huì)影響腳本的運(yùn)行,有時(shí)甚至需要重新錄制腳本。
1 .NET中的反射機(jī)制
    通常,應(yīng)用程序(包括桌面程序和Web應(yīng)用)都由一些基本的界面控件組成,所有的軟件指令都是通過(guò)控件以事件或消息的形式傳遞給后臺(tái)處理。GUI自動(dòng)化測(cè)試的本質(zhì)是對(duì)GUI中的控件元素提供編程手段[2]。在基于GUI對(duì)象識(shí)別和控制的自動(dòng)化測(cè)試工具中,過(guò)去一直依賴(lài)于Windows API函數(shù)的調(diào)用。而隨著新的編程語(yǔ)言和平臺(tái)的出現(xiàn),涌現(xiàn)了很多新的語(yǔ)言特性,這些語(yǔ)言特性可用于自動(dòng)化測(cè)試工具的設(shè)計(jì),例如反射機(jī)制就是其中一項(xiàng)技術(shù)。
    反射(Reflection)是.NET中的重要機(jī)制,通過(guò)反射可以在運(yùn)行時(shí)獲得.NET中每一個(gè)類(lèi)型(包括類(lèi)、結(jié)構(gòu)、委托、接口和枚舉等)的成員,包括方法、屬性、事件及構(gòu)造函數(shù)等,還可以獲得每個(gè)成員的名稱(chēng)、限定符和參數(shù)等。如果獲得了構(gòu)造函數(shù)的信息,即可直接創(chuàng)建對(duì)象,即使這個(gè)對(duì)象的類(lèi)型在編譯時(shí)還不知道。程序集包含模塊,而模塊包含類(lèi)型,類(lèi)型又包含成員,反射則提供了封裝程序集、模塊和類(lèi)型的對(duì)象??梢允褂梅瓷鋭?dòng)態(tài)地創(chuàng)建類(lèi)型的實(shí)例,將類(lèi)型綁定到現(xiàn)有對(duì)象或從現(xiàn)有對(duì)象中獲取類(lèi)型,然后調(diào)用類(lèi)型的方法或訪問(wèn)其字段和屬性[3]。
2 框架的整體設(shè)計(jì)
    自動(dòng)化測(cè)試框架的搭建基本上占了整個(gè)自動(dòng)化測(cè)試工作量的40%,是自動(dòng)化測(cè)試實(shí)施的一個(gè)重要組成部分。軟件自動(dòng)化框架從本質(zhì)看是一系列的策略思想、規(guī)范文件和代碼的集合。本文提出一種改進(jìn)的輕量級(jí)的GUI自動(dòng)化測(cè)試框架,該框架可以幫助用戶避免當(dāng)前測(cè)試工具出現(xiàn)的缺陷。此框架將具備以下五個(gè)特性:GUI控件自動(dòng)搜索、自動(dòng)生成和執(zhí)行測(cè)試腳本、基于數(shù)據(jù)驅(qū)動(dòng)的原則、測(cè)試的自動(dòng)驗(yàn)證、使用編程語(yǔ)言開(kāi)發(fā)??蚣艿恼w設(shè)計(jì)如圖1所示。從圖1可以看出,該框架讓測(cè)試人員從繁重的錄制工作中解放出來(lái),將更多的時(shí)間和精力集中在測(cè)試用例的設(shè)計(jì)中。

3 框架具體開(kāi)發(fā)
3.1 加載被測(cè)試程序

    為了測(cè)試GUI應(yīng)用程序,必須在測(cè)試工具中運(yùn)行被測(cè)程序使兩個(gè)程序交互。使用Assembly定義和加載程序集,加載在程序集清單中列出模塊,并從此程序集中查找類(lèi)型,創(chuàng)建該類(lèi)型的實(shí)例。為了使這兩個(gè)應(yīng)用程序?qū)崿F(xiàn)交互,必須通過(guò)多線程機(jī)制實(shí)現(xiàn)。下面是通過(guò)反射加載被測(cè)程序的核心代碼[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控件搜索
    大部分自動(dòng)化功能測(cè)試工具,尤其是商業(yè)的測(cè)試工具,都是基于GUI對(duì)象識(shí)別技術(shù)設(shè)計(jì)的。基本思想是每個(gè)基于窗體的控件都是一個(gè)窗體,每個(gè)控件或窗體都有一個(gè)句柄來(lái)進(jìn)行訪問(wèn)、操作和檢查。
    實(shí)現(xiàn)GUI測(cè)試自動(dòng)化的困難之一是測(cè)試工具并不知道被測(cè)程序中存在哪些GUI部件。錄制回放工具使用手工錄制過(guò)程暫時(shí)解決了這一問(wèn)題。Win32 API中封裝了很多可用于自動(dòng)化測(cè)試編程的函數(shù),這些函數(shù)可在編程語(yǔ)言進(jìn)行調(diào)用,實(shí)現(xiàn)自動(dòng)化測(cè)試編程。本文的自動(dòng)化GUI測(cè)試工具將采用Win32 API對(duì)被測(cè)程序進(jìn)行自動(dòng)、系統(tǒng)、全面的控件搜索。實(shí)現(xiàn)該搜索將用到Win32 API中封裝的可用于自動(dòng)化測(cè)試編程的函數(shù),包括:GetWindowRect、mouse_event、GetCursorPos和WindowFromPoint函數(shù)等。GetWindowRect函數(shù)返回指定窗口的邊框矩形的尺寸。該尺寸以相對(duì)于屏幕坐標(biāo)左上角的屏幕坐標(biāo)給出。通過(guò)使用這個(gè)函數(shù)可以計(jì)算出窗口的寬度和高度。mouse_event函數(shù)能模擬鼠標(biāo)擊鍵和鼠標(biāo)動(dòng)作。GetCursorPos函數(shù)檢取光標(biāo)的位置,并以屏幕坐標(biāo)來(lái)表示。使用WindowFromPoint函數(shù)能獲得包含指定點(diǎn)的控件的句柄。一旦得到了窗口的句柄,就能得到控件的文本、類(lèi)名以及父窗口的句柄。為了對(duì)界面進(jìn)行徹底的控件搜索,該框架將使用嵌套循環(huán),從界面的左上角到界面的右下角依次移動(dòng)鼠標(biāo)進(jìn)行控件識(shí)別,并將結(jié)果保存到對(duì)象庫(kù)中[5]。
    該模塊實(shí)現(xiàn)的偽代碼如下:
    RECT  rt=new RECT();
    GetWindowRect(iHandle,ref rt);
    width=rt.Right-rt.Left; //得到界面的寬度
    height=rt.Bottom-rt.Top; //得到高度
    step=8; //鼠標(biāo)每次移動(dòng)的像素
    for (int x=0;x<width;x+=step)
    {
        for (int y=0;y<height;y+=step)
        {
           mouse_event();      //移動(dòng)鼠標(biāo)到相應(yīng)的坐標(biāo)

           GetCursorPos();        //得到坐標(biāo)點(diǎn)處的光標(biāo)
           WindowFromPointGet();  //得到此處的控件句柄
           GetWindowText();           //得到窗體的文本
          GetClassName();             //得到控件的類(lèi)別
          GetParent();              //得到父窗體的句柄
         if (the handle does not exist in object repository)
         then save the infomation.
      }
    }
    通過(guò)對(duì)界面的徹底搜索,可以得出控件的句柄、文本、類(lèi)名、父窗體的句柄以及GUI控件間的層次關(guān)系。
3.3 生成測(cè)試用例
    實(shí)現(xiàn)GUI測(cè)試自動(dòng)化的另一個(gè)問(wèn)題是測(cè)試工具不能按事件發(fā)生的順序來(lái)選擇和操作控件。傳統(tǒng)的測(cè)試工具通過(guò)錄制的方法記錄程序運(yùn)行的順序,但是這種機(jī)制存在很多限制。本文設(shè)計(jì)的自動(dòng)化測(cè)試框架的思路是經(jīng)過(guò)界面控件的徹底搜索后,控件的詳細(xì)信息會(huì)保持到對(duì)象庫(kù)中。此時(shí),測(cè)試人員可以通過(guò)測(cè)試用例的輸入/輸出模塊來(lái)編寫(xiě)測(cè)試用例。該模塊是一個(gè)可視化編輯器。測(cè)試用例編輯器從對(duì)象庫(kù)中導(dǎo)入對(duì)象信息,該模塊根據(jù)測(cè)試用例設(shè)計(jì)人員的操作順序自動(dòng)產(chǎn)生事件的順序并將測(cè)試步驟保存到XML文件中。按事件發(fā)生的順序存儲(chǔ)的相關(guān)事件可以形成一個(gè)測(cè)試場(chǎng)景。測(cè)試用例編寫(xiě)者可以對(duì)產(chǎn)生的測(cè)試場(chǎng)景進(jìn)行編輯,改變測(cè)試步驟的順序或者添加更多的事件。測(cè)試運(yùn)行模塊將會(huì)從XML文件中讀取測(cè)試用例,按事件的順序執(zhí)行相應(yīng)的操作。
3.4 執(zhí)行并驗(yàn)證測(cè)試
    基于數(shù)據(jù)驅(qū)動(dòng)的原則,在測(cè)試用例產(chǎn)生之后,測(cè)試用例文件驅(qū)動(dòng)測(cè)試的執(zhí)行。不同的控件類(lèi)型將從測(cè)試類(lèi)庫(kù)中調(diào)用不同的測(cè)試執(zhí)行方法。該模塊采用反射機(jī)制來(lái)模擬用戶的操作。反射提供了延遲綁定,能模擬用戶的常用操作,如編輯控件文本、單擊按鈕等。調(diào)用控件的事件方法的關(guān)鍵是要用到反射中的MethodInfo.Invoke方法。如果沒(méi)有潛在的其他問(wèn)題,可以像下面這樣調(diào)用控件的事件方法:
    Type t1=testForm.GetType();
    MethodInfo mi=t1.GetMethod(“button1_Click”,flags);
    mi.Invoke(testForm,new object[]{null,EventArgs.Empty});
    注意在調(diào)用該方法時(shí)要充分考慮線程的問(wèn)題。該方法不是從被測(cè)應(yīng)用程序運(yùn)行的線程被調(diào)用的,而是從測(cè)試工具本身的主線程中被調(diào)用的。因此,應(yīng)該通過(guò)調(diào)用Form.Invoke方法間接運(yùn)行MethodInfo.Invoke方法[4]。
    驗(yàn)證測(cè)試過(guò)程中,為了得到控件的屬性或字段信息,將用到反射中的Form.GetType、Type.GetField、FieldInfo.GetValue、PropertyInfo.GetValue等方法。通過(guò)比較測(cè)試用例的預(yù)期結(jié)果和實(shí)際運(yùn)行結(jié)果來(lái)決定測(cè)試結(jié)果。然后將測(cè)試用例的編號(hào)、預(yù)期結(jié)果、實(shí)際結(jié)果以及時(shí)間信息保存到XML文件中,同時(shí)可采用XSLT方式將測(cè)試結(jié)果以更友好的方式展現(xiàn)出來(lái)。
3.5 使用Windows調(diào)度程序
    測(cè)試人員可能希望測(cè)試工具能在指定時(shí)間自動(dòng)地運(yùn)行測(cè)試,例如晚上11:00點(diǎn)。這樣,整個(gè)測(cè)試工作可以在下班之后進(jìn)行,到第二天就能看到測(cè)試運(yùn)行的結(jié)果。事實(shí)上,Microsoft都包含一個(gè)能在給定時(shí)間執(zhí)行命令的程序。當(dāng)前版本中,這個(gè)程序是Scheduled Tasks,位于控制面板上。打開(kāi)這個(gè)文件夾,會(huì)看到Add Scheduled Task 圖標(biāo),單擊它可以啟動(dòng)向?qū)?。有一個(gè)重要的選項(xiàng)是Task選項(xiàng)卡上的Run文本框,如圖2所示。可以在該文本框中添加相應(yīng)的參數(shù)來(lái)完成自動(dòng)化測(cè)試[6]。

    本文設(shè)計(jì)了一個(gè)輕量級(jí)的GUI自動(dòng)化測(cè)試框架,該框架可以系統(tǒng)、全面、主動(dòng)地實(shí)現(xiàn)控件搜索,避免了傳統(tǒng)測(cè)試工具中繁重的錄制過(guò)程。界面控件的任何改變也不會(huì)影響測(cè)試腳本的運(yùn)行。該框架讓測(cè)試人員從繁瑣的錄制工作、測(cè)試腳本的編輯和驗(yàn)證點(diǎn)的插入工作中解放出來(lái),使測(cè)試人員能將更多的時(shí)間和精力集中到測(cè)試用例的設(shè)計(jì)中。
參考文獻(xiàn)
[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] 柳勝.軟件自動(dòng)化測(cè)試框架設(shè)計(jì)與實(shí)踐[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].楊浩,譯.北京:清華大學(xué)出版社,2007:279-280.

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。