程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 追求代碼質量 - 使用TestNG-Abbot實現自動化GUI測試

追求代碼質量 - 使用TestNG-Abbot實現自動化GUI測試

編輯:關於JAVA

使用Swing、AWT 和類似的技術構建用戶界面通常會給開發人員進行測試帶 來挑戰,原因如下:

底層圖形框架的復雜性

GUI 中表現形式和業務邏輯之間的耦合

缺乏直觀的自動測試框架

當然,前兩個原因並不新鮮 —— 圖形框架本來就很復雜,而且向 GUI 應用程序添加業務功能總是會給測試造成麻煩。另一方面,過去幾年中有許多方便的框架湧現出來,確實使 GUI 測試更加便利。

本月,我將介紹一種新的框架,它極大地減輕了 GUI 測試的痛苦。

TestNG-Abbot 簡介

TestNG-Abbot 源自於兩個成功的開發人員測試框架的結合:Abbot 和 TestNG。Abbot 是一種 JUnit 擴展框架,主要目的是使 GUI 組件實現編程隔離 ,它還提供了一種驗證 GUI 行為的簡易方法。舉例來說,可以使用它來獲取對 按鈕組件的引用,使用編程的方法點擊按鈕,然後檢驗其操作。Abbot 還附帶了 一個腳本記錄器,使用它就能夠以 XML 格式布設測試場景,可以通過編程的方 式運行它。

在本系列中,我已經介紹了一些關於 TestNG 的內容,這裡將繼續介紹 TestNG。基本上,TestNG 是 JUnit 的一個替代物。除了所有預期的功能外,它 還增加了一些額外功能。正如我在其他文章中提到的一樣,TestNG 特別適合於 更高層次的測試,其中,它可以用來測試依賴關系並只返回失敗了的測試 —— 簡而言之,在測試 GUI 時,這類型測試非常方便。

它的起源就如此讓人印象深刻,所以 TestNG-Abbot 成為測試工具中的神童 就沒什麼好奇怪的了。同 Abbot 一樣,TestNG-Abbot 使 GUI 組件能夠進行編 程隔離。同時,它使用了 TestNG 的斷言,將 GUI 操作細節提取到了簡單的fixture 中,後者能夠公開驗證方法。如能正確使用,TestNG-Abbot 的直觀的fixture 類能夠使 GUI 測試如同從小男孩手裡偷一塊糖一樣簡單。(當然,您 不會想那麼干的!)

直觀的fixture 類

TestNG-Abbot 的當前版本支持七種 fixture 類型,其中一種類型用於操作 按鈕、菜單標簽以及文本項組件,如文本字段。此外,這些 fixture 類型根據 名字在邏輯上鏈接到了測試中的代碼(即 GUI 組件)。這使得 GUI 和其測試實 現了松耦合,這樣做至少有以下兩個好處:

測試不會依賴於特定位置的GUI 組件 —— 這樣無需中斷測試就可對其進行 移動。

可以在早期進行測試,並且不會受到開發期間布局和外觀改變的影響。

雖然目前只支持七種 fixture 類型,很快就會支持其他 fixture 類型。更 多的fixture 類型只會增加 TestNG-Abbot 在編程驗證 GUI 方面的高效性。

GUI 驗證不再普通!

雖然 TestNG-Abbot 使得驗證 GUI 的過程更加簡單,這並不意味著這個過程 很簡單。必須使 GUI 測試區別於單元或組件測試。驗證 GUI 中業務規則的過程 變成了對用戶場景進行驗證;或者,換種說法,GUI 測試包括驗證可見狀態的改 變。

比方說,如果按下了定單輸入 GUI 上的保存按鈕,業務規則會保證命令的內 容被保存到數據庫中。然而,在一個用戶場景中,會保證成功的狀態信息被插入 了按鈕下 —— 這正是使用TestNG-Abbot 能夠編寫的測試。事實上,如果 GUI 設計良好的話,可以測試被保存到數據庫中的命令內容而無需 測試 GUI。接著 您還可以同時並及早地編寫這兩個特別的測試。

加油!

記住 TestNG-Abbot 並不妨礙端對端測試(end-to-end)。可以輕 松將 TestNG-Abbot 和 DbUnit 結合在一起,比如,創建一個同時驗證用戶場景 和業務規則的可重復測試。

Word Finder GUI

為了使您了解 TestNG-Abbot 工作原理,我創建了一個簡單的GUI,它執行 一種功能 —— 在底層字典(也就是一個數據庫)中查閱一個給定的單詞並顯示 其釋義。不管該應用程序實際的代碼如何,測試該 GUI 用戶場景包括三個步驟 :

在文本框中輸入一個單詞。

單擊 Find Word 按鈕。

驗證是否給出了該單詞釋義。

當然,也存在一些極端的例子,比如一個用戶按下了 Find Word 按鈕但沒有 輸入單詞,或者,用戶輸入了一個無效的單詞。我將通過一些其他的測試案例說 明如何處理這類場景。

了解 GUI

圖 1 顯示了已啟動的Word Finder GUI。記住該 GUI 之所以簡單只有一個 原因:它演示了 TestNG-Abbot 的三個 fixture 類以及一些要引導的測試用例 !

圖 1. Word Finder GUI

當使用TestNG-Abbot 進行測試時,應該首先檢查 GUI 的組件。Word Finder GUI 由圖 2 所示的三個組件組成:

圖 2. Word Finder GUI 的組件

如您所見,Word Finder GUI 由一個 JTextField(用來輸入要查詢的單詞) 、一個 JButton(使 GUI 從字典數據庫中獲取釋義)和一個 JEditorPane (顯 示釋義)組成。

在良好的場景中,如果我輸入 pugnacious 然後單擊 Find Word 按鈕, JEditorPane 將顯示 “Combative in nature; belligerent”,如圖 3 所示:

圖 3. 良好的場景 —— 工作良好!

使用TestNG-Abbot 進行測試

要開始使用TestNG-Abbot,需要創建一個常規的測試 fixture,它將使用TestNG 的BeforeMethod 和 AfterMethod 注釋為您的GUI 創建一個實例。TestNG-Abbot 框架附帶了一個方便的AbbotFixture 對象,它簡化了 GUI 組件 的使用,實際上也引導了整個測試過程。要在測試 fixture 中使用該對象,需 要在測試前將一個 GUI 實例傳遞給 fixture 對象的showWindow() 方法,然後 使用名為 cleanUp() 的方法對 fixture 進行清理。

在清單 1 中,我創建了一個 TestNG 測試(實際上並沒有對其做任何測試) ,該測試在 fixture 中使用TestNG-Abbot 的AbbotFixture 對象來存放 Word Finder GUI 的實例。

清單 1. 使用AbbotFixture 對象定義 WordFindGUITest

public  class WordFindGUITest {
  private AbbotFixture fixture;

  @BeforeMethod
  private void initializeGUI() {
  fixture = new AbbotFixture();
  fixture.showWindow(new WordFind(), new Dimension(269,  184));
  }

  @AfterMethod
  public void tearDownGUI() {
  fixture.cleanUp();
  }
}

由於 Word Finder GUI 的用戶可見的行為會影響 圖 2 所示的三個組件,需 要通過編程對其進行調整,以確保工作能正常進行。比如,驗證 圖 3 演示的良 好的場景,需要執行下面三個步驟:

獲得對 JTextField 的引用並向其添加一些文本。

獲得 JButton 的句柄並單擊它。

獲得對 JLabel 組件的引用並檢驗是否顯示了正確的釋義。

檢驗良好的場景

使用TestNG-Abbot,可以通過這三個方便的fixture 類型執行上面所屬的三個步驟:TextComponentFixture 用於 JTextField;ButtonFixture 用於 Find Word 按鈕;LabelFixture 用來驗證 JLabel 中特定的文本。

清單 2 顯示了用於驗證 圖 3 中演示的內容是否可以正常工作的代碼:

清單 2. 測試一個良好場景

@Test
public void assertDefinitionPresent() {
  TextComponentFixture text1 = new TextComponentFixture (this.fixture,
   "wordValue");
  text1.enterText("pugnacious");

  ButtonFixture bfix = new ButtonFixture(this.fixture,  "findWord");
  bfix.click();

  LabelFixture fix = new LabelFixture(this.fixture,  "definition");
  fix.shouldHaveThisText("Combative in nature;  belligerent.");
} 

注意 fixture 對象通過一個邏輯名稱和特定的GUI 組件連接在一起。例如 ,在 Word Finder GUI 中,通過編程將 JButton 對象與 “findWord” 名稱聯 系起來。請注意在定義按鈕時,我是如何通過調用組件的setName() 方法做到 這點的,如清單 3 所示:

清單 3. 定義 Find Word 按鈕

findWordButton = new  JButton();
findWordButton.setBounds(new Rectangle(71, 113, 105, 29));
findWordButton.setText("Find Word");
findWordButton.setName("findWord");

同樣要注意,在 清單 2 中,我是如何通過將 “findWord” 名稱傳遞給 TestNG-Abbot 的ButtonFixture 對象而獲得對按鈕的引用。“單擊” 按鈕( 調用click 方法)然後使用TestNG-Abbot 的LabelFixture 對象插入單詞的釋義,多麼酷!不過不要就此滿足。

測試意外場景

當然,如果我非常希望驗證我的Word Finder GUI,我必須確保在用戶執行 意外操作時 —— 程序能夠正常工作,比如在輸入單詞之前按下 Find Word 按 鈕,或者情況更糟,比如他們輸入了一個無效的單詞。舉例來說,如果用戶沒有 向文本字段輸入內容,GUI 應該顯示特定的信息,如清單 4 所示:

圖 4. 糟糕的極端例子

當然,使用TestNG-Abbot 測試這種情況非常簡單,不是嗎?我所做的僅僅 是將空值傳送到 TextComponentFixture 中,按下按鈕(通過對 ButtonFixture 使用click 方法)並插入 “Please enter a valid word” 響應!

清單 4. 測試一個極端例子:如果有人沒有輸入單詞就按下了按鈕該怎麼辦 ?

@Test
public void assertNoWordPresentInvalidText() {
  TextComponentFixture text1 = new TextComponentFixture (this.fixture,
   "wordValue");
  text1.enterText("");

  ButtonFixture bfix = new ButtonFixture(this.fixture,  "findWord");
  bfix.click();

  LabelFixture fix = new LabelFixture(this.fixture,  "definition");
  fix.shouldHaveThisText("Please enter a valid word");
}

如清單 4 所示,一旦理解了獲得所需 GUI 組件的引用時,事情並不是很困 難。最後一步是檢驗其他 糟糕的極端例子 —— 輸入了無效的單詞。這個過程 與 清單 1 和 清單 3 非常相似:僅僅是將所需的String 傳遞到 TextComponentFixture 對象,單擊,然後插入特定的文本。如清單 5 所示:

清單 5. 輕松驗證另一個極端例子!

@Test
public void assertNoWordPresentInvalidText() {
  TextComponentFixture text1 = new TextComponentFixture (this.fixture,
   "wordValue");
  text1.enterText("Ha77");

  ButtonFixture bfix = new ButtonFixture(this.fixture,  "findWord");
  bfix.click();

  LabelFixture fix = new LabelFixture(this.fixture,  "definition");
  fix.shouldHaveThisText("Word doesn't exist in  dictionary");
}

清單 5 很好地驗證了圖 5 演示的功能,難道您不這樣認為嗎?

圖 5. 輸入了無效單詞

真不錯!我們已經使用TestNG-Abbot 輕而易舉地驗證了三種不同的用戶場 景。對於每種情況,我需要的只是被測試的組件的邏輯名稱以及一系列步驟,以 便創建場景。

繼續測試 GUI

TestNG-Abbot 可能是測試工具中的新生兒,但它從其前輩那裡繼承了一些非 常有用的特性。本文向您展示了如何使用TestNG-Abbot 通過編程的方法將 GUI 組件隔離,然後使用fixture 公開組件的驗證方法。在這個過程中,您了解了 對正常情況下的場景(所有事務都合乎邏輯)以及無法預見場景下(包括意外操 作)進行測試是多麼簡單。總之,你只需要知道場景和組件在其中起到了作用。使用TestNG-Abbot 方便的fixture 對象可以很輕易地改變組件的行為。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved