RUP測試過程之需求與用例

RUP(Rational Unified Process,Ratinaol 統一過程) 是rational公司提出的一套軟件開發過程,目前最新的版本是2003。RUP的最大特點就是它提供了一套完整的軟件開發過程框架,任何人或組織都可以根據自己的需要來對這個過程進行裁剪,並根據自身需要進行調整後使其成爲個性化的過程。讀者可以參考網絡上流傳的《RUP2000中文版》。 ( Rational以及 Rational Unified Process 均系 Rational Software Corporation 在美國和其他國家的商標或註冊商標。)
  有句老話說:萬事開頭難。說的是在做事情的時候,通常都是一開始覺得非常困難,但是隻要上了道,入了門,就會越來越容易、越來越順了。寫文章也是如此。不過筆者這裏說的開頭難並不是不會寫文章,而是專指不會寫文章的開頭部分。過去看到過的很多小說,無論是言情的或者武俠的,都會拿很長的篇幅出來作爲“引子”,或者叫“楔子”,用來交待一些同小說相關的信息。而一部小說是否能夠吸引讀者,這部分內容也起了很大的作用。不過,筆者作爲一個技術工作者,寫的大多數都是技術文章,一般來說文章的內容、結構都是一早就想明白的,唯獨這個開頭,實在不知如何寫起。不過想想也罷,既然不擅長這個,那就努力把內容寫的詳細、易懂一些,儘量讓讀者不會有上當的感覺吧。
  軟件測試作爲一個獨立的職位或者說行業,並不是軟件業的新生事物,但的確是隨着最近兩年一些新的思想注入國內軟件行業(比如敏捷開發過程、測試驅動開發等),才得以紅火起來的––這一點,從相關書籍的出版和銷售就可以看得出來,從事軟件測試工作的人也漸漸多了起來。但是也因爲是剛剛起步,同時國內大多數軟件公司都還處在中小型開發團隊甚至作坊式開發的層次,不可能提供太多的測試職位,想找到一些高水平並且富有經驗的測試人員更是難上加難。這最終也就導致了國內大多數測試從業者都處在“初級階段”這樣一個結果。
  筆者長期活躍在國內的幾個比較知名的測試論壇,發現大家希望討論的問題主要可以分爲兩種:一種是對於一些測試工作具體操作方法的提問,一種是對於測試工具使用的提問。總體看來,更多的問題集中在了後者。這似乎已經成爲了國內軟件業的通病,無論是開發還是測試,總希望可以通過某個工具或者語言來一勞永逸的實現某個理想。如果真的希望工具可以改變一切,那麼這種願望總是會落空的。而前者,大多是因爲進入了一些剛剛開始重視軟件測試的中小型軟件公司,而公司的開發團隊中負責軟件測試的可能只有一兩個對軟件測試一知半解的新手,當公司需要開展某些方面的測試工作時,缺少這部分相關經驗的朋友變選擇了通過網絡求助。
  測試工具的應用,的確可以提高工作效率,而對於測試工具方面的提問,本來也是無可厚非的,但是在筆者的實踐中,如果希望提高一個團隊的工作效率和改善工作效果,關注於過程和方法要遠遠好於關注工具。測試工具的學習、引入和使用,本身就是一個需要消耗大量資源的過程,而且對於工具的選擇和引入工具時機的選擇也是非常關鍵的,如果負責這項工作的並不是一位在軟件行業沉浸多年,有着豐富測試經驗並熟知開發過程的資深人士,那麼開發團隊將爲此承擔巨大的風險。即使成功的引入了測試工具,工具本身可以帶來的效率的提高也不是在短期內可以體現的。在這裏,筆者希望剛剛或者正在準備組建測試團隊的軟件公司在考慮測試流程的搭建和測試工具引入時,不要給剛剛進入測試行業的朋友太多壓力,因爲這兩項工作都不僅僅同軟件測試本身相關,同時也會涉及到項目管理、開發過程方面的內容。輕易的做出一個決定只會對將來在團隊中測試工作的開展帶來不利的影響。
  在這篇文章中,筆者不打算對測試工具方面的問題提出任何建議,而將對網絡上大家關注的測試過程和測試方法方面給出一些具有實際參考價值的經驗。
    測試工作應該什麼時候開始? 測試用例是不是一定要寫?如果寫,應該詳細到什麼程度纔會比較好用又容易維護? 什麼樣的測試用例纔是好的測試用例?測試用例如何覆蓋測試需求?測試需求和測試用例的關係是什麼?怎麼樣保證測試需求的整理和測試用例的設計不會浪費太多的人力或其他資源?……
  這些問題可謂是老生常談了,在論壇上、MSN上,或者郵件中,也經常會有朋友問到筆者一些這方面的問題。相信不管是測試新手,還是從事測試工作有一段時間的朋友,都會在工作中不得不經常的要考慮,這些問題到底有沒有一個相對明確的答案呢?
  相信看到這裏,已經有些朋友在想:這些問題也不是很難啊,在RUP對測試過程的描述中都已經說的很明白了啊。軟件測試工作必須要通過計劃測試、設計測試、實現測試、執行測試、評估測試幾個階段來完成。其中計劃測試階段需要制定測試計劃、整理測試需求;設計測試階段要設計測試用例和測試過程,要保證測試用例完全覆蓋測試需求;實現測試階段要根據測試用例實現具體的自動化腳本或者手工的操作步驟;執行測試階段則通過自動化測試工具或人手工來執行那些自動化或手工腳本;最後的評估階段則要對軟件的質量和測試工作自身的質量做出一個客觀的評價。RUP中還有詳細的工作指南和文檔模板呢!
  對,上面所說的這些都沒有錯,RUP中對於軟件測試過程的描述要比筆者上面這段文字詳細也生動得多。但是,我們同時也可以看到,RUP中描述到的,更多的是關注於過程的管理,或者更準確的說,RUP是在爲我們提供一個大的方向,是一個穩定的、具有指導作用的框架,而不是一些具體的、涉及到操作細節的方法。這也是爲什麼很多朋友通讀了RUP中關於軟件測試的部分,但是一旦實際應用仍然找不準方向的原因。筆者今天希望同大家討論的,則恰恰是這樣一些在實踐RUP測試過程時,從實際工作中總結出來的工作方法和經驗。 對於測試過程方面的規範和一些基本概念, RUP中已經講的很詳細了,筆者在此也就不再贅述,有需要的讀者請參照RUP中的相關部分。本文中所關注的內容包括:
 1.在計劃測試時,如何確定測試工作的範圍和如何整理測試需求;
 2.設計測試用例時,應該如何把握測試用例的粒度;
  3.如何平衡測試用例的可用性和可維護性;
4.如何通過逆向的測試數據分析方法來保證測試用例的有效性和減少測試工作中資源的浪費;
5.一個簡單的但有實際意義的例子將展示如何將筆者的方法應用到測試過程中。
  這裏要事先聲明一下,筆者工作三年來,不管是開發還是測試,工作內容始終是圍繞着信息管理系統相關業務展開的,而對於測試工作,也一直侷限於在系統測試階段通過手工方法和簡單的利用一些測試工具特性進行黑盒測試。因此,在本文下面描述的內容中,難免受到客觀環境和筆者個人經驗的影響。也正因爲如此, 筆者不保證本文中方法和觀點適合於所有組織和個人的軟件開發過程 。只是希望能夠藉此爲大家提供一種思路,幫助更多人進行個性化的 RUP測試過程實踐,共同提高軟件測試行業的水平。 另外,本文中使用到的例子,均爲筆者的一些假設,如果侵害到任何第三方組織或個人的利益,實屬巧合,請通過 E-Mail通知筆者,筆者將在今後再次發佈本文時做出相應的調整。
如何確定測試工作的範圍?
  對於一個存在生命週期的軟件產品來說,它的開發和測試往往都不是一次性的,因爲隨着新的需求的出現,以及對原有版本的改進,新的版本會不斷的發佈(即使對於一些以客戶定製方式運作的項目,在開發過程中以及發佈後的維護期內,也會產生衆多的內部版本)。隨着版本的迭代,我們的測試工作也會一直繼續下去。而在每一次迭代時,可能在整個工作階段的開始就受到一些因素的影響,比如市場需求、既定的發佈時間、併發的工作導致的資源緊張等等,使我們不得不考慮對軟件質量要求的適度,最終使得我們在每個階段的測試工作的要求或者說所涉及到的內容有可能是不同的。這種變化,最終將會影響到測試需求的確定。
  那麼到底該如何確定每次迭代是測試工作的範圍呢? 在筆者的實踐中,通常把測試工作範圍的確定,等價的認爲是軟件需求的確定。
  不過現在有一個很實際的問題是這樣:軟件需求在開發過程中不斷髮生變化,有時候到了後期還會有新的需求添加進來,還有些需求在交付內部測試版本之後又發現原來的需求本身就存在缺陷,之後再次返工,在軟件最終發佈之前,怎麼可能確定的下來呢。啊,這些都是讓我們的開發人員和測試人員極其頭痛的事情。到底應該怎樣在頻繁變更的需求中確定哪些部分是我們在某個階段要測試的內容呢?或者說通過什麼樣的方法可以改善我們上面提到的那些問題呢? 一個實際的做法就是實現軟件需求的版本化控制 。既然說到了這裏,就不免要說些題外話。筆者一直都認爲軟件需求是開發工作和測試工作在制定計劃、開展工作時所共同參照的源頭和依據,而我們只有在源頭上控制好,才能保證下面工作的平穩開展。如果希望某個階段工作的進度和內容可以明確的定義下來,就必須要考慮軟件需求的版本化控制。這裏所提到的“軟件需求的版本化控制”,是指在一個軟件產品的生命週期中,當要進行一個新版本的迭代時,要儘早的確定這個版本中將要實現的需求,並同上個版本做出比較,哪些內容是新增的,哪些內容是被調整過的。在該階段工作開始之初的工作會議上,明確的向所有需要了解軟件需求的涉衆傳達這部分信息。而如果在該版本的開發過程中不斷的出現需求變更的情況,則應該根據市場策略、已公佈的發佈時間、客戶需求、實現的代價、難易程度以及對現有工作的影響等方面,對需求進行適度劃分,嚴格定義當前版本中需要實現的需求,而其他部分,則作爲未來版本的軟件需求進行考慮。如果有的朋友認爲上面的內容還是太理論化,需要一個更實際的、可操作的方法。那麼只能說,對於需求的變更,以及因爲需求變更而引起的設計的變更,必須要早發現,早討論,早決定,早調整。這可能更多的要依靠一個團隊中相關負責人員的主動工作來保證,而不是依靠一個明確的方法。注意,這裏的一個關鍵是,對於軟件需求,同樣需要嚴格按照版本進行管理,或者說使用“基線”進行管理。
  如何整理測試需求?
  一旦當前階段測試工作的範圍確定下來,我們就可以開始考慮測試需求的整理––也就是明確的定義現階段要“測什麼”。測試需求的確定將爲我們制定進度時間表、分配資源以及如何確定某個階段測試工作是否完成提供一個可供衡量的標準。當然,還有更重要的一點,已被確定的測試需求是我們進行測試用例設計和考慮測試覆蓋的依據。整理測試需求的第一步,就是要“測試需求”。測試需求?對,不知道您是否想到,這裏的“測試需求”中的“測試”是一個動詞,指的是對軟件需求本身的檢查。
  啊?這不是已經超出了測試工作的範圍了嗎?測試人員不是應該只關心軟件的實現同需求是否相符嗎?這樣對測試人員要求未免太高了。––這是筆者過去同一些朋友談到測試人員必須對需求進行檢查時聽到的一些不同的聲音。  在這裏,首先要明確一個問題,就是軟件測試的工作到底做什麼?
  在《軟件測試》( Ron Patton〔美〕,中文版由機械工業出版社出版,這本書是測試新手入門的經典教材)一書的第10頁,有一個明確而簡潔的定義:軟件測試員的目標是找到軟件缺陷,儘可能早一些,並確保其得以修復。
  瞧!這裏說要“儘可能早”的“找到軟件缺陷”。那這“儘可能早”要早到什麼時候呢?
  不知道大家對《軟件工程》這本書還有什麼印象。至少在筆者看過的多個不同版本的軟件工程方面的書中,對於軟件缺陷都會有一段類似的描述:缺陷發現的越早,則修復這個缺陷的代價就越小,在需求、設計、編碼、測試、發佈等不同的階段,發現缺陷後修復的代價都會比在前一個階段修復的代價提高10倍(參見下圖)。這樣看來,上面問題的答案自然就變成了“禿子頭上的蝨子”:從需求階段開始!從“測試需求”開始!
  注意,筆者這裏的觀點並不是說可以取消團隊中的“需求評審會議”,這裏並不存在衝突。筆者所希望講述的,是測試人員應該如何看待軟件需求,而並不是把“需求評審會議”所承擔的責任攬到自己身上。 ?在論壇上也偶爾看到有的朋友問:如何測試需求呢?每次看到這樣的提問,筆者內心就禁不住的一陣激動,因爲一直以來,討論這方面問題的朋友的確少之又少。在筆者的實際工作中,對軟件需求的檢查包括兩個方面的內容。一是對軟件需求正確性的檢查,也就是要保證需求文檔中所描述的內容是真實可靠的。在進行這部分工作時,不要迷信所謂的“都是用戶提出的真實的需求”,因爲我們必須考慮,提出這些需求的涉衆,是否真的可以正確的描述自己的需求?我們的需求人員是否真的可以正確的理解用戶的需求?有沒有一些被用戶認爲在業務處理上是理所當然、極其平常的事情,而沒有作爲需求提出來?有沒有一些被用戶認爲他們過去使用的軟件已經提供了相應的功能,所以認爲我們也應當提供,而沒有提出來的?關於這個問題,也曾經有朋友提過不同的看法,認爲這樣對測試人員的要求太高了––既要熟悉需求人員的工作,又要熟悉軟件所涉及的行業的業務。但筆者還是固執的認爲,作爲測試人員,還是需要對軟件產品所涉及的行業的業務有一個全面的、深入的瞭解––當然,這不是對一個剛剛入門的測試者的要求,但是如果想稱爲一個優秀的測試者,是難免要付出這部分努力的。
  二是要保證軟件需求的可測試性。對於“可測試性”,筆者的概念是:對於一條軟件需求或者一個需要實現的特性,必須存在一個可以明確預知的結果,並且可以通過設計一個可以重複的過程來對這個明確的結果進行驗證。說的具體一點,就是要保證所有的需要實現的需求都是可以用某種方法來明確的判斷是否符合需求文檔中的描述。如果對於某條需求或某個特性,無法通過一個明確的方法來進行驗證,或者無法預知它的結果,那麼就意味着這條需求的描述存在缺陷,應該請需求人員對需求文檔進行修改或補充––我們有理由相信,如果作爲測試人員對需求無法產生準確的理解,那麼開發人員也同樣無法對同一條需求產生準確的理解。對於一條確定的軟件需求理解的二義性,是在不規範的開發過程中導致返工的一個主要原因。如果認爲有必要,那應該在“需求評審會議”上確認所有涉衆對需求的理解是一致的。 當然,對於如何提高軟件需求的質量,在網絡上或者已經出版的書刊中都已經有了很多更加具體、實用的方法,如果有興趣,大家也可以找來參考。不過,如果您是一位測試者,那麼上面這部分內容對您仍然是非常有用的。相信您只要在工作中進行嘗試,慢慢的體會,一定會發現這種方法給您帶來的好處。?現在當前的測試工作範圍已經確定,相應版本的軟件需求也通過了評審,我們就可以在這個已經確定的範圍內進行測試需求的整理。我們手頭上可以參考的東西,通常會有軟件需求規約(以下簡稱 SRS)和用例(以下簡稱UC)––當然,也可能是一份包含UC的SRS。通過對SRS和UC的閱讀,我們可以從文檔對特性和業務流程的描述中獲得對軟件所涉及的業務的一個基本的認識。比如用戶在處理實際業務時都要作些什麼,多個業務之間的先後順序是怎樣的,用戶在處理業務是對於哪些地方有特別的要求,等等。這部分規則,將成爲我們的測試需求中最基本的一部分。
  至於測試需求的表現形式,筆者認爲大家都可以根據自己的需要進行設計,而沒有必要把思路限制在到底使用表格方式還是使用文本方式,只要把握一個原則就行了:在一條測試需求中,用容易理解的自然語言,明確的描述一項需要測試的內容。對於多項測試內容,應儘可能的剝離開來,保證一條測試需求只包含一項測試內容。
  另外,大家也可能注意到了,在軟件開發過程的這個階段,通常是沒有用戶界面(以下簡稱UI)可供參考的––雖然RUP中對於需求階段的工作描述包括了UI設計的部分,但很多時候在這個階段還是無法提供一個確定的UI的––也就是說我們這時獲得的測試需求,將是完全基於業務的,而並不包括基於UI的那部分規則,是同軟件的最終具體實現相獨立的。
  隨着開發工作的繼續,開發部門的架構設計文檔和詳細設計文檔也將陸續提交,這時候,我們可以根據設計文檔來對已有的測試需求進行增補。注意,這裏我們對於設計文檔中提到的內容要有選擇的採用,只有同SRS或UC中已經定義的部分相符的內容,纔可以用來調整我們的測試需求。而同軟件需求不相符的部分,則需要同設計人員和需求人員一起討論,確定下以哪一方作爲基準,決定是否需要調整軟件需求,然後對測試需求進行相應的增補或者調整。比如對於一些算法,需要考慮設計文檔中定義的,同系統實現相關的那些計算公式,是否同軟件需求中描述的算法表達的是否是同一個意思?而對於一些約束或者業務規則,設計文檔中描述的是否同需求中的相應部分一致? 呵呵,看完上面這部分內容,恐怕又有一部分朋友暈倒在地了,而沒有暈倒的那部分朋友 也要提出異議:啊?!你這不是又包含了對開發人員所作的設計工作的檢查嗎?!剛剛讓我們檢查需求,現在又讓我們檢查設計,真的把我們當成全才了!沒辦法,爲了讓軟件交到我們手上的時候只包含儘量少的缺陷,大家只能再辛苦一下了。我們的工作不應當僅僅限制在軟件交付後盡力找到存在的缺陷,而更應該努力及早發現軟件缺陷出現的苗頭,儘量預防缺陷的出現。雖然並不是說在所有的團隊中都應該由測試人員承擔“測試需求”和“測試設計”的工作,但是測試人員對這些工作起到的作用,是其他團隊中的其他角色所無法替代的。開發部門完成編碼實現工作,提交供內部測試的應用程序時,測試人員手頭上應該已經準備好了絕大部分測試用例和測試數據,測試部門將開始執行測試。通常在我們執行測試的過程中,即使我們已經從“通過測試”和“失敗測試”兩個不同的角度準備了非常充分的測試用例和測試數據,但總是有些缺陷的出現是出乎我們意料的,或者說是已有的測試需求和測試用例未能覆蓋的。那麼,對於這部分缺陷,也應當添加到測試需求中,並設計相應的測試用例,以便於下次版本迭代時進行參考。 OK,相信說到這裏,各位看客也應該可以理解我的觀點了:對於一個長期發展的團隊或者持續開發的產品,它的所有東西都是要不斷積累的、不斷迭代的。無論對於軟件需求還是測試需求,不僅僅是在一個版本的開發過程中,在不同的階段進行迭代,在產品的整個生命週期中的不同版本間,也是不斷迭代和積累的。
關於測試用例
  什麼時候開始設計測試用例?測試用例該怎麼寫?什麼時候算是完成了測試用例的設計工作?上面幾條可以算是網絡上測試用例設計方面最熱的問題,而且每隔一段時間就會被不同的人重新提起。提問的有剛剛進入測試行業的朋友,也有工作一段時間後重新陷入迷茫的“老手”。這幾個問題看似簡單,可是要想回答的讓大家都感到滿意,還真是不容易。這樣的高難度,筆者也不敢有太多的奢望,還是把自己的經驗寫出來,希望對大家有些參考價值吧。 測試用例 是爲特定目標開發的測試輸入、執行條件和預期結果的集合。這些特定目標可以是:驗證一個特定的程序路徑或覈實是否符合特定需求。––這是 RUP中關於測試用例的定義。而在實際工作中,對於測試用例的設計和選擇,是考察一個測試人員工作能力和經驗的最好方法。 如果您像筆者前面說的那樣,已經在工作中開展了測試需求的整理工作,那麼測試用例的設計工作就會變成一件自然而然的事情了。如果您在需求階段就開始了對測試需求的整理,那麼當這部分測試需求整理完後,就可以開始相應測試用例的設計了。而隨着開發工作的繼續,在測試需求被不斷的增補、調整後,也應該添加或修改相應的測試用例,以保證測試用例的有效性。這裏筆者要特別強調一點:測試用例的完成並非是一勞永逸的,因爲測試用例是來源於測試需求,而測試需求的來源包括了軟件需求、系統設計、詳細設計,甚至包括了軟件發佈後,在軟件產品生命週期結束前發現的所有軟件缺陷。來源的多元化註定了測試需求是非常容易發生變化的。一旦測試需求發生變化,則測試用例必須重新維護。如果您對於軟件開發的迭代方法比較熟悉,那麼就可以對測試用例的設計採用同樣的方法。而最終的結果,是您的團隊將逐漸擁有越來越全面細緻的測試需求和測試用例庫,測試人員越來越多的精力,可以放到對測試過程的考慮和測試用例的選擇方面。至少在筆者的實踐中,這種方法雖然前期需要相對大量的投入,但隨着時間的遷移,在沒有使用自動化測試工具的情況下,同樣大大提高了每個測試人員單位時間內測試工作的效率。關於設計測試用例的方法,無論是在已經出版的專業測試書籍還是網絡上的專業測試論壇中,都已經有了很多非常好的文章來專門講解,筆者也不打算佔用太多篇幅重新引用,大家如果有這方面需要,通過網絡都可以很容易的找到這些資料。在這裏,筆者只是想簡單的評論一下很多初學者對這些方法容易產生的誤解。相信對於任何一個測試人員來說,等價類劃分法和邊界分析法都是最早接觸,也是最基本、最容易使用的測試用例設計方法。很多朋友也都知道先使用等價類劃分法劃分出等價類,然後使用邊界分析法確定測試需要的邊界值。但是很多朋友也提到,在工作了一段時間後,發現這兩中方法所能應用的地方越來越少,難道這兩種方法真的只能應用在檢查編輯框輸入類型和輸入長度的時候嗎?當然不是。對於一些剛剛接觸測試工作的朋友提出的這個問題,筆者認爲現在市面上的很多測試書籍都要承擔很大的責任。比如很多書中,在講到測試用例設計時,都不約而同的使用同一個例子–– Windows計算器程序。通常是告訴你對於計算器有一個允許的輸入範圍(比如允許輸入一個大於0小於等於100的整數),然後要求設計相應的包含合法數據和不合法數據的測試用例。當然,僅僅是這樣一條簡單的描述,我們已經可以設計出很多測試用例和測試數據了,比如對於輸入範圍的考慮,對於輸入數據類型的考慮,對於輸入長度的考慮等等。但是在我們的實際工作中,很多時候看到的並不是這樣過於簡單的軟件需求描述,很多時候這些內容都是隱含在一些算法或業務規則中的。 我們現在舉個例子來看一下: “雙倍餘額遞減法是在不考慮固定資產殘值的情況下,以平均年限法折舊率(不扣殘值)的兩倍作爲折舊率,乘以每期期初固定資產折餘價值求得每期折舊額的一種快速折舊的方法。 
    年折舊率="2÷預計使用年限×100%"
   月折舊率="年折舊率÷12"
  月折舊額="期初固定資產賬面淨值×月折舊率"
  爲了保證固定資產使用年限終了時賬面淨值與預計淨殘值相等,在該固定資產折舊年限到期的前兩年,將固定資產淨值扣除預計淨殘值後的餘額平均攤銷。” 上面的內容是我國現行財務制度中關於固定資產折舊的一種方法––雙倍餘額遞減法––的具體算法,大家可以在任何一本會計書中找到這部分內容以及一些相應的例子,不過我們這裏並不關心固定資產的折舊到底是怎麼一回事。筆者想知道的是大家在看完上面的描述後是否已經發現,我們在設計測試用例時,對於準備進行折舊的固定資產,至少應該包括預計折舊年限小於兩年、等於兩年和大於兩年三種不同的類型。這也應該算是一個等價類劃分法和邊界分析法的應用吧。實際上,制約我們更好的使用這些測試方法來進行測試用例設計的,並不是方法的應用範圍不夠寬廣,而是因爲如果我們不能對這些同實際業務相關的具體算法或業務規則進行深入的分析,就不可能挖掘出深層的測試需求,那麼這兩種方法的應用也就很有限了。這也是筆者在前面一再強調加深對軟件需求瞭解的原因。對於網絡上也有討論的另外兩種方法––錯誤推測法和因果圖法,則分別因爲可靠性較差和操作相對複雜而並沒有得到廣泛的應用。
  如何劃分測試用例的粒度?
  我們是不太可能在一個測試用例包含所有測試需求的,因爲衆多的功能以及不同的路徑組合將使這樣一個測試用例像巨無霸一般,完全不具有可操作性。––除非您的軟件所包含的功能真的又少又簡單,不過如果真的有這麼一個軟件,恐怕也沒有測試和發佈的必要了。
  當然,這也並不是要您走向另一個極端,爲需求中定義的每個特性或功能都提供一個甚至多個測試用例。這裏的關鍵,是要尋找一個合適的度。 筆者推薦的方法是:關注有效功能。
  有效功能:就是指在被測應用所涉及的實際業務中,當用戶在手工狀態下進行工作時,整個業務流程中對用戶來說,具有實際意義那些功能。這個功能的特徵是當我們把這個功能單獨從計算機軟件還原到用戶的原始手工狀態時,它的完成可以作爲用戶實際業務的一個階段性結束的標誌,而不是一旦從這個業務流程中獨立出來就失去了意義。而該業務完成後,可以爲其他用戶或業務提供所需要的信息。
  這裏區分“有效功能”的關鍵有如下兩個:
  1. 這個功能是可以還原到用戶原始的手工業務流程中去的。我們的計算機和軟件,都是爲了幫助用戶解決手工業務中一些煩瑣和低效的問題,而提出的一些忠實於原始工作方法或略有變通的解決方案,並不是要改變用戶全部的業務流程。所以,應該從用戶實際業務的角度來判斷功能是否有效。
  2. 這個功能是否可以標誌着用戶實際業務的一個階段性結束?並且這項業務完成之後,被完成的業務實體是否可以交付給其他用戶或業務以供完成下面的工作? 爲了方便理解,我們可以先看一下下面的例子。拿我們常見的財務軟件來說,當添加一張會計憑證時,通常是需要填寫會計科目,在使用計算機完成工作時,我們可以利用軟件的功能,從很多備選科目中選擇一個自己需要的科目,或者通過科目代碼來輸入科目。這項功能很有可能會作爲一個特性要求出現在軟件需求規格說明書中,那麼這個科目的選擇或輸入是不是一個有效功能呢?讓我們試着用上面規則來衡量一下。首先,這個功能在用戶手工業務處理過程中是存在的,不同的是這項功能是在用戶填寫憑證時,在自己的大腦中完成的––用戶會根據需要,在自己記憶的科目中選擇合適的填寫上去,這項功能節省了用戶在記憶大量會計科目時付出的額外勞動。我們可以認爲這個功能是爲用戶原來的工作提供了一種簡便的、變通的方法。那麼這項功能的完成對於用戶來說意味着什麼呢?我們從上面的描述中可以看到,用戶希望軟件提供的是可以添加一張完整的憑證這樣的功能,而不僅僅是方便填寫會計科目。填寫會計科目只是用戶在添加憑證時的一個步驟,單獨把這個功能提取出來對用戶來說沒有任何實際意義。對於業務流程下游的用戶,需要的也不僅僅只是一個會計科目的信息,而是一張包含了會計科目以及其他會計信息的完整的會計憑證,否則就無法進行下面的工作。這樣看來,這個功能並不是一個有效的功能,我們可以把它最爲需要測試的特性在測試需求中進行描述,卻不應該作爲一個單獨的測試用例出現在我們的測試用例集中。而我們在測試用例中真正關注的,應該是添加會計憑證這個具有實際意義的功能。另外,我們還需要關注如何將多個相互之間存在依賴關係的功能區分爲單個的有效功能。例如,現在有 A、B、C三個功能,其中B功能的開始必須依賴於A功能的完成,而且A功能如果出現不同的完成狀態,B功能也會做出不同的反應;C功能對B功能的依賴也是如此。那麼這時候,我們是否應當將三個相互依賴的功能包含在一個測試用例中呢?這樣的做法也不是不可以,但是我們也可以先判斷一下,這三個功能是否都是有效功能(您可以使用前面提到的方法來試着評判一下)?如果A、B、C都是獨立的有效功能,那麼我們可以從上面的描述中發現,它們之間存在的依賴性,可以理解爲是一種狀態或者說數據的依賴性。後一個功能關心的,是前一個功能最終提供給它的是什麼樣的“輸入”,而不是前一個功能到底作了些什麼。這樣看來,我們完全可以將它們分別包含在幾個獨立的測試用例中,而在每個測試用例的開始,把不同的輸入作爲不同前置條件來描述。
測試用例是否應該包含所有的細節?
  這是在網絡上聽到訴苦最多的又一個熱點問題:公司要求按照一個嚴格的規範來開展測試工作,必須書寫所有的測試用例文檔,要求文檔的書寫一定要具體,並在執行測試時要參考測試用例文檔來進行。如果測試用例文檔寫的過於簡略,則會被領導斥爲偷懶。但是,如果文檔中的對操作步驟描述的過於具體,像下面這樣:
  01.在“用戶名”項中輸入“user”;
  02.在“密碼”項中輸入“password”;
  03.點擊“確定”按鈕。 這樣的描述方式表面看起來可操作性似乎是增強了,任何人拿到這個文檔都可以充當測試人員,檢查一下這個功能是否存在缺陷。但是我們不要忘記,在開發過程中,變更的存在是必然的。一旦需求、設計或者應用程序中的某些細節發生了變化,比如“用戶名”變成了“操作員”,“密碼”變成了“口令”,“確定”變成了“登錄”,或者輸入項所接受的數據類型發生了變化,那麼同這部分內容相關的所有的測試用例都需要修改。否則,我們憑什麼可以保證這些描述不同的測試用例說的是同一樣東西?如果我們只有這麼一個測試用例,也許一切都不是問題,但是對於一個業務複雜、功能完整的系統,如果按照這樣的方法描述測試用例,最終要麼產生大量的測試用例文檔,要麼產生過長的單個文檔。無論是那一種,如果發生了類似於上面說的變化,維護文檔都將變成一次地獄式的體驗。這也是爲什麼在網絡上頻頻出現的這個問題,而且每次出現都會受到測試同行們的關注的原因。那麼這個問題應該任何解決呢?測試用例是不是把所有的流程寫出來就可以了呢?如何在減少測試用例文檔中包含過多瑣碎的細節的同時保證測試用例的可操作性呢?又有什麼方法可以提高我們維護測試用例文檔的效率呢?筆者的建議是:關注“測試思想”而不是關注操作步驟。要理解這個問題,首先要弄明白測試用例的作用。就像用例一樣,測試用例並不是用來描述具體的實現的,而是着重描述處理問題的思路––對於一項明確的測試內容進行測試的思路。作爲測試用例的設計人員,如何理解基本流和備選流?如何深入分析並找到所有需要覆蓋的路徑和需要檢查的特性?我們在測試用例中應該用容易理解的自然語言清晰的來描述我們將要如何進行測試,而不是簡單的把在應用程序上如何操作的煩瑣的步驟記錄下來。把測試用例設計當成填寫具體操作步驟的表格是人們對測試用例最大的誤解。傳統的測試用例文檔編寫有兩種方式。一種是填寫操作步驟列表:將在軟件上進行的操作步驟一步一步詳細的記錄下來,包括所有被操作的項目和相應的值。另一種是填寫測試矩陣:將被操作項作爲矩陣中的一個字段,而矩陣中的一條條記錄,則是這些字段的值。網絡上對於這兩種方式孰優孰劣的爭論,將大家錯誤的引導向了兩個極端:要麼採用 A,要麼採用B。而大家卻忽視了一點,對於工作方法的爭論,本質上同工具的爭論並不是一回事(例如曾經的VC、BCB之掙)。如果不同的方法各有優勢,我們完全可以通過變通的方法,把優勢的部分組合在一起來使用。 操作步驟列表的優勢在於對基本流和備選流進行分析後,它可以清晰的描述您的測試思路。而測試矩陣則更適合於用來存放測試數據,特別是那些需要人工賦予一個確定的值的特性。下面,我們來看一個例子,當然,這個例子同樣是杜撰的。?需求名稱:用戶登錄安全驗證需求描述:用戶登錄安全驗證是爲了保證所有登錄到系統中的用戶,都是由系統管理員預先在系統中設定的。使用系統中不存在的用戶名,或者用戶名輸入正確,但密碼輸入錯誤情況,都無法登錄到系統中。當用戶使用了不存在的用戶名或錯誤的密碼時,系統應分別給出適當的提示。如果用戶連續三次無法使用正確的用戶名和密碼登錄到系統,則系統應給出適當的提示,並退出當前程序。如果用戶使用正確的用戶名和密碼登錄到系統,則退出界面,轉到系統主界面。對於用戶登錄界面和程序主界面,請參考相應的 UI設計文檔。
  測試需求:
  01. 檢查能否使用正確的用戶名和密碼登錄到系統;
  02. 檢查能否使用錯誤的用戶名或密碼登錄到系統;
  03. 檢查使用錯誤的用戶名和密碼登錄失敗超過三次,是否會自動退出當前程序。
  測試用例:
 
序號  操作過程描述    
1  輸入用戶名。    
2  輸入密碼。    
3  確認登錄。  
 
序號  用戶名  密碼  預期結果    
1  正確的用戶名  正確的密碼  登錄到系統並轉到系統主界面    
2  正確的用戶名  錯誤的密碼  無法登錄到系統並提示密碼錯誤    
3  錯誤的用戶名  正確的密碼  無法登錄到系統並提示用戶名錯誤    
4  錯誤的用戶名  錯誤的密碼  無法登錄到系統並退出當前程序    
5  空用戶名  ……  ……  
     這個例子並不是按照 RUP提供的標準模板編寫的,它的目的只是要爲大家展示,用前面所講的方法,整理出來的測試需求和設計完成的測試用例到底是個什麼樣子。所以省略了很多細節,不過大家在實際編寫測試用例文檔的時候,可以根據自己的需要把相應的內容添加上去。同時,也可以在用戶名和密碼兩個字段中填寫準備使用的具體數據。 相信大家已經看到,在我們的例子中,測試需求同測試用例之間並非是一一對應的關係因爲一條測試需求未必是明確的對應到一個有效功能的(其實測試需求本身同軟件需求和用例之間也未必是一一對應的)。而我們的測試用例所關注的,應該是一個有效功能。不過您不用擔心,這種情況並不會增加您管理測試需求和測試用例的成本,現在市面上提供的測試工具中已經有些是專門用來維護軟件需求、測試需求同測試用例之間的關係的,並且它們提供的強大的視圖功能還可以讓您很容易的查看到測試用例對測試需求的覆蓋情況。對於例子中的測試用例文檔,已經被分成了兩個部分,一部分是描述了測試用例執行者所應遵循的操作過程,一部分則是在操作中需要使用到的測試數據。這樣做的原因是在我們的實際工作中,尤其是在進行功能測試時,很多時候都是使用雷同的操作過程和不同的測試數據來進行的。而使用上面的方法,可以不用再對原本在多個用例中重複出現的操作過程再次描述,而可以把更多的精力放到測試數據的設計和準備上。這樣作帶來的副產品,就是提高了測試用例的可維護性。怎麼?還有人對筆者的觀點持懷疑態度?那好吧,那麼我們來嘗試着證明一下。我們的郵遞員要在 5個城市內奔波,並且每個城市都有些郵件需要投遞,他需要找到可以一次走遍5個城市的所有路線。這聽起來似乎並不是太複雜,利用我們已有的數學知識,很容易就可以得到答案。但是對於我們要測試的內容,通常都會包含更多複雜的規則。 例如,我們有三個文本框,每個文本框每次都只能輸入一個英文大寫字母,允許輸入的值只包括: A、B、C三個字母,當三個文本框輸入不同的值的時候,我們不知道會發生什麼,也不知道它們之間是否會互相影響,所以需要您來設計可以覆蓋所有輸入情況的測試用例來測試它。 瞧,這很簡單不是嗎?如果我們希望每個測試用例在執行時一旦出現缺陷都可以很快的找到導致缺陷的原因,那麼最好的辦法就是每個測試用例只包括一個同其他測試用例不同的輸入值。那麼可供我們輸入的值都有哪些呢?嗯,對於每個文本框,都至少有 A、B、C三種已經聲明的不同的值,另外,我們還要考慮當文本框爲空、輸入空格、輸入非英文字符以及輸入A、B、C之外的英文字符的情況。那麼按照上面的方法,我們會有多少測試用例呢?答案是343個。這只是一個很簡單的例子,我們工作中遇到的軟件的業務規則和特性決不會比這少的,那會有多少個測試用例呢?God knows. 不過至少有一點可以肯定,我們無法在原有業務規則發生變化時高效的、無差錯的維護完343個測試用例。 但是如果使用我們前面所描述的方法,對於操作過程的改變,您只需要重新維護一次,而對測試數據的維護,也同樣是非常簡單的,而且並不會因爲連續大量修改時出現的錯誤導致測試用例本身出現歧意。?在將主要精力從“設計”操作步驟轉移到設計測試數據之後,我們還將從這種方法中獲得更大的益處––通過“逆向測試數據分析”來提高測試工作的整體效率。這種“逆向測試數據分析”的方法,是假設軟件中存在多個互相依賴的功能,而且這些功能中包含在“依賴鏈”最末端,並且不再被其他功能依賴的功能。在我們準備測試數據時,首先從這個“依賴鏈”最末端的功能開始,分析這個功能會對不同的輸入產生哪些不同的結果。然後將所有的輸入進行整理,分清哪些輸入是來源於其前一個功能的輸出。之後,對該功能的上一個功能進行同樣的分析,整理出所有的輸入和輸出,但是這個功能的輸出至少應該包含“依賴鏈”最末端功能接收到的全部輸入。繼續按照這樣的思路循環向上,直到到達“依賴鏈”開始端的功能。不知道您在工作中有沒有遇到這樣的情況:在對那些“依賴鏈”上的功能進行測試時,一開始並沒有嚴格的規範測試數據的使用,結果前一個功能測試時產生的數據根本無法在下面的工作中被很好的利用起來,反而因爲大量無效數據增加了後面功能的測試難度。最終不得不對每一個功能重新準備測試數據。大量的時間,浪費在了這些重複而低效的勞動上。?當然,如果希望可以進一步提高某個階段測試工作的效率,還可以考慮應用“設計測試過程”的方法。這裏所說的測試過程,指的是我們在執行測試時所設定的執行測試用例的先後順序。之所以這樣作,是因爲可以充分的利用不同功能之間的耦合性,儘量通過一次操作來檢查儘量多的內容,從而降低已完成工作的無效性或低效性,最終提高某個階段的整體工作效率。不過,這項工作同樣要求操作者必須對被測的系統所涉及的所有業務以及這些業務之間的關係都非常熟悉才行。?如果您正被測試工作的低效問題所困擾,那麼建議您嘗試一下上面的方法,希望會對您的工作有所幫助。
  如何評價測試用例的好壞?
  這部分內容的出現,完全是因爲不久前同幾個朋友的一次討論。當時大家都認爲對於一個測試用例好壞的評價,無外乎兩個標準:是否可以發現尚未發現的軟件缺陷?是否可以覆蓋全部的測試需求?但是後來發現這兩個標準對於一些問題是處理不了的。例如,對於一個質量非常好的軟件產品,存在的軟件缺陷異乎尋常的少,測試用例設計人員準備了大量的測試用例,已經完全覆蓋了測試需求,但是隻有很少一部分測試用例在執行時發現了缺陷,而其他用例都順利通過了。那麼是否就可以認爲順利通過的那部分測試用例不好呢?對於這個問題,筆者認爲不管是測試用例是否可以發現尚未發現的缺陷,還是測試用例對測試需求的覆蓋度,都是用來評估測試設計人員工作能力和經驗的標準,而對於如何評價測試用例的優劣,應該還有其他標準。當然,在不同的團隊中可能存在不同的標準,但下面兩條應該是適合於任何團隊的。 1.易用性。對於一個即熟悉測試工作,又熟悉被測應用的測試人員,應當可以花費 很少的時間就可以理解測試用例中表達的測試思路,並可以很快的執行完這個測試用例。 2.易維護性。當開發過程中的某些因素影響了測試需求,測試用例的作者或其他測試設 計人員,應該可以花費很少的時間就完成定位並維護所有相關測試用例的工作。
  一些題外話
  曾經有朋友問:如果測試用例同軟件的具體實現互相獨立,怎麼保證測試用例的可操作性呢?怎麼保證任何一個人都可以一拿到測試用例就可以直接上機執行測試呢?筆者的回答是:儘量不要讓這種事情發生。首先,筆者一直不贊同那種讓“任何人”都可以充當測試人員,按照手中測試用例執行測試的做法。因爲對於被測應用的全面瞭解和熟悉,是作爲一個測試人員最基本的要求––在前面的文字中對於軟件需求的熟悉也多次被強調。我們無法預知讓一個對軟件以及軟件所涉及的實際業務不夠熟悉的人,依靠一份他同樣不熟悉的操作步驟列表來執行測試會有什麼樣的結果。但是有一點可以明確,這就好像讓一個沒有醫學背景的人,僅僅依靠一本七年制本碩連讀的《內科學》教材來爲患者檢查是否患有心臟病,最終結果是患者承擔了全部的風險。其次,測試用例的本來目的是爲了描述我們的“測試思想”––也就是“怎樣測”,而是否可以熟練的操作被測應用,並不是在測試用例這個“對象”中所要考慮和保證的,應當剝離出來,作爲獨立的部分進行處理。而問題的關鍵,在於如何保證拿到測試用例的人有足夠的能力和經驗來執行測試,這完全可以通過公司內部對軟件及軟件所涉及的實際業務的培訓,或者軟件的操作手冊。總之,還是儘量不要隨意的加入“任何人”到測試工作中吧。

 

 

 

 

更多精彩內容請訪問          www.17testing.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章