
所屬文章系列及序號:尋找塵封的銀彈:bug修理廠(一)
看似沒有什么營養(yǎng)的bug描述里,其實蘊含著兩個關鍵要素,往往被我們忽略。開發(fā)者一旦掌握了這兩個要素,靈感會被瞬間激發(fā)出來,立刻想到解決方案,而且是正確的方案!筆者之所以要在這里強調(diào)“正確的方案”,原因就在下邊對這兩個要素的講述之中。
【一個要素是條件】
Bug描述里一般會列出這些條件:操作系統(tǒng)的版本號,環(huán)境變量配置了什么值(這些變量也許會是一個長長的列表),發(fā)生bug之前做了什么操作(這些操作也許會是一個長長的列表)。
我們需要從這個描述中找出導致bug的“條件要素”,才能更好的理解bug發(fā)生的原因,從而可以找到解決方案。這里提到的“條件要素”是指,如果不執(zhí)行某個測試步驟,就不會發(fā)生這個bug,那么這個步驟就是“條件要素”。
對于能夠100%重現(xiàn)bug(或叫必現(xiàn)),我們既可以用下邊的方法去找“條件要素”,又可以直接用設置斷點的方式去發(fā)現(xiàn)代碼錯誤,不過設置哪個斷點也有很多可討論的地方,這些復雜的討論需要在開發(fā)者“做bug重現(xiàn)”時再去解決(參見后續(xù)文章)。在這兩種方法的具體選擇上,要看哪個方法更快、自己更熟悉等因素。
對于重現(xiàn)概率較低的bug,作為一個開發(fā)者,如何在這些海量信息面前,迅速找出那個決定性的條件?這絕對是個能力,而且有時很像智商測試題。這是程序員必備的技能,具體的方法有很多,其中一個方法是“對比”。
現(xiàn)代版的俗話說:“沒有對比就沒有傷害”。
當開發(fā)者或測試者修改了某一個測試步驟,例如改變了一個環(huán)境變量的值、減少了一個測試步驟、改變了兩個測試步驟的順序,等等,有時就會發(fā)現(xiàn)bug沒有了,那就證明是這次的測試步驟改變導致bug消失的,條件要素也就找到了。
這里有兩個變化需要注意:
一、無論是必現(xiàn)的bug還是不必現(xiàn)的bug,修改一個步驟后bug消失了,一般情況下就能判斷出是這次修改步驟導致的,但僅限于一般情況,還有其他情況導致bug發(fā)生,例如多線程,這些復雜的討論需要在開發(fā)者“做bug重現(xiàn)”時再去解決(參見后續(xù)文章),這個階段只是為了讓項目經(jīng)理、開發(fā)者、測試者看懂bug就足夠做決策用了。
二、一次只能改變一個測試步驟,否則我們就無法準確知道是哪個改變導致的。
到此為止,方法是有了,但是方法還不夠有力。一旦測試步驟非常多,那么需要對比的測試用例就多,有時會達到100條以上,這樣的效率就太低了,而且操作起來讓人心煩,根本找不到工作中的快樂。
好在我們還有更好的方法:谷歌搜索的“手氣不錯”!也就是說,在把所有情況羅列出來以前,先用自己的直覺試驗一個最有可能的用例,往往就能找到那個關鍵的條件要素。不過直覺需要知識和經(jīng)驗的積累,更需要對經(jīng)驗的“反芻”。
【另一個要素是“錯誤是什么”】
有人會說,“錯誤是什么”不是明擺著的嗎?看完下邊這個例子,他就能體會到“明擺著”只是一種奢望:
有一個Bug的標題是:用戶打開某個界面時,得到的人員列表不符合預期。
Bug的細節(jié)描述是:當用戶打開應用程序的一個界面時,得到了一個如下這個不符合預期的人員列表:
002 B先生
003 C小姐
001 A先生
而期望值是:
001 A先生
002 B先生
003 C小姐
理解錯誤的壞結果
如果這個列表比較長,那么靠人眼去對比期望值和實際結果,需要多花一點時間。不要小看多花的這一點時間,一方面,人的大腦看到瑣碎的東西一定會比較累。
另一方面,如果是產(chǎn)品經(jīng)理或項目經(jīng)理在看這個列表,他不可能去看每一個bug的細節(jié),因為他需要站在一個更高的視角去看待整個項目。所以他看到這種模糊不清的問題,要么多花一些時間去仔細理解這個bug,要么是認為自己理解清楚了,從而讓這個bug在整個開發(fā)鏈條中的多個人之間流轉(zhuǎn)一圈,最后bug仍然沒有解決,這樣一來,多花的時間就有些可觀了。
導致理解錯誤的淺層原因
下面就是一個導致bug無效流轉(zhuǎn)的“坑”。
開發(fā)者看到這個結果對比的直覺是:一定是第一列的顯示順序錯了。之后,開發(fā)者就去改代碼,改完之后,測試者又發(fā)現(xiàn)了另外一個bug:
當用戶打開應用程序的一個界面時,得到了一個如下列表:
001 A先生
002 B先生
003 C小姐
004 A小姐
而期望值是:
001 A先生
004 A小姐
002 B先生
003 C小姐
實際上只是因為在這個列表中又加入一條數(shù)據(jù)而已,卻觸發(fā)了開發(fā)者改上一個bug時的理解錯誤,導致修改bug的成本翻倍。
經(jīng)過分析,終于得出結論:應該按照第二列排序,而不是第一列!
這還只是一個最簡單的例子,大部分人還是能一眼就能看出來,但是,實際的工作中遠比這個情況復雜,想不“中招”就需要去蕪取精的能力了。
正確的做法是:
開發(fā)者看到這個問題,如果邏輯清晰的話,應該能想到有很多種情況導致這種錯誤,上文提到的只是其中的兩種情況,他想到之后要去找測試者確認,有時甚至要找到需求文檔編寫者和產(chǎn)品經(jīng)理。
導致理解錯誤的深層原因
表面上看起來這是個溝通問題,其實不是,這是因為:測試者確切地知道需求是什么,只是他認為沒必要寫出來,而開發(fā)者也認為自己理解對了,也就沒必要再問,導致了bug的無效流轉(zhuǎn)。當大家都認為沒有分歧時,自然就不需要溝通,所以邏輯能力的欠缺才是深層原因!
解決邏輯能力欠缺的有效方法有兩個:長期來看,應該去學習、思考。短期來看,用最準確的語言去描述,例如上文的bug描述應改為:用戶打開某個界面時,得到的人員列表應該按照第二列排序。
導致理解錯誤的知識原因
行文至此,如果讀者認為這就是“第二個要素:錯誤是什么”的全部了,“也不過如此嘛”,那有時還會掉到下邊這個更深的“坑”里:
對于使用分布式數(shù)據(jù)庫的系統(tǒng),程序中傳給數(shù)據(jù)庫的SQL中,如果沒有包含order by,那得到數(shù)據(jù)的順序是不會得到保證的!因為分布式數(shù)據(jù)庫為了提高性能,是用并發(fā)的方式從多個數(shù)據(jù)庫節(jié)點獲得數(shù)據(jù),既然是并發(fā),那就無法確定哪個節(jié)點的數(shù)據(jù)先傳到。
如果開發(fā)者沒有這個知識,或即便有這個知識而忘記了在這里運用它,就會掉到上邊這個“深坑”里。結果就是:讓一個bug衍生出另外一個bug,再衍生出第三個bug,讓這些“臭蟲”在開發(fā)者、測試者、項目經(jīng)理、產(chǎn)品經(jīng)理,甚至客戶那里轉(zhuǎn)啊轉(zhuǎn),創(chuàng)造出的GDP是很多了,但都是無價值甚至是負價值的GDP。
作于2018-3-10