1、軟件測試中的“黑天鵝” 幾年前,我帶領的一個測試小組遺漏了一個嚴重的bug到網上,當用戶反饋這個bug后,我們對它進行了深入的分析和重現,最終所有人一致認為,這個bug能夠發生實在是機緣巧合,因為它需要多個條件同時發生才有可能觸發,比如“XX算法開關必須打開、XX算法開關又必須關閉、XX參數必須取某個特定值、用戶的使用環境必須是XX個場景、硬件必須是使用XX接口板、軟件必須是XX版本、XX的帶寬恰巧又不夠。。。”,在用戶那里,這些條件有一條不滿足,就不會發生這個bug。 由于這個bug的影響比較嚴重,又是用戶報告的,照例要提交缺陷根因分析報告。其中,報告里有一項“后續如何發現這類缺陷,確保不遺漏?”我們不知道如何避免這樣的缺陷再次發生,實際上,如果從正向設計的角度,我們無論如何也不會設計一個滿足上述所有條件的用例,也不會去執行這樣的測試。不過,我們不得不費盡心思地去思考,這個bug的發生是如何有其合理性的、是可以解釋的、因此也是可以預防的,以填補報告里這一項的空白。 前不久我閱讀了一本書叫做《黑天鵝》。數千年來,人們認為世界上只有白天鵝,但是發現第一只澳大利亞黑天鵝以后,這種牢不可破的觀念被顛覆了。作者指出“黑天鵝事件”滿足三個特征: - 稀有性,或意外性,即它通常在預期之外; - 沖擊性,即它會產生極端影響; - 事后(而不是事前)可預測性,人的本性促使我們在事后為它的發生編織理由,并且或多或少地認為它是可解釋和可預測的。 很多重要的線上bug不就是測試中的“黑天鵝”嗎?它們的發生在你的預期之外、產生了極端的影響、事后人們總是認為這些bug是可以避免的。 仔細想一想,你所在的項目中是否有“黑天鵝”?2013年1月 31日,亞馬遜主頁癱瘓近1小時,你是否提前預期到了(《黑天鵝》書中寫到,“從對稱的角度講,一個高度不可能事情的發生,與一個高度可能事件的不發生是一樣的”)?12306網站的癱瘓、高鐵事故、ATM取款系統故障。。。,你是否能提前預期到?其實,你可能已經發現,“黑天鵝”離我們并不遙遠,總是有那么多被認為不應該發生的現象實際發生了。 造成“黑天鵝”現象的可能有很多種原因,從測試的角度講,我們如何來認識軟件測試中的“黑天鵝” – 那些總是讓人意想不到又產生嚴重后果的bug呢? 2、對“黑天鵝”視而不見 人們習 慣于對“黑天鵝”視而不見。“社會學家一直錯誤地以為他們的理論能夠衡量不確定的事物”。人們相信通過使用趨勢分析工具和復雜的數學公式可以幫助我們很好地預測股票市場的風險、挑選一支好的股票,結果大失所望的人不在少數;人們相信復雜的科學儀器和先進的數學、物理學、天文學等理論可以幫助我們很好地預測地震、海嘯、天氣,結果經常有令人意想不到的自然災害發生。 人們習慣于使用確定性的理論去推測那些不確定的事物,在這個處處都充滿了“變數”的時代,“以不變應萬變”的做法已不合適。RBT(基于風險的測試)是個不錯的方法,有些人會按照既定的套路使用RBT:在項目的某個時間點,邀請相關人一起收集風險、分析風險,然后按照風險分析結果開展測試活動。但是風險是時刻變化的、風險是不能確定的,你不可能提前預期所有的風險,你得學會“以動制動”,動態地、持續地應用RBT技術。哪怕如此,你仍然無法避免所有的風險,仍然會有“黑天鵝”發生,因為軟件測試的過程充滿了隨機性。 ReqBT(基于需求的測試)是個至少從數學上說很嚴謹的測試技術,它會用因果圖的方法把業務中的每一個原子邏輯規則都表達出來。ReqBT的創始人Richard Bender認為只要使用了ReqBT方法,不會遺漏一個從黑盒角度講、功能上的、業務邏輯相關的、嚴重的bug。我深知這套方法的妙處,但仍然對如上的陳述有所懷疑,原因無他,測試中的不確定性太多,沒有哪個確定性的理論是銀彈,可以保證沒有某類的“黑天鵝”發生。 但這并不表示這些形式或模式確定類的技術沒有任何用處、只要使用不確定性的技術比如ET(探索性測試)、RST(快速軟件測試)等就好了。應該說,這些確定性的方法(RBT、ReqBT等)和不確定性的方法(ET、 RST等)結合起來使用的話,“動靜結合”,會更有效地減少測試中“黑天鵝”的發生。 3、判斷是否是“黑天鵝” 想知道哪些重要的軟件缺陷是“黑天鵝”,哪些不是?只要問一問,這些bug與出現之前所預期的相比較,是否是在預料之中的? 我們會發現,這些重要的bug大體可以分為兩類:一類是可以預期發生的,但是并沒有采取及時的措施去規避;一類是不被預期發生的,認為不應該發生這種缺陷。這就啟發我們在做RCA(缺陷根因分析)時,對不同類bug的分析會帶來不同的收獲。 分析可以預期發生的嚴重缺陷,可以很好地幫助我們改進已經在實施的確定類方法或技術中的不足。比如在實施RBT過程中,為什么沒有識別出某個風險?或者為什么對風險級別的估計不足?或者為什么沒有對已知的風險采取風險規避措施?再比如在應用MBT(基于模型的測試技術)過程中,為什么某一個因子在建模時被遺漏了?或者為什么基于模型生成測試條件或測試用例時某個重要的參數被忽略掉了?再比如按照企業既定的流程管理軟件測試的過程中,為什么在測試策略或測試方案中忽略了這一風險?或者為什么在測試分析和測試設計中沒有覆蓋這個風險點?或者為什么在測試執行環節沒有發現這個缺陷?等等。通過這樣對的RCA過程,可以更好地幫助我們改善既有的測試方法或流程。 分析不被預期發生的嚴重缺陷,可以為我們開展不確定類測試方法或技術提供更多的輸入和想法。例如本文開篇所舉的那個關于某算法失效的例子,想通過確定類的測試方法、正向的方式提前設計(也就是預期)相關的測試用例,基本不大可能。相反,我們換一個角度,也許在ET中探索出這個缺陷的幾率更大一些,比如適當增加與用戶應用環境相關的各種因子組合的復雜場景測試的 session。 《黑天鵝》是一本關于不確定性的書。“有兩種認識現象的方式。第一種排除不正常的現象,只關注正?,F象。研究者不理會意外事件,只研究正常案例。第二種方法則認為,為了理解這一現象,人們需要首先考慮極端現象,尤其是當它們有非同尋常的效應累積的時候,比如黑天鵝現象。”對于測試而言,如果希望了解我們的不足,這兩類缺陷(可以被預期的缺陷和不可以被預期的缺陷)都要分析。 4、我們所不知道的更有意義 “黑天鵝的邏輯是,你不知道的事比你知道的事更有意義,因為許多黑天鵝事件正是由于它們不被預期而發生和加劇的。”作者認為現在的世界由不確定性主導,不論這個結論正確與否,單就測試而言,這個結論是非常適用的,軟件測試是由不確定性主導的。測試就是尋找未知的過程,這些未知的事情包括未知的缺陷、未知的被測對象的質量狀況、未知的真實的被測對象是什么樣的以及所有那些你認為你已經知道的但實際上是你不知道的軟件相關的信息,這些未知給予測試挑戰的同時也賦予測試很大的意義。 可以這樣說,所有的測試用例都是基于測試人員已知的知識設計出來的,執行這些用例有機會發現那些能夠被預期的缺陷;而測試中的“黑天鵝”- 那些重要的不被預期的缺陷,有多少是由測試用例發現的? 分析每一只“黑天鵝”,會幫助我們發現那些原本對于我們是“未知”的東西,每一只“黑天鵝”的遺漏,都是由于一些“未知”的因素,或者是未知的知識或信息、或者是不知道某些信息的重要程度而加以重視。下一次測試中,就會有意識地盡量拓寬我們的已知領域,減少“黑天鵝”發生的次數。 探索性測試在拓寬“已知領域”方面功不可沒。當我們需要探索時、當我們不知道下一步測試什么時、當我們想要獲得更多的想法時,我們使用探索性測試,ET有助于拓寬我們的測試深度和測試寬度,盡可能擴大已知領域的邊界,縮小我們未知的領域。 5、結論 你看到一個后果很嚴重的缺陷,正是由于你認為它不應該發生?這是不是很奇怪?不管你采用什么樣的測試方法、你的測試團隊有多么強大、你在測試上投入了多少人力物力,測試中的“黑天鵝”總會發生。 作者在《黑天鵝》書中指出人性的一個弱點:“習慣于學習精確的東西,而不是總體的東西”,并且把“由于只關注那些純粹而有明確定義的‘形式’而導致的錯誤”稱為‘柏拉圖化’”。測試的柏拉圖化思想會讓你只關注外在的形式,例如測試的流程是否遵守、測試的模板是否應用、測試方法的具體步驟是否實施,而開始忽略其他不那們具體不那么明確不那么美好和解釋得清的事務,忽略那些顯得有些混亂和不可琢磨的事務,比如在有些人眼里,探索性測試不容易管理、不好解釋給別人、步驟不那么明確、有太多不可琢磨的東西在里面。 就像敏捷里承認變化總會存在而去擁抱變化一樣,我們也應該正視測試中“黑天鵝”現象的存在,并盡最大可能地多嘗試以減少“黑天鵝”發生的機會(拓展已知領域、減少未知領域),并且一旦“黑天鵝”發生了盡最大可能地把握黑天鵝機會(分析那些未知點,更好地應用不確定類的方法,尋求測試改進)。 1. 歷史與三重迷霧 在“認識軟件測試中黑天鵝”一文中,我描述了什么是軟件測試中的黑天鵝及其特點,本文將探討測試中的黑天鵝發生之前、之后、以及正在發生之中的故事。 《黑天鵝》一書的作者Nassim指出“歷史是模糊的。你看到了結果,但看不到導致歷史事件發生的幕后原因。”其實,測試何嘗不是這樣,假如把測試看成一個盒子,這個盒子也是模糊的,你看不到盒子里面是什么,整個機制是如何運行的。 書中描述:“對待歷史問題,人類思維會犯三個毛病,我稱之為三重迷霧。他們是: --假想的理解,也就是人們都以為自己知道在一個超出他們認知的更為復雜(或更具隨機性)的世界中正在發生什么。 --反省的偏差,也就是我們只能在事后評價事務,就像只能從后視鏡里看東西(歷史在歷史書中比在經驗現實中顯得更加清晰和有調理)。 --高估事實性信息的價值,同時權威和飽學之士本身有缺陷,尤其是在他們進行分類的時候,也就是進行‘柏拉圖化’的時候。” 我很容易聯想到,這三重迷霧分別對應測試中的黑天鵝發生之前、之后、以及黑天鵝形成之中的故事,即:發生之前的“盲目預測”、發生之后的“假想解釋”、以及黑天鵝形成之中的“柏拉圖化”。 2. 黑天鵝發生之前的“盲目預測” “第一重迷霧就是我們以為我們生活的這個世界比它實際上更加可理解、可解釋、可預測”。打開收音機或電視機,你就會聽到或看到,每天都有無數的人在信心滿滿地預測著各種各樣的事情:股市的走勢、房價的走勢、戰爭是否會爆發、疾病是否會流行…… 正向Nassim指出的那樣,“幾乎所有關心事態發展的人似乎都確信自己明白正在發生什么。每一天都發生著完全出乎他們預料的事情,但他們就是認識不到自己沒有預測到這些事。很多發生過的事情本來應該被認為是完全瘋狂的,但在事情發生之后,看上去就沒有那么瘋狂。這種事后合理性在表面上降低了事件的稀有性,并使事件看上去具有可理解性。”就拿我所生活的這座城市-上海來說,近來的許多事件都在證實著這點:黃浦江上打撈出數千頭病死豬、H7N9的流行,昨天突然看到一條“上海自來水中添加了XX”的微博更是令人觸目驚心,我們內心都預測這些事情不應該發生,可是實際上卻發生了。 這種黑天鵝發生之前的“盲目預測”讓我想到軟件測試中版本發布之前的“測試評估(test evaluation)”。一個產品經過測試團隊的集中測試后,發布到用戶那里,誰能準確預測是否會出現“黑天鵝”呢?在你的團隊,在版本對外發布之前,是否需要測試團隊填寫一個關于產品質量的測試評估表?下圖是測試評估表的一個樣例。
這里的特性指的是“測試特性(test feature)”。根據各團隊上下文的不同,這個測試特性可能與開發特性直接對應,也可能不與開發特性一一對應,每個測試特性對應一條到多條需求(用戶需求或系統設計需求)。我最??匆姷馁|量評估說明是“XX特性基本功能正常。”有些人會在后面附上所發現的比較嚴重的bug。這樣的描述顯然并不令人滿意。 問題是: 每個特性質量的A/B/C/D的結論是否準確?所有特性的A/B /C/D的結論加一起又如何判別整個系統的質量?是否所有特性的質量都是A或B,版本就可以對外發布,并且發布以后不會出現令人意想不到的“黑天鵝”現象?測試人員給出的A/B/C/D有多大成分是基于一種feeling給出的? 對于任何一條需求,開發人員的任務就是實現它,無論是由一個項目組實現,還是多個項目組配合實現。但是,對于測試人員,考慮的事情就復雜一些。我們除了要驗證這條需求本身的功能實現是否正確,還要驗證該需求和其它功能之間的交互,還要考慮客戶可能使用的各種場景(Scenario),包括各種組網場景、各種參數的配置等。如果把測試場景和測試特性交互起來,測試就無窮無盡了,并且也沒有必要在每一種測試場景下,都驗證被測特性的基本功能、異常功能、與其它功能的交互、非功能屬性等各方面。如何設計更有效的、有限數目的用例盡量做到最大的測試覆蓋,這屬于另外一個話題,本文不做探討。
毫無疑問,盡管測試設計人員和測試執行人員精疲力盡的試圖覆蓋該特性的所有可能的場景,測試人員仍然只覆蓋了一小部分的場景下的該特性的部分測試用例,如果沒有Fatal的遺留問題,是否該特性的質量就可以評價為A或 B,并且認為可以對外發布了呢?這種測試評估工作,與其說是讓測試人員對被測對象的質量進行測試評價,不如說是讓測試人員對被測對象進行質量預測,因為測試人員所了解的只是部分信息,而不是全部。Nassim說“在這些錯誤的預測和盲目的希望中,有一些愿望的成分,但也有知識的問題。”我更愿意相信,測試人員對產品質量的預測主要是“知識的問題”,畢竟完整測試是不可能的。 既然測試無法做到完整覆蓋,不如在有限的時間和資源內,盡可能覆蓋典型的場景,測試評估中針對已經覆蓋到的典型場景進行評估,具體地,James Bach和Michael Bolton在RST(Rapid Software Testing)課程里提出的三步法可以供參考: 測試中發現了哪些問題; 做了哪些測試活動發現了這些問題; 測試活動本身的有效性如何,哪些地方可以改善。 那么對于典型場景之外的其他場景又如何評估呢,這與測試評價之前的那些測試活動息息相關,也就是與黑天鵝正在形成之中的那些故事有關,我們在后面第四部分再探討。 3. 黑天鵝發生之后的“假想解釋” 不管怎樣,那些你認為不應該發生的“黑天鵝”經常如期而至。很多組織要求缺陷發生后開展缺陷根因分析(RCA)(我總是在盡力避免使用“缺陷回溯”這個詞)。尤其對黑天鵝這樣的重要的bug,更要仔細開展缺陷根因分析了。對黑天鵝開展RCA的目的是利用這個黑天鵝,挖掘它帶給我們的信息,從而盡可能在以后的測試中發現更多類似的缺陷,對開發而言則是在以后盡可能避免引入此類的bug。 RCA的目的是做到基于缺陷的過程改進,而不是解釋黑天鵝的發生這個動作本身。不要試圖去解釋所有的黑天鵝,尤其是那些在實驗室很難重現的黑天鵝。我看到有些測試團隊,當黑天鵝發生了很緊張,又是一個嚴重的bug漏測了,趕緊組織人力調查分析,盡快寫出一個看起來像樣的缺陷分析報告。而閱讀這個RCA報告,很難從中找出真正有力的措施可以有效避免今后這類bug不再漏測。舉幾個現實中的“RCA現象”:RCA報告中,錯誤的原因有“人為錯誤”、“溝通不暢”、“缺乏相應的測試用例”等;避免漏測的措施有“加強代碼走讀”、“加強白盒測試”、“提高測試設計能力”、“加強與開發人員的溝通”等。Nassim發現,“我們的頭腦是非常了不起的解釋機器,能夠從幾乎所有事物中分析出道理,能夠對各種各樣的現象羅列出各種解釋,并且通常不能接受某件事是不可預測的想法。” 我曾對多個團隊進行T-RCA(我提出的一個缺陷根因分析的方法)引導,發現一個有趣的現象,盡管各個團隊所測試的產品是不同的,但是他們RCA分析的結論卻是驚人的相似,很多團隊都存在我上述所列的“RCA現象”。我分析原因大致有二,一是沒有找到有效開展RCA的方法,沒有找到缺陷發生的根本原因;二是很多團隊使用了比較“細致”的RCA模板,模板里對每一項可能的情況進行了細致的分類,比如該缺陷所處的測試級別、涉及的測試活動、所屬的測試類型、可能的原因分類等等。缺陷根因分析工作仿佛變成了測試人員只要對照模板逐一打鉤去篩選就可以了,但實際上RCA是個高度探索性的過程,需要與缺陷相關的各干系人去溝通,需要從紛繁復雜的種種因素中創造性地找到改進的措施。面對著電腦,填寫那些RCA模板中的空白項不是最主要的工作。實際上,某種程度上講,過細的RCA模板簡化了缺陷分析過程,掩蓋了缺陷根因分析過程的復雜性,也比較容易導致分析結果的雷同?!逗谔禊Z》里的這句話也許可以給我們更多啟示:“我們對周圍世界的任何簡化都可能產生爆炸性后果,因為它不考慮不確定性的來源,它使我們錯誤地理解世界的構成。” 4. 黑天鵝形成之中的“柏拉圖化” 既然,測試中的黑天鵝的發生是個經常性的事件,那么測試的過程不也正處于黑天鵝形成的過程嗎?想象一下,當前我們正在測試一個產品,我們了解黑天鵝理論,我們知道這個產品發布給用戶后極有可能會冒出“黑天鵝”來,那么我們當前可以采取什么措施呢? 我在“認識軟件測試中黑天鵝”一文中解釋了什么是“測試的柏拉圖化”:只注重外在的形式、尤其是針對具體明確的事情進行簡單分類的時候,犯“柏拉圖化”錯誤的人容易高估他們已經掌握的事實性信息的價值,而對大量的他們還不知曉的并且非常重要的信息視而不見。我是在2006年發現這個“我所不知道的大量信息的”,也同時發現了之前我所犯的“測試的柏拉圖化”的錯誤,即特別重視諸如“測試用例設計個數、測試用例執行個數、發現的bug數”等這些數據,也許在這些明確的、外在的形式之外,有更多值得我們思考的東西。 那一年,我負責一個特性(大體就是在手機上通過蜂窩小區廣播的形式收看電視)的測試,這個特性是個全新開發的特性,我是第一個、也是當時唯一一個測試人員,測試任務很緊張,因為這個特性已經定于一、兩個月以后在香港某個運營商網絡里首次商用。像大多數測試人員一樣,我很辛勤地、按照既定方法和策略測試這個特性,在有限的測試時間里:我熟悉了這個特性、設計了很多測試用例、執行了大量的測試用例、發現了很多bug、對這個特性相關的每一個bug都了如指掌、通過和開發人員不斷地交涉和定位bug還對該特性當前存在的缺陷非常清楚、熟悉這個特性的代碼和問題定位手段。當我奔赴香港作為測試人員輔助開通這個特性的商用之前,研發團隊解決了所有嚴重的缺陷,我很有信心應對各種可能的狀況,我幾乎認為我對這個特性的了解已經很完整了。 可是,當我抵達用戶那里,看到我們的產品在真實網絡中的運行環境、配置、使用方式,與用戶和當地技術支持人員的各種交流,坐在地鐵里看到身邊的人員拿著手機正在開啟使用我剛剛參與開通商用的特性,從真實網絡環境中獲取的大量錯誤報告和跟蹤消息和后臺日志。。。短短幾天內,有關這個特性的、以前我所不知道的、大量的信息沖進了我的大腦,我像突然撿到寶藏一樣地忙著分析日志、記錄bug,生怕遺漏了哪個bug沒有記錄,然后回到實驗室都不知道如何觸發。 我發現了一個重要的事實:這一回,我只用了幾天時間,沒有設計任何測試用例,沒有執行任何測試用例,卻在一個我幾乎認為沒有什么嚴重缺陷的特性上,“不費吹灰之力”似的又發現了很多嚴重的缺陷。而且這些缺陷不是實驗室觸發的,而是就發生在用戶的身上,有些遭到用戶的投訴,有些用戶還不知曉,換句話說,這些缺陷都是優先級很高的非常重要的缺陷。 從香港回來,我一直在思考,測試團隊如何發現這些重要的缺陷?甚至如何讓平常我們在實驗室中的測試也能這么高效、這么有效?您可能已經猜到了,這就是后來備受重視的UBT(Usage Based Testing),或者有的行業叫做TiP(Test in Production),也有人稱為Testing-in-the-wild。 再回到前面曾提到的一個關于測試評估的問題上:假如平常的測試更關注典型場景的測試,那么對于非典型場景如何測試以及如何評估呢?我想UBT是個不錯的選擇。既然無法做到全覆蓋的測試,就不去做,不要試圖在現有的測試模式下,測試設計和測試執行都投入很大精力去覆蓋各種場景和交互,因為這樣做收效甚微,依然達不到目的。平常的功能測試只做最普通、最典型、最重要場景下的功能驗證,保證每個測試特性的基本功能OK。此外,還要開展UBT或TiP,主要考慮各種配置和場景,用模擬器模擬真實商用組網環境和業務模型,或者直接在用戶使用產品的真實環境中開展測試。 假如被測系統如下圖的方框,灰色的小塊就是我們平常的功能測試覆蓋,可能很多測試團隊的做法是試圖盡最大能力增加這些灰色小塊的覆蓋,但依然會有很多覆蓋不到的地方。而UBT就相當于紅色的范圍,雖然沒有針對性的設計測試用例,但由于模擬了可能使用的商用場景和業務,業務之間交互的測試在這種測試環境下自動進行,潛在的一般的bug都被自動發現(比較難觸發的異常 bug依然發現不了),如果這樣的UBT測試連續執行幾天或數周都沒有問題,此時測試的評估中就可以很有信心地寫到:在XXX UBT環境下連續運行XX天,沒有發現嚴重問題。 這樣,也大大減少了版本發布后“黑天鵝”出現的幾率。
5. 結論 如果你認同“測試的黑天鵝”就在我們身邊,那么: 在“測試的黑天鵝”發生之前,不要在信息不完整的情況下對全局做“盲目預測”,因為你只掌握了部分信息,你要做的是更準確地陳述這些“部分信息”; 在“測試的黑天鵝”發生之后,不要試圖對所有黑天鵝都做“假想解釋”,更重要的是從已經發生的黑天鵝身上挖掘更有價值的信息,以減少更多類似黑天鵝事件的發生; 在“測試的黑天鵝”形成過程之中,不要犯“測試的柏拉圖化”錯誤,重視你知道的信息,更重視那些你所不知道的大量的更有價值的信息。 |
原文轉自:http://www.uml.org.cn/Test/201307162.asp