應用 Rational 工具簡化基于 J2EE 的項目第 8 部分 :測試軟件 本文是演示了在分布式的、基于 J2EE 的項目中使用 Rational 工具的系列文章(如下面所列)的第 8 部分。
第 1 部分: 項目介紹;高層次計劃
第 2 部分: 風險管理;需求管理
第 3 部分: 模型創(chuàng)建和訪問控制;需求分析
第 4 部分: 用例細化;產(chǎn)成報告;工具和技術(shù)選擇
第 5 部分: 體系架構(gòu)和設計
第 6 部分: 詳細設計;早期開發(fā);雙向工程;早期單元測試
第 7 部分: 繼續(xù)開發(fā);早期的構(gòu)建;演示
第 8 部分: 單元測試策略;功能測試;GUI 測試腳本 第 9 部分: 系統(tǒng)構(gòu)建和測試;缺陷跟蹤;產(chǎn)品交付 第 10 部分: 項目完成;結(jié)論;未來的工作
本文中所虛構(gòu)我們是一家軟件公司 Lookoff Technologies Incorporated,我們的客戶 Audiophile Speaker Design, Inc. (ASDI),它雇用我們實現(xiàn)他們最初的 IT 需求。對于更詳細的信息,參見
第 1 部分。
本文是這個系列文章的第 8 部分,本文中對最初在這個系列的
第 6 部分介紹的測試方面的主題進行了詳細的討論。在第 6 部分的文章中,我們看到了在早期的開發(fā)當中我們開始使用 Rational Purify 和 Rational Quantify 檢查內(nèi)存的使用情況和性能的瓶頸。同時也討論了我們在早期的單元測試工作的很多細節(jié)。本文將描述這些工作的進展,并回顧我們使用 Rational 測試工具的自動化測試的能力來減少測試的成本,主要是 Rational PureCoverage 和 Rational Robot 的使用情況。在項目的這個階段,我們主要關注在功能測試(包括 GUI 測試)上,雖然我們也從事了一些早期的負載測試。
注意,這里使用的 Rational 統(tǒng)一過程(RUP)術(shù)語反映了測試的兩個不同的維度:“單元測試”是在將要被測試的軟件的開發(fā)階段進行的 — 在這個時候測試是針對最小的可測試的軟件單元的 — 而“功能測試”和“負載測試”是針對特定測試目標的,不管是在被測試軟件的哪個開發(fā)階段。本文中所討論的關于單元測試的大多數(shù)內(nèi)容也可以應用在我們后面的開發(fā)階段的測試工作中(例如,在集成測試期間合并不同的組件或者子系統(tǒng))。
第 8 部分快照
在第 8 部分演示的工具和技術(shù):
Rational PureCoverage — 用于在單元測試期間分析代碼的覆蓋率(代碼被執(zhí)行的次數(shù)) Rational Robot — 為可重復的自動化執(zhí)行錄制和回放測試腳本 Rational Administrator — 用于創(chuàng)建項目,與 Rational Robot 一起使用,關聯(lián)與項目相關的測試腳本 Rational TestManager — 組織和管理測試,并查看測試的結(jié)果
被創(chuàng)建或者更新的產(chǎn)物:
Robot 測試腳本 — 為自動化測試的執(zhí)行而被創(chuàng)建
在開發(fā)的進展過程中,我們發(fā)現(xiàn)我們的單元測試工作超過了我們的開發(fā)工作,因為我們正在構(gòu)建的應用具有非常復雜的用戶交互。單元測試總是要求大量的工作,并且我們也許沒有足夠的預算和時間來執(zhí)行大量的單元測試工作。我們發(fā)現(xiàn)我們的 GUI 測試,包括單調(diào)的手工測試的過程,尤其減慢了我們的速度。
雖然 ASDI 項目的第 1 階段只是一個概念上的驗證,但是我們也具有艱苦的時間忍耐在系統(tǒng)中顯而易見的 bug 。在擁有堅固、可靠的軟件和頻繁的集成、快速的演示之間找到一個平衡是非常不容易的。我們定義了第 1 階段項目的范圍,這樣我們就必須進行不止一次的技術(shù)上的演示;客戶期望演示是一個可以使用的系統(tǒng)的 beta 版本。
這里,我們將看一下我們的單元測試工作的范圍,我們可以選擇(或者不)使用自動化的能力,并且我們使用 Rational PureCoverage 來確定我們測試的徹底性。
單元測試的范圍 — 什么、多少次和什么時候測試 — 是幾個可變量的基礎,包括:
軟件的復雜程度 產(chǎn)品的特性和接口 被測試部分對整個產(chǎn)品是否是非常關鍵的 團隊對軟件中缺陷的容忍程度
在代碼測試的次數(shù)方面,在之前的項目中我們沒有打算在我們的軟件中進行 100% 代碼覆蓋率的測試。完全的覆蓋是非常昂貴的并且很難達到,因為我們必須要手工的檢查我們的代碼以確定哪一行代碼沒有被測試覆蓋到。對單元測試的小的變化將要求我們重新檢查代碼以確保完全的覆蓋率被維護。然而,我們得感謝 Rational PureCoverage ,在 ASDI 項目中我們能夠容易得實現(xiàn)了接近 100% 的代碼覆蓋率(由于項目預算和范圍的原因,少量的未測試的殘留是被允許的)。PureCoverage 很大程度的簡化了檢查代碼覆蓋率的任務,這使識別哪一部分的代碼已經(jīng)或者還沒有被測試變得非常簡單。
就像我們在這個系列的
第 6 部分提到的那樣,我們的單元測試工作幾乎與核心的軟件開發(fā)本身開始的一樣早。我們多數(shù)的開發(fā)人員在他們擁有一個能夠被測試的軟件單元不久就開始編寫單元測試。他們喜歡當代碼在他們的頭腦中產(chǎn)生時測試軟件的內(nèi)部構(gòu)件。
單元測試的執(zhí)行總是先于系統(tǒng)的構(gòu)建;將明顯能夠通過單元測試來消除的簡單缺陷引入到一個構(gòu)建版本中是讓人不可接受的。單元測試總是在代碼被分發(fā)檢查之前被執(zhí)行。此外,開發(fā)人員以規(guī)范的基礎運行他們的單元測試以確保他們的定期變化不會破壞軟件。我們的方法不像一些軟件方法那樣激進 — 比如
極限編程(XP),在 XP 中單元測試的開發(fā)通常是先于代碼的開發(fā)的 — 但是我們將單元測試當作是一個重要的軟件開發(fā)的早期步驟。
這里當然也有一些如何進行測試的問題,特別是什么樣的測試應該被自動化的范圍。編寫“后臺”(非 GUI )代碼的開發(fā)人員是幸運的,他們能夠編寫自動化的測試,包括 Java 驅(qū)動程序、代碼存根和腳本。然而,就像我們早些時候提到的,GUI 開發(fā)人員的測試是更加困難的。
對于我們的非 GUI 測試,我們觀察了與每一個類相關聯(lián)的單元測試的習慣;我們編寫驅(qū)動代碼訪問類,并報告成功或者是失敗。我們嘗試使用能夠為我們自動生成、管理和運行測試的測試框架,比如被 XP 所推薦的那些工具,但是他們將產(chǎn)生混雜的結(jié)果。雖然理論是很好的,但是這些框架(包括,比如
JUnit)對于我們的項目目的來說來是不夠成熟的。不過,我們的開發(fā)人員非常自信如果他們有時間熟悉和對這些工具進行改進,這些測試框架對我們的單元測試是非常有價值的。我們也許在將來的項目中更多的使用這些測試框架。在我們的 ASDI 項目中,采用 XP 的方法也許是太冒險了;相反,我們更加愿意接受 XP 在控制和風險降低方法方面的概念和思想。你能夠在
the XProgramming.com 網(wǎng)站上找到大量有關 XP 思想的內(nèi)容。
我們沒有使用 Rational 的測試工具來測試非 GUI 的代碼,因為我們覺得他們不能達到一個足夠底層的級別。對于自動化測試我們的 GUI 驅(qū)動的代碼,Rational 的測試工具真的表現(xiàn)的非常出色。用戶界面測試是非常手工和交互的,并且要求大量的內(nèi)容確認; Rational 的測試工具以一種一致的并快速的方式使我們反復的進行這些測試變得更加的簡單容易。
通過使用 Rational PureCoverage ,在我們的單元測試執(zhí)行期間,我們能夠大幅的降低我們花在確定代碼覆蓋率上的時間 — 也就是說,哪些方法或者代碼行被執(zhí)行或者被遺漏 。這個工具能夠使我們觀測我們提供的代碼覆蓋測試,然后決定是改進測試還是通過手工檢查的方法來測試代碼。
PureCoverage 除了可以支持 C 或者 C++ 的應用程序以外,還可以支持 Java 程序,并且可以通過與 Quantify 相同的方式來配置和運行(在這個系列的
第 6 部分被討論過)。這個工具能夠使我們?yōu)g覽我們的單元測試;以兩種方法進行代碼覆蓋測試:使用 Coverage Browser 或者指定文件的 Coverage Fileview 方式。
使用 Coverage Browser 的方式(圖 1 ),我們能夠看到在單元測試中被包括的每一個文件(和目錄)的代碼覆蓋測試的統(tǒng)計學的總結(jié)。這些統(tǒng)計表包括了所有方法的調(diào)用次數(shù),方法被訪問或者遺漏的次數(shù),還包括被訪問或者遺漏的代碼行的數(shù)量。
圖 1: Coverage Browser
(
點擊放大)
我們能夠雙擊一個在總結(jié)中的方法來進入 Coverage Fileview ,僅僅顯示在那個方法中哪些代碼行被訪問或者被遺漏。就像被顯示在圖 2 中的例子,被遺漏的代碼行被用紅色突出出來(被訪問的代碼行用藍色標識)。
圖 2: Coverage Fileview
(
click here to enlarge)
功能測試根據(jù)被定義在用例中的需求來驗證軟件是否正確的工作。為了確保我們測試了所有的需求,我們在設計和組織我們的功能測試時使用 Rational Robot 和 Rational TestManager 。(一個關于使用 Robot 的功能測試策略的討論能夠在 Robot 的用戶指南中被找到。)Robot 能夠使測試腳本更加容易的被錄制,然后為自動化測試回放。使用 Robot 能夠創(chuàng)建兩種類型的測試腳本:
GUI 腳本 記錄你的用戶界面動作,當進行回放時,就像一個用戶在操作應用的登陸和控制程序的窗口。一些客戶端的測試 — 比如,嵌入到我們的 Web 應用中的 ActiveX 控件 — 需要使用這些腳本。因為 GUI 測試為我們造成了特殊的問題,因此這類的功能測試將在下一部分被詳細的討論。 VU scripts 當你使用它在包的級別上跟蹤什么樣的網(wǎng)絡信息被發(fā)送和接受時,檢測你的應用。當進行回放時,這些腳本不必登陸應用就可以重新運行測試,這使他們比 GUI 腳本執(zhí)行的更快。我們?yōu)槲覀兊?command gateway 的非 GUI 功能測試和 B2B 的負載測試使用 VU 腳本。
我們盡可能早的開始創(chuàng)建我們的功能測試集合,因為這些測試對工程團隊來說是非常有價值的工具。我們在代碼被分發(fā)檢查之前適當?shù)膿碛袦y試腳本的目標有時是很難實現(xiàn)的,可能是因為代碼的一些部分和一些組件要比其他的代碼和組件花費更多的時間來完成,或者是因為集成和測試(I&T)團隊太慢以至不能及時的完成測試腳本。在一種情況下,當用戶界面仍然在變化時,測試腳本已經(jīng)被完成了;雖然一些返工是必要的,但是變化的出現(xiàn)是相當容易集成的。
一旦我們擁有了一個強有力的功能測試集合,重新測試系統(tǒng)將是非常容易的。這樣當你需要在后來的迭代中重新測試系統(tǒng)小的改變時得到很大的回報,并且可以確保變化不會影響其他的代碼部分。我們映射我們的功能測試腳本到用例上,以便我們可以立即知道當被關聯(lián)到被給定的用例的需求被修改時哪一個測試應該被運行。
當非 GUI 代碼的開發(fā)人員非常高效的進行他們的單元測試工作時,JSP/servlet 的開發(fā)人員將很難的保證時間的進度。刺痛他們的是測試 GUI 域的過程,這個過程包括反復的執(zhí)行下面的步驟:
在數(shù)據(jù)庫中建立測試數(shù)據(jù)。 通過 Web 瀏覽器登陸應用。 導航被測試的頁面(一個表單要被填充)。 在頁面上填寫一個或者多個域,依賴具體的測試。 點擊適當?shù)陌粹o提交表單。 檢查結(jié)果。 使用不同的測試(不同的域值或者不同的域)返回到步驟 4 ,直到所有合理的組合都被測試。
一些 GUI 測試尤其令人討厭,包括相同的入口,在幾個域中填寫冗長的值??梢允褂眉羟泻驼迟N,但是對于團隊來說一遍一遍的重復這些測試仍然是非常瑣碎的工作。有些頁面有 50 個不同的測試必須被執(zhí)行,每個測試都包括很多的步驟。
雖然我們最初不傾向使用 Rational 的測試工具,但是我們覺得我們在 GUI 上的困難是我們深入研究 Rational 測試工具的很好的理由。我們決定使用 Rational Robot 來自動化我們 GUI 的大部分測試。我們通過以下的方式調(diào)整了這些測試:
開發(fā)人員為每一個測試起草一個單元測試說明。 初級的集成與測試團隊成員接受單元測試說明并基于當前的軟件構(gòu)建版本創(chuàng)建測試腳本。 單元測試腳本是可配置管理的,以便對測試腳本的變更可以被跟蹤。 定期的,一個開發(fā)人員給集成與測試團隊執(zhí)行單元測試腳本的任務,并提供一個根據(jù)單元測試說明指明成功或者失敗的報告。
這個方法工作的非常好。它不僅僅在集成與測試團隊沒有太多的事情做的開發(fā)過程的早期階段給他們在更多的工作,而且也給他們一個機會通過揭示單元測試說明來了解整個軟件系統(tǒng)。此外,我們?yōu)?GUI 測試使用 Robot 的經(jīng)驗也為阿我們對其他的功能測試腳本進行了準備。
當 Rational Robot 啟動時,它需要一個已存在項目(使用 Rational Administrator 創(chuàng)建的)的選擇,測試腳本將與這個項目進行關聯(lián)。在我們的例子中,項目的定位必須是在網(wǎng)絡上可訪問的,以便我們能夠在整個團隊中共享項目的數(shù)據(jù)庫。我們在 Administrator 中創(chuàng)建了 ASDI 項目,如圖 3 所示,并且當 Robot 提示我們選擇一個項目時,我們選擇了這個項目。
圖 3: 使用 Rational Administrator 創(chuàng)建一個項目
作為一個 GUI 測試的非常簡單的例子,我們需要確證對于我們的 partSearch.jsp 頁面來說客戶端的驗證是行為正確的,這個頁面執(zhí)行了 JavaScript 的代碼來驗證他們域。每個 ASDI 的條件,部分數(shù)字被輸入到整個頁面中,比如,必須是比 0 要大的整型數(shù)字;如果一個用戶輸入一個無效的數(shù)字,JavaScript 代碼就會報告一個錯誤,并且不會送壞的數(shù)據(jù)到服務器。我們的 JavaScript 代碼遵循了在
對于表單驗證的樣例代碼,我們在 FormChek.js 文件中編寫了我們自己的驗證代碼。適當?shù)氖褂眠@個代碼,一個負數(shù)的輸入會彈出如圖 4 所示的窗口。
圖 4: 適當?shù)?partSearch.jsp 頁面驗證
我們在 Robot 中創(chuàng)建了一個測試腳本來測試數(shù)字域的驗證是否示適當?shù)?。首?Robot 提示我們?yōu)槟_本提供一個名字(圖 5)。
圖 5: 錄制一個新的 GUI 腳本
在點擊 OK 這后,我們被提供了一個錄制控制器(圖 6),然后當 Robot 錄制我們的動作時,我們使用我們的基于窗口的應用。在這個例子中,我們啟動了 Internet Explorer 5 ,在 partSearch.jsp 頁面進行瀏覽,輸入一個壞的數(shù)字 (-123456),點擊 頁面上的 Submit 按鈕。
圖 6: Robot 錄制控制器
Robot 將我們的動作記錄在一個 GUI 腳本中(圖 7 )。這是一個非常簡單的例子;我們實際的測試會包括更加復雜的測試腳本。我們不用創(chuàng)建成百上千個獨立的腳本,而是盡量為每一個屏幕界面設計一個大的腳本。在 Robot 的文章中有進行測試設計的非常詳細的信息,我們能夠從 Robot 文檔中所推薦的內(nèi)容中得到大量的借鑒。
圖 7: 簡單的 Robot GUI 腳本
(
點擊放大)
通過使用易讀的并且可以容易的進行編輯的腳本,我們就不必為只是有很小差異的測試重復的錄制測試腳本了。有時我們可以不用重新運行測試就直接編輯測試腳本,或者我們只是重新錄制一個測試的一小部分,然后將它粘貼到已存在的腳本中。
為了再一次運行測試,我們簡單的在 Robot 的錄制控制器上(或者選擇 File 菜單上的 Playback )點擊 “play” 按鈕。腳本就像我們最初執(zhí)行測試一樣回放我們的測試操作,并且當腳本運行完成時,Rational TestManager 被啟動來總結(jié)我們的測試結(jié)果。對于上面那個簡單的例子,TestManager 在圖 8 中顯示的結(jié)果表明,測試腳本運行的結(jié)果是測試被通過。
圖 8: TestManager 報告 Robot 的測試通過
(
點擊放大)
假設我們想測試代碼的錯誤處理能力,比如壞的數(shù)字不再被捕獲 — 也就是說,沒有出現(xiàn)一個指明錯誤的窗口,我們的應用就會將整個數(shù)據(jù)傳送到 servlet 來執(zhí)行查詢。當我們通過回放腳本重新運行這個 GUI 測試時,Robot 將會捕獲這個問題,并且將結(jié)果寫到報告中(圖 9 ),包括顯示出這個測試是失敗的。
圖 9: TestManager 報告 Robot 測試的失敗
(
點擊放大)
當我們開始 ASDI 項目時,我們期望使用 Rational 的分析和設計工具而不是 Rational 的測試工具。到項目第一階段的這個時期,我們非常驚訝并且也很高興的看到我們通過使用 Rational 的測試工具自動化并且改進了我們的測試過程。這些工具都有一個堅實的學習曲線,但是一旦我們掌握我們每個工具的使用方法,我們的集成與測試團隊的生產(chǎn)力將大大的提高。在一些情況下,個體開發(fā)人員使用象 Rational Purify 、Quantify 和 PureCoverage 這樣的工具為他們的單元測試工作提供補充。其他的工具,比如 Rational Robot ,則需要集成與測試團隊具有更高的技能并投入更大的注意力。
團隊仍然必須在系統(tǒng)級別上承擔集成和測試的任務。多數(shù)的單元測試工作被分包給了開發(fā)人員,但是我們還需要更加全面和正式的測試子系統(tǒng)和整個系統(tǒng)。這就意味著我們需要正式的構(gòu)建版本、最終的構(gòu)建文檔和在集成與測試上的重要關注。特定目的的負載測試只是我們測試工作中的一小部分,但是它在整個系統(tǒng)的測試中卻是非常重要的。幸運的是,我們的測試集合已經(jīng)完成了 95% ,并且我們還稍稍的比計劃的時間提前了一點,因此我們能夠有一些額外的精力來關注系統(tǒng)的測試以確保高質(zhì)量的第一階段的系統(tǒng)交付。
我們的風險列表在此刻已經(jīng)非常的短了。客戶在演進系統(tǒng)上的合作并不太令人驚訝,我們的技術(shù)風險已經(jīng)非常少了,非常感謝工程團隊帶來的良好的進展。
現(xiàn)在我們必須對我們的代碼開發(fā)進行最后的加工、執(zhí)行系統(tǒng)的測試、識別系統(tǒng)中的任何缺陷并按計劃交付階段一的系統(tǒng)給客戶。當團隊接近主要階段的尾聲時,及時的將所有的細節(jié)包裝起來通常時很難的。如果我們想避免超出計劃,我們就需要系統(tǒng)有少量的缺陷,并且能夠快速的矯正在測試中發(fā)現(xiàn)的任何問題。
Steven Franklin 在軟件的設計、架構(gòu)和工程過程方面有非常廣泛的背景,這些經(jīng)驗通常被用到大的,分布式的信息管理和控制系統(tǒng)中。他從1997年開始使用 Rational 工具,他主要的興趣在 XML 、J2EE、無線和軟件工程技術(shù)方面。你可以通過
steve@sfranklin.net聯(lián)系 Steven.