軟件測試中如何提取一個測試層次結構
測試用例(Test Case)是為某個特殊目標而編制的一組測試輸入、執行條件以及預期結果,以便測試某個程序路徑或核實是否滿足某個特定需求。
測試用例(Test Case)目前沒有經典的定義。比較通常的說法是:指對一項特定的軟件產品進行測試任務的描述,體現測試方案、方法、技術和策略。內容包括測試目標、測試環境、輸入數據、測試步驟、預期結果、測試腳本等,并形成文檔。
不同類別的軟件,測試用例是不同的。不同于諸如系統、工具、控制、游戲軟件,管理軟件的用戶需求更加不統一,變化更大、更快。筆者主要從事企業管理軟件的測試。因此我們的做法是把測試數據和測試腳本從測試用例中劃分出來。測試用例更趨于是針對軟件產品的功能、業務規則和業務處理所設計的測試方案。對軟件的每個特定功能或運行操作路徑的測試構成了一個個測試用例。
隨著中國軟件業的日益壯大和逐步走向成熟,軟件測試也在不斷發展。從最初的由軟件編程人員兼職測試到軟件公司組建獨立專職測試部門。測試工作也從簡單測試演變為包括:編制測試計劃、編寫測試用例、準備測試數據、編寫測試腳本、實施測試、測試評估等多項內容的正規測試。測試方式則由單純手工測試發展為手工、自動兼之,并有向第三方專業測試公司發展的趨勢。
要使最終用戶對軟件感到滿意,最有力的舉措就是對最終用戶的期望加以明確闡述,以便對這些期望進行核實并確認其有效性。測試用例反映了要核實的需求。然而,核實這些需求可能通過不同的方式并由不同的測試員來實施。例如,執行軟件以便驗證它的功能和性能,這項操作可能由某個測試員采用自動測試技術來實現;計算機系統的關機步驟可通過手工測試和觀察來完成;不過,市場占有率和銷售數據(以及產品需求),只能通過評測產品和競爭銷售數據來完成。
既然可能無法(或不必負責)核實所有的需求,那么是否能為測試挑選最適合或最關鍵的需求則關系到項目的成敗。選中要核實的需求將是對成本、風險和對該需求進行核實的必要性這三者權衡考慮的結果。
確定測試用例之所以很重要,原因有以下幾方面。
測試用例構成了設計和制定測試過程的基礎。 測試的“深度”與測試用例的數量成比例。由于每個測試用例反映不同的場景、條件或經由產品的事件流,因而,隨著測試用例數量的增加,您對產品質量和測試流程也就越有信心。 判斷測試是否完全的一個主要評測方法是基于需求的覆蓋,而這又是以確定、實施和/或執行的測試用例的數量為依據的。類似下面這樣的說明:“95 % 的關鍵測試用例已得以執行和驗證”,遠比“我們已完成 95 % 的測試”更有意義。 測試工作量與測試用例的數量成比例。根據全面且細化的測試用例,可以更準確地估計測試周期各連續階段的時間安排。 測試設計和開發的類型以及所需的資源主要都受控于測試用例。 測試用例通常根據它們所關聯關系的測試類型或測試需求來分類,而且將隨類型和需求進行相應地改變。最佳方案是為每個測試需求至少編制兩個測試用例:
·一個測試用例用于證明該需求已經滿足,通常稱作正面測試用例;
·另一個測試用例反映某個無法接受、反;蛞馔獾臈l件或數據,用于論證只有在所需條件下才能夠滿足該需求,這個測試用例稱作負面測試用例。
情景:
這個問題在編寫客戶端或端到端測試的時候尤為常見——就是那些為整個系統而不是為某個類所做的測試。偶爾Junit用戶——那些幾乎完全依賴 JUnit作為測試驅動的開發工具的人——會忘記那些從來不使用Junit的、非測試驅動程序員,因為JUnit提供了一個易于使用的Java框架來編寫測試程序。說這些是因為一個測試驅動的程序員會說:“如果你有一個這么大的測試模塊,那你的測試代碼就太大了,必須要修改測試代碼使其只專注于系統的一個方面。如果你這樣做了,那問題就會得到解決”。其實說的沒錯,可是這話是典型的數學家的語言:專注,精確,然而毫無用處。
如果能夠精簡測試模塊或者能夠找出其中沒有被所有測試所共享的部分,那就更好了:我們更喜歡簡單的測試用例層次結構。如果已經無法將事情簡化——或者是看不出該如何做--那也至少應該試著將通用的測試模塊移到一個地方。
技巧:
解決這個問題的技巧說來很簡單:盡管編寫的是測試程序,但它們還是用方法和對象實現的,所以將其當作方法和對象來看待。一個從一組類中抽取重復行為的辦法是,應用抽取超類的重構方法創建一個類層次結構。具體步驟如下:
1. 選擇兩個有通用測試模塊的測試用例類。
2. 創建一個新的TestCase的子類,它是有重復的測試模塊的測試用例類的超類。在這里,我們將這個新類叫做BaseFixture,這個是各人自己取的。
3. 將BaseFixture類聲明為抽象類,沒有必要創建這個類的實例。
4. 修改測試用例類代碼,使其繼承自BaseFixture而不是直接繼承TestCase。
5. 將重復的測試模塊復制到BaseFixture中——就是說,復制參數域和setUp()方法中初始化參數域的代碼?赡苄枰薷膮涤,將其聲明成受保護的而不是私有的,否則測試用例類就不能使用它們?梢詫涤蚍庋b在一個受保護的get方法里面,但是在這個例子中我們覺得沒必要這樣做。
6. 從每一個測試用例類中刪除測試模塊參數域,從setUp()方法中刪除已經移到BaseFixture中的代碼。
7. 在每個測試用例類的setUp()方法的開始加上一行super.setUp()。
8. 現在可以重新編譯運行此測試程序,來驗證其行為并沒有改變?梢詫ΡM可能多的共享通過測試模塊對象的測試用例類重復上述步驟。
另外在驗證了做完上述步驟沒有帶來任何問題以后,要看看那些setUp()方法中是否可以刪除一些空的或只有一行super.setUp()的方法。
討論:
可以將這個訣竅歸結為:“抽取測試用例類的超類,將其聲明為抽象的因為沒有理由去實例化它!
1. 通過將重復的測試代碼移到一個超類中來消除重復性事一個好主意。
2. 在重復代碼出現之前,我們一般想不到它。
最后有個地方要注意:必要的時候調用方法super.setUp()和super.tearDown()。從TestCase類直接派生子類的時候,并不需要擔心這些,因為超類的實現中什么也沒有做;但是現在你的超類的每個方法的實現中都可能有很重要的部分。這是一個常犯的錯誤——一個我們所有人都會犯的錯誤,并將持續到我們的編程生涯的結束的那一天——所以不必為此感到難過。
文章來源于領測軟件測試網 http://www.anti-gravitydesign.com/