軟件測試的真正目標是什么?為了研究這個問題,我隨機問了一些
javascript.:tagshow(event, '%C8%ED%BC%FE%BF%AA%B7%A2');" href="javascript.:;" target=_self>
軟件開發和測試工程師、管理人員。其中一些說目標是驗證軟件是否滿足用戶和產品的
需求。
其他的人給出了更簡單的回答,例如:“確認軟件沒有
Bugs”以及“為了驗證軟件能夠正常運轉”。 就我看來,這些說法都不準確。簡單來說,軟件測試的真正目的是找到以前沒有發現的
bug。1 下面我將從我對軟件測試目標的看法出發,剖析我同事關于軟件測試的主要目標的誤解,并給
測試人員一些建議。
誤解1:軟件測試的目的是為了確保沒有Bug
這種看法反映了一種對于軟件本質的樂觀但從根本上錯誤的觀點。一個簡單的事實就是不存在“bug-free”的軟件。
為什么是這樣呢?首先,在等式的開發一邊,你必須面對時刻在變化的技術,一個復雜的而且經常有缺陷的應用設計,集成新的已存在的系統帶來的困難,等等。人本身的錯誤也是一個很大的因素。雖然現代思維應用開發工具可以自動生成代碼,但是在有些地方人必須參與到開發過程中,而人是會犯錯誤的。
而在等式的測試這一邊,不可能讓你的產品在送到你的用戶以前運行所有可能的測試來檢測出每一個可能的bug。讓我們來看一個簡單的假定的例子。比如說你要測試一個這樣的程序:
接受3個整型的數值作為輸入,每一個數值的范圍在0到9之間。在2種操作系統下運行?梢栽L問存儲在3個不同廠商中任何一個提供的數據庫中的數據。我們計算一下,我們有1,000種可能的排列作為測試輸入。為了測試在每個操作系統上的每種排列,我們需要2,000個測試用例,另外再考慮到每種輸入在每個支持的數據庫運行一遍,我們需要6,000個測試用例。這個數字還沒有考慮到其他的測試情況,例如網絡故障,磁盤空間不足以及內存耗盡等等。所以實際上我們需要測試用例的數目要更大一些。
無疑,我們不得不接受這樣一個事實:我們只能生活在一個所有的軟件都有bug的世界當中。然而,我們沒有必要絕望。經過精心的計劃,我們可以選擇性地找出產品中最多出現危險以及對我們的用戶最重要的部分中的bug。下面是我發現的有效的一些步驟。
在你的計劃當中加入風險分析
正確理解你的客戶需求文檔本身就是一門科學(后面將會詳細講到)。如果你不能直接接觸到你的用戶--例如,通過客戶焦點小組,那么你就應該和你的客戶支持部門一起商討你的測試計劃,因為他們直接接觸到最終用戶。
要明白你的產品哪些部分處于危險當中同樣需要分析。變更是危險的主要來源;如果你引入了一個變更,你可能不注意地引入了一個新的bug或者發現一個已經存在的bug。因此,支持新功能的代碼一直是一個尋找危險的好地方。為了修正一個bug而修改的代碼也是這樣。而且,如果你在某個地方發現了bug,那么在附近潛藏著其他bug的可能性就很大。雖然你可能認為經過多年修正了很多bug的地方最后“清除干凈了”,這種想法只是在修正時發現了bug的根源的情況下才是正確的。如果bug的根源是糟糕的設計,而進行的修正只是一個簡單的補丁而不是從根本上解決這個問題,那么這個修正實際上可能引入了新的bug。另外,記。杭词故腔凇案驹颉钡男拚灿锌赡軙l基礎性變更,暴露其他嚴重bug。
理解產品是如何工作的--和為何可能出故障
對一些測試者來說,第一個想做的就是看產品外在的可見的“行為”--將精力集中在他們的產品客戶將看到的部分。這樣做效力有限,因為他們沒有清楚的理解產品程序的邏輯,數據流等等,這些是用戶不可見的。為了能夠理解產品是如何工作的,以及怎樣會出故障,你必須看“罩子下面”并且在你的測試中用到你看到的東西。
例如,如果你只看一個GUI,你可能看到程序通過一個格式化的HTML表格顯示一個特定的數據庫查詢的結果。然而,除非你知道這個表格的表示是一個Java數組對象,從服務器傳到客戶端,然后轉化為一個HTML表格,否則你就不會知道這里存在一個潛在的一個客戶端性能瓶頸的危險。如果一個用戶運行一個查詢,返回的記錄太多,就會導致客戶端在處理表格的時候像死機一樣。(我在幾年前是通過這樣的方法解決這個問題的:每次讓客戶端只接收一部分結果數據,并且明確地告訴用戶還有其他的數據未傳過來。)
如果有充足的時間設計和進行測試,你總是可以找到更多的bug。然而,如果那個bug好像對你的客戶影響不大,那就不值得花時間和精力去找到它。去搜索每一個可能導致系統在5,000年發生一次故障的bug是沒有意義的,因為那可能需要你花5,000年去運行所必要的測試。3 花時間去找出哪里可能藏有真正有影響的bug,并將測試集中于那些地方,會好很多。
理解客戶究竟會怎樣去使用產品
之前,我間接提到了通過直接接觸實際用戶或者通過你公司用戶服務部門去了解用戶需求的重要性。通過同樣的渠道,你也應該確認你的測試計劃是否反映了你用戶的系統配置,特殊需求以及吞吐/系統能力需求。
這也需要了解你的客戶的條件限制,這些限制將直接影響用戶怎樣使用你的產品。在我加入Rational');" href="javascript.:;" target=_self>Rational之前,我的工作是有關一個Internet防火墻,它能夠支持常被稱之為“split-brained DNS”功能網絡配置功能。這個功能使用戶能夠在他們的防火墻后面維護一個私有的DNS服務器。然而我們發現,一些內部DNS服務器被錯誤的配置了,在我們沒有更正他們的DNS 配置之前,無法使防火墻正常工作。最后我們不得不更改我們的安裝工具使得即使在用戶的內網斷了的情況下防火墻仍能夠正常運行。這樣我們就可以把修理他們的網絡當做一個獨立的(收費的)任務。
現在讓我們轉到第二個誤解。如果我們接受了bug-free軟件真的是不存在的這一觀念,我們可以通過運行測試找到故障,那么我們要測試到出故障,對嗎?但是如果測試中出故障是一個好事情,那么我們是否能夠把它叫做“失敗”呢?
誤解2:軟件測試的目的是為了驗證軟件能夠正常運轉
和第一個誤解一樣,這個說法也反映了一個對軟件測試完全樂觀的觀點。在我們一生的活動中,我們盡力去創造和建造能夠正常運行的事物,我們盡我們最大的努力去避免故障。然而,軟件測試人員必須有不同觀念:為了能夠成功,我們必須有意地盡量去促使故障的產生。4
如果我們不采用“不正當的”方法會發生什么?如果我們設計避免故障的測試,那么將會使我們的客戶失望。當你開發一個軟件應用程序的時候,你會清楚地了解應用程序所使用的數據類型,配置以及它能運行所需要的環境。你也知道程序的局限性。如果你的目標是驗證應用程序能夠工作,你就會限制你在數據、配置和應用程序最初設計所支持環境的邊界處測出故障的可能。如果你這樣做,你有較大的機會通過你所有的測試。然而在現實世界中,你的客戶很有可能會超越這些邊界并遇到你測試中沒有測出來的bug。
下面是一些要成為一個好的測試者所需要的可以使用的建議。
如果產品出現了故障,你就進行了一個成功的測試。
如果你在頭腦中保持測試的目標是為了發現一個bug這一觀念,那么你就可以開始考慮一個“成功”的測試就是讓軟件運行出現故障。不論你只是運行了一個測試還是運行了成千上萬次測試,即使你沒有發現bug,你的軟件仍然不能說沒有bug。bug仍然潛伏在測試沒有覆蓋到的領域。換句話說,要證明沒有bug是一件非常困難的事情,并且,我們前面提到過,你必須集中力量去找到產品中危險最大的領域中的bug。
不久前,我接受了一個產品的測試任務,在我之前這個產品已經經過了成百上千次測試。產品出來以后,他們所有人對產品的一些過去投入了幾年的工作的組件進行測試。然而,他們的測試很少甚至沒有涉及到感興趣的測試領域。雖然這種回歸測試有利于驗證新代碼的變更沒有導致一些舊的函數無法運行,但是我不得不在可能導致麻煩的區域設計新的測試。在 軟件測試的藝術,5 一書中,Glenford Myers用了一個醫學上的類比,如果你覺得不舒服去醫院檢查,但檢查的結果并不足以診斷病因,那能夠說這個檢查是“成功”的嗎?不!你還是有病,你的醫生必須再進行正確的檢查。
所有的使用者都會犯錯誤
在測試一個新的軟件應用程序的時候,看到不好的測試結果的人肯定要反對你的測試場景!皼]有人會那樣做!”。不要相信沒有這個。一些用戶會那樣做,或者做一些更糟的事情,并且他們不是有意那樣。你的工作就是在產品運送到客戶手里以前,考慮用戶會犯的錯誤中最壞的情況,并且確認你的產品仍然能夠安然無恙,沒有崩潰或者丟失數據。再說一遍,你要尋求的是那些能夠發現危險bug的測試故障。
讓我們再看一下我們之前討論的簡單程序,那個需要6,000次測試才能包括所有可能的程序。如果你要設計只在合法的輸入,環境,操作等情況下的測試,那么你的測試只涵蓋了對你系統運行來說最好的場景。但是,如果有些地方出錯會怎樣?如果用戶手指滑了一下,或者錯誤的配置了什么,或者刪除了非常重要的信息,你的軟件會怎樣表現?或者當一個系統/服務器出現掛起,或者出現達到一些資源的上限(比如內存,磁盤空間,數據庫記錄的ID等),會發生什么?當一些應該被標識為損壞的數據進入或者通過系統會怎么樣?如果操作中斷,系統處于含糊不清的狀態?或者如果太多的人在同樣的時間做同樣的事情?潛在錯誤的列表是無限的,并且如果你只想確認“它可以工作”的話,你可能就會忽略掉這些場景中的大部分。
結論
我希望這篇文章可以讓你確信軟件測試的真正目標是尋找bug。即使是在交付時間表很緊的情況下,采取一個步驟來想一下從哪里開始著手,你的測試將會是最有效率的。但即使在時間非常充足的情況下,你也不可能測試出每一個bug,所以你必須將你的測試劃分優先級,劃分的根據是基于產品目前的狀態(新的,修改的或者只是純漏洞)和對客戶的可能影響而進行的最誠實的評估。避免采用你知道軟件可以處理的測試數據和操作;你的任務是在測試中擴大軟件的邊界。在你設計自動化測試時,也要避免“踩滅”失敗條件的誤區。你的任務不是創造大量的總是可以干凈的成功運行的測試。你需要去尋找和理解故障條件。不要浪費時間去想你的軟件產品中是否存在bug。它肯定有bug,并且你不可能全部找出它們。你的組織和你的顧客指望你找出那些最有影響的bug。你必須要做的是,你要從消極的角度考慮這些問題。