您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 >
對(duì)Ajax應(yīng)用程序進(jìn)行單元測(cè)試
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/1/31 14:20:55 ] 推薦標(biāo)簽:

您可能從編寫 Ajax 應(yīng)用程序中獲得了極大樂(lè)趣,但是對(duì)它們執(zhí)行單元測(cè)試卻著實(shí)讓人頭痛。 在本文中,Andrew Glover 著手解決 Ajax 的弱點(diǎn)(其中之一),即應(yīng)對(duì)異步 Web 應(yīng)用程序執(zhí)行單元測(cè)試的固有挑戰(zhàn)。幸運(yùn)的是,他發(fā)現(xiàn)在 Google Web Toolkit 的幫助下,解決這個(gè)特殊的代碼質(zhì)量問(wèn)題要比預(yù)想的容易。

Ajax 在近期無(wú)疑是 Web 開(kāi)發(fā)界時(shí)髦的字眼之一 —— 與 Ajax 相關(guān)的工具、框架、書籍以及 Web 站點(diǎn)的劇增是該技術(shù)流行的好證明。此外,Ajax 應(yīng)用程序也相當(dāng)靈巧,不是嗎?不過(guò),像任何一個(gè)開(kāi)發(fā)過(guò) Ajax 應(yīng)用程序的人證實(shí)的一樣,對(duì) Ajax 執(zhí)行測(cè)試真的很不方便。事實(shí)上,Ajax 的出現(xiàn)已經(jīng)從根本上使得許多測(cè)試框架和工具失效,因?yàn)樗鼈儾](méi)有針對(duì)異步 Web 應(yīng)用程序測(cè)試進(jìn)行設(shè)計(jì)!

有趣的是,某個(gè)支持 Ajax 的框架的開(kāi)發(fā)人員注意到了這個(gè)限制,并為此做了一些非常新穎的設(shè)計(jì):內(nèi)置的可測(cè)試性。除此之外,由于該框架簡(jiǎn)化了使用 Java™ 代碼(而不是 JavaScript)創(chuàng)建 Ajax 應(yīng)用程序,它的起點(diǎn)甚高,并且充分利用了 Java 平臺(tái)上無(wú)可置疑的標(biāo)準(zhǔn)測(cè)試框架:JUnit。

我所論及的框架當(dāng)然是非常流行的 Google Web Toolkit,也是 GWT。在本文中,我將向您展示 GWT 如何實(shí)際地利用 Java 兼容性,使 Ajax 應(yīng)用程序的每個(gè)部分都能像與之對(duì)應(yīng)的同步應(yīng)用程序一樣進(jìn)行測(cè)試。

 

JUnit 和 GWTTestCase

因?yàn)榕c GWT 有關(guān)的 Ajax 應(yīng)用程序采用 Java 代碼編寫,所以非常適合開(kāi)發(fā)人員使用 JUnit 進(jìn)行測(cè)試。事實(shí)上,GWT 開(kāi)發(fā)小組還為此創(chuàng)建了一個(gè)幫助器類 GWTTestCase,擴(kuò)展自 JUnit 的 3.8.1 TestCase。該基類添加了一些功能,可測(cè)試 GWT 代碼并處理某些基礎(chǔ)實(shí)現(xiàn)從而啟動(dòng)并運(yùn)行 GWT 組件。
 
Google Web Toolkit
Google Web Toolkit 在 Java Web 開(kāi)發(fā)社區(qū)的發(fā)布聲勢(shì)浩大,同時(shí)也獲得了與之相稱的巨大轟動(dòng)。GWT 為利用 Java 代碼進(jìn)行設(shè)計(jì)、構(gòu)建和部署支持 Ajax 的 Web 應(yīng)用程序提供了一種新穎的方式。Java Web 開(kāi)發(fā)人員不再需要學(xué)習(xí) JavaScript 并花費(fèi)數(shù)個(gè)小時(shí)解決特定于瀏覽器的問(wèn)題,他們可以直接進(jìn)行與 Ajax 有關(guān)的富含信息的動(dòng)態(tài) Web 應(yīng)用程序設(shè)計(jì)。

需要提醒的是:GWTTestCase 并非用來(lái)測(cè)試與 UI 相關(guān)的代碼 —— 它是為了便于測(cè)試那些由 UI 交互觸發(fā) 的異步問(wèn)題。對(duì) GWTTestCase 用途的誤解使許多剛接觸 GWT 的開(kāi)發(fā)人員備受挫折,因?yàn)樗麄兤谕軌蛴盟奖愕啬M用戶界面,但終發(fā)現(xiàn)這是徒勞的。

Ajax 組件有兩個(gè)基本組成:體驗(yàn)和功能,這些都被設(shè)計(jì)成異步方式。圖 1 演示了一個(gè)模擬 Web 表單的簡(jiǎn)單 Ajax 組件。由于該組件支持 Ajax,表單的提交是異步執(zhí)行的(即:無(wú)需重新載入與傳統(tǒng)表單提交關(guān)聯(lián)的頁(yè)面)。

圖 1. 一個(gè)支持 Ajax 的簡(jiǎn)單 Web 表單

輸入一個(gè)有效單詞,單擊組件的 Submit 按鈕,將向服務(wù)器發(fā)送消息請(qǐng)求該單詞的定義。該定義通過(guò)回調(diào)異步返回,相應(yīng)地插入到 Web 頁(yè)面,如圖 2 所示:


圖 2. 單擊 Submit 按鈕后顯示響應(yīng)

功能性和集成測(cè)試

圖 2 所示的交互測(cè)試可用于多個(gè)不同場(chǎng)景,但是其中兩種場(chǎng)景為常見(jiàn)。從功能性觀點(diǎn)考慮,您或許希望編寫一個(gè)測(cè)試:填入表單值,單擊 Submit 按鈕,然后驗(yàn)證表單是否顯示定義。另外一個(gè)選擇是集成測(cè)試,使您能夠驗(yàn)證客戶端代碼的異步功能。GWT 的 GWTTestCase 正是被設(shè)計(jì)用來(lái)執(zhí)行此類測(cè)試。

需要牢記的是:在 GWTTestCase 測(cè)試用例環(huán)境下不可以進(jìn)行用戶界面測(cè)試。在設(shè)計(jì)和構(gòu)建 GWT 應(yīng)用程序時(shí),您必須清楚不要依賴用戶界面 測(cè)試代碼。這種思路需要把交互代碼從業(yè)務(wù)邏輯中分離出來(lái),正如您已經(jīng)了解的,這是佳的入門實(shí)踐!

舉例而言,重新查看圖 1 和圖 2 所示的 Ajax 應(yīng)用程序。該應(yīng)用程序由四個(gè)邏輯部分構(gòu)成:TextBox 用于輸入目標(biāo)單詞,Button 用于執(zhí)行單擊,還有兩個(gè) Label(一個(gè)用于 TextBox,另一個(gè)顯示定義)。實(shí)際 GWT 模塊的初始方法如清單 1 所示,但是您該如何測(cè)試這段代碼呢?


清單 1. 一個(gè)有效的 GWT 應(yīng)用程序,但是如何測(cè)試它?

                public class DefaultModule implements EntryPoint { public void onModuleLoad() {   Button button = new Button("Submit");   TextBox box = new TextBox();   Label output = new Label();   Label label = new Label("Word: ");   HorizontalPanel inputPanel = new HorizontalPanel();   inputPanel.setStyleName("input-panel");   inputPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);   inputPanel.add(label);   inputPanel.add(box);   button.addClickListener(new ClickListener() {    public void onclick(Widget sender) {      String word = box.getText();      WordServiceAsync instance = WordService.Util.getInstance();       try {         instance.getDefinition(word, new AsyncCallback() {                      public void onFailure(Throwable error) {             Window.alert("Error oclearcase/" target="_blank" >ccurred:" + error.toString());           }           public void onSuccess(Object retValue) {             output.setText(retValue.toString());           }    });        }catch(Exception e) {          e.printStackTrace();  } }   });   inputPanel.add(button);   inputPanel.setCellVerticalAlignment(button,     HasVerticalAlignment.ALIGN_BOTTOM);   RootPanel.get("slot1").add(inputPanel);   RootPanel.get("slot2").add(output);   }} 


清單 1 的代碼在運(yùn)行時(shí)發(fā)生了嚴(yán)重的錯(cuò)誤:它無(wú)法按照 JUnit 和 GWT 的 GWTTestCase 進(jìn)行測(cè)試。事實(shí)上,如果我試著為這段代碼編寫測(cè)試,從技術(shù)方面來(lái)說(shuō)它可以運(yùn)行,但是無(wú)法按照邏輯工作。考慮一下:您如何對(duì)這段代碼進(jìn)行驗(yàn)證?惟一可用于測(cè)試的 public 方法返回的是 void, 那么,您怎么能夠驗(yàn)證其功能的正確性呢?

如果我想以白盒方式驗(yàn)證這段代碼,必須分離業(yè)務(wù)邏輯和特定于用戶界面的代碼,這需要進(jìn)行重構(gòu)。這本質(zhì)上意味著把清單 1 中的代碼分離到一個(gè)便于測(cè)試的獨(dú)立方法中。但是這并非聽(tīng)上去那么簡(jiǎn)單。很明顯組件掛鉤是通過(guò) onModuleLoad() 方法實(shí)現(xiàn),但是如果我想強(qiáng)制其行為,可能 必須操縱某些用戶界面(UI)組件。

軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd