如何設計一個“好的”測試用例?

在正式開始討論之前,我先跟你聊聊,什麼纔是“好的”測試用例,這個“好”又應該體現在哪些方面。這是一個看似簡單實則難以回答的問題,即使深入思考後,也很難有非常標準的答案。

通常,你的第一反應很可能會是“發現了軟件缺陷的測試用例就是好的用例”,我可能會反問你“如果說測試用例發現了缺陷就是好用例,那麼在該缺陷被修復後,同樣的用例難道就不是好用例了嗎?”。

你可能還會說“發現軟件缺陷可能性大的測試用例就是好用例”,這話看起來還是蠻有道理的,但是我同樣會反問你“你打算用什麼方法來量化測試用例發現缺陷的可能性?”。

類似地,你可能還會說“發現至今未被發現的軟件缺陷的測試用例就是好用例”,那麼我想問你的是:如何評估是否還存在未被發現的缺陷?如果軟件中根本就沒有錯誤了呢?

其實,是你定義“好的”測試用例的思路錯了,這就有點像“傻子吃燒餅”,連吃五個不飽,吃完第六個終於飽了,於是他說:早知道吃了第六個就會飽,何必吃前面五個呢。細想,他吃的六個燒餅其實是一個整體,一起吃下去纔會飽,而你無法找到吃一個就能飽的“好”燒餅。

對於測試用例其實也是同樣的道理,“好的”測試用例一定是一個完備的集合,它能夠覆蓋所有等價類以及各種邊界值,而跟能否發現缺陷無關。

我舉一個“池塘捕魚”的例子,可以幫你更好地理解什麼是“好的”測試用例。

如果把被測試軟件看作一個池塘,軟件缺陷是池塘中的魚,建立測試用例集的過程就像是在編織一張捕漁網。“好的”測試用例集就是一張能夠覆蓋整個池塘的大漁網,只要池塘裏有魚,這個大漁網就一定能把魚給撈上來。

如果漁網本身是完整的且合格的,那麼撈不到魚,就證明池塘中沒有魚,而漁網的好壞與池塘中是否有魚無關。

“好的”測試用例必須具備哪些特徵?

一個“好的”測試用例,必須具備以下三個特徵。

  1. 整體完備性: “好的”測試用例一定是一個完備的整體,是有效測試用例組成的集合,能夠完全覆蓋測試需求。

  2. 等價類劃分的準確性: 指的是對於每個等價類都能保證只要其中一個輸入測試通過,其他輸入也一定測試通過。

  3. 等價類集合的完備性: 需要保證所有可能的邊界值和邊界條件都已經正確識別。

做到了以上三點,就可以肯定測試是充分且完備的,即做到了完整的測試需求覆蓋。

三種最常用的測試用例設計方法

明白了“好的”測試用例的內涵和外延後,我再回過頭來給你講講,爲了能夠設計出“好的”測試用例,你通常都要使用哪些設計方法。

從理論層面來講,設計用例的方法有很多,如果你去翻閱測試圖書或網絡教程,會發現一堆讓人眼花繚亂的測試方法,比如等價類劃分法、邊界值分析法、錯誤推測方法、因果圖方法、判定表驅動分析法、正交實驗設計方法、功能圖分析方法、場景設計方法、形式化方法、擴展有限狀態機方法等等,但是從軟件企業實際的工程實踐來講,真正具有實用價值並且常用的只有前三種方法。

當然,對於那些與人的生命安全直接或間接相關的軟件,比如飛行控制、軌道交通的列車控制、醫療檢測相關的軟件或者系統,由於需要達到幾近變態的測試覆蓋率要求,會採用更多的測試設計方法。但對大多數的軟件測試而言,綜合使用等價類劃分、邊界值分析和錯誤推測這三大類方法就足夠了。

接下來,我會結合實際的例子,給你解釋一下這三類方法的核心概念以及在使用時需要注意的問題。

第一,等價類劃分方法

從上一篇文章中你已經知道了,等價類中任意一個輸入數據對於揭露程序中潛在錯誤都具有同等效果。後續我們只要從每個等價類中任意選取一個值進行測試,就可以用少量具有代表性的測試輸入取得較好的測試覆蓋結果

現在,我給你看一個具體的例子:學生信息系統中有一個“考試成績”的輸入項,成績的取值範圍是0~100之間的整數,考試成績及格的分數線是60。

爲了測試這個輸入項,顯然不可能用0~100的每一個數去測試。通過需求描述可以知道,輸入0~59之間的任意整數,以及輸入60~100之間的任意整數,去驗證和揭露輸入框的潛在缺陷可以看做是等價的。

那麼這就可以在0~59和60~100之間各隨機抽取一個整數來進行驗證。這樣的設計就構成了所謂的“有效等價類”。

你不要覺得進行到這裏,已經完成了等價類劃分的工作,因爲等價類劃分方法的另一個關鍵點是要找出所有“無效等價類”。顯然,如果輸入的成績是負數,或者是大於100的數等都構成了“無效等價類”。

在考慮了無效等價類後,最終設計的測試用例爲:

  • 有效等價類1:0~59之間的任意整數;
  • 有效等價類2:59~100之間的任意整數;
  • 無效等價類1:小於0的負數;
  • 無效等價類2:大於100的整數;
  • 無效等價類3:0~100之間的任何浮點數;
  • 無效等價類4:其他任意非數字字符。

第二,邊界值分析方法

邊界值分析是對等價類劃分的補充,你從工程實踐經驗中可以發現,大量的錯誤發生在輸入輸出的邊界值上,所以需要對邊界值進行重點測試,通常選取正好等於、剛剛大於或剛剛小於邊界的值作爲測試數據。

我們繼續看學生信息系統中“考試成績”的例子,選取的邊界值數據應該包括:-1,0,1,59,60,61,99,100,101。

第三,錯誤推測方法

錯誤推測方法是指基於對被測試軟件系統設計的理解、過往經驗以及個人直覺,推測出軟件可能存在的缺陷,從而有針對性地設計測試用例的方法。這個方法強調的是對被測試軟件的需求理解以及設計實現的細節把握,當然還有個人的能力。

錯誤推測法和目前非常流行的“探索式測試方法”的基本思想和理念是不謀而合的,這類方法在目前的敏捷開發模式下的投入產出比很高,因此被廣泛應用。但是,這個方法的缺點也顯而易見,那就是難以系統化,並且過度依賴個人能力。

比如,Web界面的GUI功能測試,需要考慮瀏覽器在有緩存和沒有緩存下的表現;Web Service的API測試,需要考慮被測API所依賴的第三方API出錯下的處理邏輯;對於代碼級的單元測試,需要考慮被測函數的輸入參數爲空情況下的內部處理邏輯等等。由此可見,這些測試用例的設計都是基於曾經遇到的問題而進行的錯誤推測,很大程度上取決於個人能力。

在軟件企業的具體實踐中,爲了降低對個人能力的依賴,通常會建立常見缺陷知識庫,在測試設計的過程中,會使用缺陷知識庫作爲檢查點列表(checklist),去幫助優化補充測試用例的設計。

對於中小企業,可能最初的方法就是建立一個簡單的wiki頁面,讓測試工程師完成測試用例的最初設計後對應這個wiki頁面先做一輪自檢,如果在後續測試中發現了新的點,就會繼續完善這個wiki頁面。

對於測試基礎架構比較成熟的中大型軟件企業,通常會以該缺陷知識庫作爲數據驅動測試的輸入來自動生成部分的測試數據,這部分內容我會在後面的文章中詳細介紹。

如何才能設計出“好的”測試用例?

掌握了最基本的三種設計測試用例的方法,你就相當於拿到了打仗所需要的槍支彈藥,接下來就是如何在實戰中用這些武器打個大勝仗了。

在真實的工程實踐中,不同的軟件項目在研發生命週期的各個階段都會有不同的測試類型。 比如,傳統軟件的開發階段通常會有單元測試,軟件模塊集成階段會有代碼級集成測試,打包部署後會有面向終端用戶的GUI測試;再比如,電商網站的測試會分爲服務器端基於API的測試、中間件測試、前端GUI測試等。

對於每一種不同的測試類型,設計出“好的”測試用例的關注點和方法論可能會有很大的差異, 有些可能採用黑盒方法,有些可能採用白盒方法,有些還會採用灰盒方法(比如,微服務架構中的測試),所以很難有一套放之四海而皆準的套路。

所以,在這篇文章中,我僅以最常見、最容易理解的面向終端用戶的GUI測試爲例,跟你聊聊如何才能設計一個“好的”測試用例。

面向終端用戶的GUI測試,最核心的測試點就是驗證軟件對需求的滿足程度,這就要求測試工程師對被測軟件的需求有深入的理解。在我看來,深入理解被測軟件需求的最好方法是,測試工程師在需求分析和設計階段就開始介入,因爲這個階段是理解和掌握軟件的原始業務需求的最好時機。

只有真正理解了原始業務需求之後,纔有可能從業務需求的角度去設計針對性明確、從終端用戶使用場景考慮的端到端(End-2-End)的測試用例集。這個階段的測試用例設計,主要目的是驗證各個業務需求是否被滿足,主要採用基於黑盒的測試設計方法。

在具體的用例設計時,首先需要搞清楚每一個業務需求所對應的多個軟件功能需求點,然後分析出每個軟件功能需求點對應的多個測試需求點,最後再針對每個測試需求點設計測試用例。

這個用例設計過程,你可能覺得有點繞,但是沒關係,我以“用戶登錄”功能的測試用例設計爲例,畫了一張圖來幫你理清這些概念之間的映射關係。

圖中的業務需求到軟件功能需求、軟件功能需求到測試需求,以及測試需求到測試用例的映射關係,在非互聯網軟件企業的實踐中,通常會使用需求追蹤管理工具(比如ALM、DOORS、JIRA、TestLink等)來管理,並以此來衡量測試用例對業務需求、軟件功能需求的覆蓋率。

具體到測試用例本身的設計,有兩個關鍵點需要你注意。

  1. 從軟件功能需求出發,全面地、無遺漏地識別出測試需求是至關重要的,這將直接關係到用例的測試覆蓋率。 比如,如果你沒有識別出用戶登錄功能的安全性測試需求,那麼後續設計的測試用例就完全不會涉及安全性,最終造成重要測試漏洞。

  2. 對於識別出的每個測試需求點,需要綜合運用等價類劃分、邊界值分析和錯誤推測方法來全面地設計測試用例。 這裏需要注意的是,要綜合運用這三種方法,並針對每個測試需求點的具體情況,進行靈活選擇。
    以“用戶登錄”的功能性測試需求爲例,你首先應該對“用戶名”和“密碼”這兩個輸入項分別進行等價類劃分,列出對應的有效等價類和無效等價類,對於無效等價類的識別可以採用錯誤猜測法(比如,用戶名包含特殊字符等),然後基於兩者可能的組合,設計出第一批測試用例。
    等價類劃分完後,你需要補充“用戶名”和“密碼”這兩個輸入項的邊界值的測試用例,比如用戶名爲空(NULL)、用戶名長度剛剛大於允許長度等。

用例設計的其他經驗

除了上面介紹的方法外,我再跟你分享三個獨家“祕籍”,希望能夠幫你設計出“好的”測試用例集。

  1. 只有深入理解被測試軟件的架構,你才能設計出“有的放矢”的測試用例集,去發現系統邊界以及系統集成上的潛在缺陷。
    作爲測試工程師,切忌不能把整個被測系統看作一個大黑盒,你必須對內部的架構有清楚的認識,比如數據庫連接方式、數據庫的讀寫分離、消息中間件Kafka的配置、緩存系統的層級分佈、第三方系統的集成等等。

  2. 必須深入理解被測軟件的設計與實現細節,深入理解軟件內部的處理邏輯。
    單單根據測試需求點設計的用例,只能覆蓋“表面”的一層,往往會覆蓋不到內部的處理流程、分支處理,而沒有覆蓋到的部分就很可能出現缺陷遺漏。在具體實踐中,你可以通過代碼覆蓋率指標找出可能的測試遺漏點。
    同時,切忌不要以開發代碼的實現爲依據設計測試用例。因爲開發代碼實現的錯誤會導致測試用例也出錯,所以你應該根據原始需求設計測試用例。

  3. 需要引入需求覆蓋率和代碼覆蓋率來衡量測試執行的完備性,並以此爲依據來找出遺漏的測試點。 關於什麼是需求覆蓋率和代碼覆蓋率,我會在後續的文章中詳細介紹。

總結

最後,我來簡單總結一下今天的主要內容。

首先,你需要明白,“好的”測試用例一定是一個完備的集合,它能夠覆蓋所有等價類以及各種邊界值,而能否發現軟件缺陷並不是衡量測試用例好壞的標準。

其次,設計測試用例的方法有很多種,但綜合運用等價類劃分、邊界值分析和錯誤推測方法,可以滿足絕大多數軟件測試用例設計的需求。

再次,“好的”測試用例在設計時,需要從軟件功能需求出發,全面地、無遺漏地識別出測試需求至關重要。

最後,如果想設計一個“好的”測試用例,你必須要深入理解被測軟件的架構設計,深入軟件內部的處理邏輯,需求覆蓋率和代碼覆蓋率這兩個指標可以幫你衡量測試執行的完備性。

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