關於軟件測試的問與答(與神仙的對話)

 

關於軟件測試的問與答(與神仙的對話)


  作爲芸芸衆程序員的一員,我對軟件開發中的一切都充滿問題。今天是關於測試,作爲一名唯物主義者,我相信衆物都有其神,於是我找到了測試之神。
  
  我問:神仙,爲什麼我們需要測試?
  大神用憐憫的眼神看着我,說到:我可憐的孩子,之所以需要測試,都是上帝的錯啊,上帝創造了你們,但是因爲沒有測試,所以你們都是不完美的、不理智的,你們會被情緒、環境左右,會犯錯。
  大神說這話的時候充滿了憐憫,當然,他對任何事情都充滿憐憫。我想,我該叫他憐憫之神。
  我說:哦,這麼說上帝也是不完美的,因爲他也需要測試?
  憐憫之神果然是神仙:咳咳,說到哪兒了,你吃飯了嗎?
  
  我問:我們需要測試,可是,爲什麼我看測試人員只是天天敲鍵盤而已啊?
  憐憫之神說:你敲鍵盤是在寫代碼,測試人員敲鍵盤是在獲取當前系統的信息,這兩者真正的工作都是那些腦力活動,是在敲擊鍵盤這個物理行爲之前以及伴隨這些物理行爲的腦力活動。如果你敲擊鍵盤的時候沒有進行思考,那麼你就不是在進行開發和測試;而且,如果你在思考但是沒有敲擊鍵盤,你還是可能在進行開發和測試。
   我說:關鍵是思考。
  憐憫之神說:是的。他顯然對後半句猶豫了一下,但是還是說了,人類一思考,我們就發笑。
  我想,一點都不好笑,連朝鮮都一比零小勝巴西了。我說,其實對軟件開發人員來說,我們也應該通過使用自己的產品來對它進行測試。
  憐憫之神點點頭,說,這叫做“吃自己的狗食”,如果你都對自己的產品感到擔心和鄙夷,別人爲什麼要買它?
  我說,可是,除非我們開發的是開發工具,否則我們根本不可能用它。地球人都知道,做減肥藥廣告的從來不喝減肥藥,買火腿腸的從來不吃火腿腸....人人都需要是化學家。
  憐憫之神說:所以完全由開發人員構成的測試樣本不太可能代表整個用戶羣。
  我自言自語道,所以我們需要測試人員,需要另一個角度的思考。
  
  我問:儘管測試人員測試了,但是爲什麼系統還是存在缺陷哩,難道他們不對所有可能性都進行測試的嗎?
  憐憫之神翻了我一個白眼,嘆了口氣。作爲報復,在下面的敘述中,我將稱他爲白眼之神。
  白眼之神說,對任何程序而言,可能進行的測試數據都是無限的。測試也許可以令人信服的表明存在缺陷,但是永遠無法表明不存在缺陷。
  我想了想,說,我們現在的系統需要導入客戶的遺留數據,光報表就多達20萬,如果一張張的校驗報表內容和樣式,那麼一定會死人的。
  白眼之神說,那你們是怎樣測試的哩?
  我說,抽取樣本測試哈。我說,我明白了,由於我們無法測試所有的可能性,那麼任何測試實際上都是某種程度的樣本測試,這些樣本以某種方式代表整個可能測試集合的一個部分或者片段。
  白眼之神點點頭,說,測試只是採樣!
  我說,正像我們去醫院體檢,所有化驗單上都寫着,本結果只對該樣本負責。
  白眼之神說,實際上,採樣也是一個心理過程,而且是一個感性過程,令某人滿意的樣本也許會讓另外一個覺得一點都不滿意。
  我說,由於不可能進行窮舉測試,所以我們往往在兩個目標間徘徊:希望測試能夠覆蓋所有令人感興趣的條件,希望測試集減少到可以管理和承受的程度。就像吃自助餐,希望吃到所有東西,但是又要不把肚皮撐破。
  白眼之神說,所以我們需要儘可能選擇那些具有最強代表性的樣本進行測試,而這是測試人員的優勢。另外,多樣化樣本發現的問題可能超過大樣本發現的問題,同樣,測試團隊多樣化也可能發現更多的問題。
  我說,是的,同樣是抽血,一些人會要求早上不吃飯抽取靜脈血,一些人則需要間隔取幾次血。
  
  我問:開發中,我們採用了TDD的方式,我們單元功能測試的覆蓋率也很不錯,這樣,我想我們可以減少測試人員?減少系統測試?
  神說,你會因爲一架飛機保證它所有的部件在組裝前都進行了測試而乘坐它的處女航嗎?
  我說,哦,羅老號發射失敗了。
  神說,但是,良好的單元功能測試能夠爲系統測試去除噪音。
  我說,缺陷都不是自己鑽進去的,而是開發人員放前去的。單元功能測試能夠在一定程度上阻擋開發過程中缺陷的進入,同時阻擋一些簡單的缺陷,系統測試不能捕獲所有缺陷,相對單元功能測試,系統測試會花費更長的時間和成本,這些時間和成本能夠通過單元功能測試得到部分節約。
  神說,開發人員的測試保證了他對需求的理解和實現的一致,但是開發人員對需求的理解和真正的需求一定一致嗎?
  我說,所以需要測試人員即時驗收。
  神說,另外,關於TDD,從心理學的角度說,一個人是很難發現自己的錯誤的,所以TDD和結對編程一起實踐會有比較好的效果。
  
  我問:爲什麼很多項目最後的集成測試階段會那麼長哩?這總是導致我們的項目延期,而幾乎所有的項目都會延期。
  神說,說說你們的集成測試階段都在做些什麼?
  我說,噢,我們拉出一個發佈分支,凍結代碼提交,開始進行測試,找出缺陷,查明缺陷原因,根據重要性修改缺陷,然後重新測試,以此循環。恩,問題在於此時總會發現大量缺陷,並且我們每修復一些缺陷總會引入新的缺陷,所以這個時間拉得很長。
  神說,修復缺陷的同時引入新缺陷,這叫做故障反饋率(FFR),也就是一個修復讓系統中產生了另一個缺陷的情況所佔的百分比。這個數值如果在50%以下就很幸福了,另外,壓力和試圖提高缺陷修復速度都會提高FFR。
  我說,也就是修復缺陷的同時引入新缺陷是個正常情況。恩,可是我的問題是爲什麼最後的測試階段需要花費這麼長時間?
  神說,難道你不覺得是你們經理錯誤的估計了最後集成測試階段所應該花費的時間?
  我說,噢!
  神說,此外,測試不等於除錯。
  我想了想,說,是的,說的是最後集成測試階段,但實際上包含了兩個行爲:測試和除錯,相比測試,除錯佔據了更多時間。恩,我們現在的一個項目特性,由於開發時沒有考慮性能問題,導致上線前花費了大量時間進行調優。
  神說,項目延期的主要問題在於測試推遲。
  我說,是的,這個給我的印象很深,如果在開發階段就進行大數據的測試,那麼會節省很多時間。一個缺陷,發現的越晚,修復的成本就越高。
  神說,要測試先行,並且測試往往在項目開始開發前都已經開始了,測試需要貫穿於整個開發過程,頻繁進行,而是不推遲到最後的集成測試階段。TDD和持續集成是很不錯的實踐,但是它們僅僅是測試中的一部分。
  
  我說,那麼,測試保證了質量。
  神說,三鹿沒有測試嗎?
  我說,....
  神說,測試只是提供信息。至於這些信息的定義、重要性以及所要採取的反應都取決於人,而人做出的決定都是感性的,利益驅動的。
  神說,如果開發的產品本身就質量低劣,進行測試你不覺得是浪費大家的時間嗎?對低劣的代碼測試得再好又有什麼用呢?一段時間發現的缺陷越多,並不意味着剩下的缺陷越少,而總是意味着會出現更多的缺陷。
  我說,我明白了,測試只是收集信息,除此之外,並不能做其他任何事情。正如我們去體檢,體檢報告只能反映出當時我們的身體狀態,至於健不健康,則取決於我們平時的生活習慣,這是兩個分開的事情,體檢並不保證我的健康。
  神說,很多大公司非常看重測試部門,原因其實是他們無法看清楚他們自己的開發過程,於是只能從測試裏獲取信息,而這些信息對整個軟件開發來說只是一部分而已。我看到過有項目經理向測試人員詢問是否可以交付,這根本上就是在推卸責任,信息和作出決定根本是兩回事,更何況測試收集的信息只是部分信息呢,如果是這樣,不如讓測試人員來當經理好了。
  我說,怪不得每次去檢查身體問化驗醫師有沒有問題正不正常,化驗醫師總是不耐煩的說去問醫生呢。
  
  我問:什麼測試纔是良好的測試呢?
  神說,你覺得呢?
  我說,測試的目的是發現缺陷,所以發現的缺陷越多,那麼測試越好。
  神說,然後呢?
  我說,我會告訴測試人員,啊哈,你們發現的缺陷越多,我就發給你們越多的獎金。
  神說,又是一個糟糕管理的絕佳範例。
  我說,確實會有問題,這樣對測試人員來說,一個低劣的系統對他們的價值最高,他們會愛上那些糟糕的開發人員,引發辦公室戀情。這和整個團隊的目標-交付高質量的系統矛盾,並會在開發部門和測試部門之間引起矛盾和爭執。還有,發現的缺陷會增加,但是獲得信息的質量卻降低了。
  神說,你混淆了測試的目的,測試的目的不是發現缺陷,而是獲取我們所需要的信息。作爲對比,如果你所有體檢的項目都正常,你會覺得體檢沒有價值嗎?
  我說,恩,我會很高興。
  神說,測試只是採樣,所以良好的測試需要能夠根據上下文覆蓋系統中最重要的部分,而且又不能膨脹到不可管理的地步。
  我說,想起來了,我們在體檢的時候往往會有不同的檢查套餐,例如針對白領的,會着重檢查胃和頸椎;針對40歲以上人羣的,會增加癌症因子篩查。也就是測試並不是一個孤立的行爲,它需要根據不同的情況採取不同的策略。而且,我們總希望體檢時不用花太多的錢。
  神說,“良好”並不是屬於某個測試的屬性,它只能是測試、實現、成本和應用場景四者之間關係的屬性。
  我說,無法衡量測試?
  神說,作爲比較,系統上線後用戶的使用也可以看做是測試的繼續。
  我說,你的意思是我們可以對系統在使用中出現的缺陷加以追蹤,然後進行統計和分析,例如測試比較典型的遺漏了哪種缺陷,而哪種測試實際上是沒有太多必要的,因爲用戶根本都沒有使用該功能。這樣,以後我們就可以對測試加以改進。
  
  我問:那麼,我們需要對所有缺陷都跟蹤記錄?
  神說,你們沒有對所有缺陷都跟蹤記錄?
  我說,有些缺陷太小了,例如拼寫錯誤,有些缺陷很容易就修復,所以測試人員就直接和我們說了,沒有填寫缺陷記錄。
  神說,你怎麼看?
  我說,我覺得還不錯,沒有一個開發人員願意自己的程序裏出現錯誤,我們往往把程序看成了自己的擴展,指出程序有錯誤就是在指出我有錯誤,所以,對於一些很小、由於疏忽引起的錯誤,測試人員直接和我說而不記錄讓我感覺好一些。
  神說,缺陷只有在系統交付後才成爲錯誤。
  我說,好吧,可是報告我的程序出現缺陷會讓我受到批評。
  神說,那是另外一個關於團隊管理的問題了。如果一個人花在指責其他人上面的時間越多,那麼解決該問題的可能性就越低。
  我說,可是,我們應該反對文檔,文檔阻礙了交流,實際上沒有太大的價值。
  神說,文檔在不使用的情況下纔沒有價值。一些人反對的不是文檔,而是自己寫文檔。信息在文檔化之後才能被追蹤和統計,特別是作爲項目信息一部分的缺陷信息,它反映了項目的狀態,一定不能夠被忽略,如果爲了“節省時間”和“面子”而不記錄缺陷,那麼導致的結果就是項目狀態的丟失,會給項目後續的判斷帶來影響,以後會浪費更多的時間和金錢。
  我說,我想起來了,每次去取體檢結果時,我都會看到本次體檢指標與歷次的對比,這次的結果提醒我膽固醇又提高了,頸椎則好了很多,所以要少吃肥肉多鍛鍊,同時曉慶教我的頸椎病鍛鍊要繼續堅持。
  
  我問:收集信息似乎只是第一步,信息的處理過程又是怎樣的呢?
  神說,你們是怎麼做的呢?
  我說,首先,測試人員會選擇樣本對系統進行測試。比如發現系統不能上傳圖片了,測試人員會報告一個缺陷,記錄下詳細的信息。
  神說,這是第一步,攝取信息,此時,信息在被人確定含義之前是沒有意義的。
  我說,接着,我們會看到這個缺陷報告,並和測試人員進行交流。測試人員表示了擔憂,因爲上傳圖片對客戶來說是一個很重要的功能,現在連它都不能正常工作是否意味着系統的其他部分也存在很多問題。
  神說,測試人員在給信息賦予含義。
  我說,我們和測試人員一起重現了這個缺陷,系統報出的問題是權限認證失敗,我們認爲這是一個權限方面的問題,上傳圖片的其餘功能應該不受影響,也許是有人改動過當前測試用戶的權限,也有可能是上一次提交破壞了什麼東西,總之影響不會很大,因爲這塊有很多的單元功能測試,如果是提交破壞,也應該是頁面上的代碼,這段代碼不多,錯誤能夠很快定位和修復。
  神說,你們在給信息賦予含義,不同的人會給信息確定不同的含義。
  我說,接下來,我們會討論這個缺陷的優先級。測試人員認爲這個缺陷很重要,應該立刻修復;我們認爲這個缺陷雖然重要,但是非常容易修復,並且此時有另外一個非常重要的缺陷需要修復;項目經理詢問了我們各自對這個缺陷的理解,說,我們現在有一個特別重要的關於圖片搜索的缺陷需要修復,我認爲這個缺陷最重要,因爲後天需要給客戶的老闆進行演示,上傳圖片的功能也很重要,但是不在演示的範圍之內,但是既然很容易定位,我們也可以迅速的查明引起問題的原因,但是不修復。
  神說,現在在確定信息的重要性,並做出反應。不同的人會給信息確定不同的重要性。
  我說,那麼完整的過程應該是:攝取信息->確定含義->確定重要性->做出反應。
  神說,是的。
  我說,等等,我看到問題了。因爲不同的人會確定不同的含義,不同的人會確定不同的重要性,所以對做出決定的人來說,他一定要有自己的理解和權衡,並根據自己的重要性和其他信息最終做出決定。但是現實情況卻並非如此,很多信息在提供給管理者之前已經被信息提供者賦予了他所定義的含義和重要性,而管理者由於不能獲取其他信息或乾脆就沒有思考,所以就直接根據信息提供者所定義的含義和重要性做出決定了。
  神說,你想到了什麼?
  我說,忠臣、奸臣和昏君。其實沒有忠臣和姦臣,只有昏君。看似管理者高高在上,手握生殺大權,但其實權利早就被信息提供者瓜分殆盡了。
  神說,你扯遠了。
  
  我問:好吧,下一個問題是如何避免測試困難呢?
  神說,你覺得是大的系統容易測試還是小的系統容易測試?
  我說,當然是小的系統容易測試。
  神說,那麼,讓系統儘可能的小。
  我說,現在一個普通遊戲都要好幾個G。
  神說,第一,讓需求受控。這是一項很重要的管理工作,如果沒有很好的完成這項工作,那麼就是管理上的失敗。
  我說,這似乎很困難,因爲客戶總是在要求我們加功能,而有些功能確實是很重要的。
  神說,如果在項目後期要求增加功能,而這項功能又是必需的,那麼實際上是在告訴我們需求分析出現了問題,出現了需求遺漏。而一項功能如果最終因爲各種原因其實不能使用,那麼也是需求分析出現了問題,出現了需求冒進,脫離了實際情況。
  神說,要控制需求的增長,就需要決策者、需求分析人員和客戶來區分某件事對客戶來說真的是必需的,需要價值驅動。
  我說,第二呢?
  神說,第二,不要試圖在軟件中處理所有的可能情況。
  我說,這個我有印象,我們需要向新系統中導入遺留報表,由於遺留數據跨越十年,所以存在很小一部分不規範的網頁,如果在程序裏包含對所有報表的處理,那麼是相當困難的事情,最後我們選擇了手動處理這部分數據。
  神說,第三,代碼質量。最好的實現永遠是最簡潔的代碼,要儘量減少代碼的複雜性。兩個具有相同物理規模的程序在內部複雜性上可能有極大的不同,而這最終會是決定測試工作難度的主要因素。
  我說,我們可以通過增量構建,不一次做所有事來控制代碼的複雜性。
  神說,此外要注意組件之間的分離,特別是多團隊協作的項目。
  我說,是這樣的,對於大型項目,往往會劃分以模塊爲單位的小組開發,小組之間、模塊之間要儘量減少依賴和不必要的溝通,因此代碼可以有冗餘,每個開發小組都要各自獨立,有自己的分析人員、開發人員和測試人員。
  提到增量構建,我又有了新的問題。
  
  我問:我們現在採用迭代式開發,那麼每次迭代完成後對客戶的演示能不能算是用戶驗收測試呢?
   神說,演示不是測試。
   我說,客戶觸摸到了真實的系統,直觀瞭解到了系統的功能和使用方式,獲取了系統信息,然後進行反饋,這可以看作是部分用戶驗收測試。
   神說,對客戶來說,如果沒有真正的使用該系統,那麼就沒有進行測試。此外,客戶獲取的信息難道不是你們準備好的嗎?
   我說,是這樣,演示之前我們會進行很多準備工作。
   神說,實際上是在準備客戶能夠獲取的信息。
   我說,那麼最理想的迭代開發應該是持續部署?
   神說,持續部署和持續增量使用。


轉自豆瓣:http://book.douban.com/review/4594239/

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