京東購買鏈接:https://item.jd.com/10205955087769.html
2.4 海戰棋問題:測試 VS 檢查
海戰棋遊戲是一款網格遊戲,我們可以將輸入空間看作二維平面,有 X 軸(左右方向)和 Y 軸(上下方向)兩個維度。為了方便理解,我們可以將 X 軸視為軟件中的各項活動,比如搜索功能、產品信息展示、購物車、創建 / 編輯賬號等,Y 軸則代表在這些活動內部的具體輸入空間。這種比喻可能不是很貼切,因為二維平面畢竟只是一個模型,不可能非常完美地適用於任何情況。在童年時期玩的海戰棋遊戲中,X 軸由數字(1 ~ 10)表示,Y 軸由字母(A ~ J)表示,左上角的座標就是(1,A),如圖 2-4 所示。
圖 2-4 海戰棋遊戲
海戰棋遊戲已有近 100 年的歷史,比版權法出現得還早。在遊戲中,兩位玩家首先會在棋盤上按照以下規則佈置各自的艦隊:
● 一艘航空母艦(佔 5 個格子)
● 一艘戰列艦(佔 4 個格子)
● 一艘巡洋艦(佔 3 個格子)
● 兩艘驅逐艦(每艘佔 2 個格子)
● 兩艘潛艇(每艘佔 2 個格子)
玩家可以將這些戰艦縱向或橫向佈置在棋盤上,但是不能斜向佈置。
2.4.1 將戰艦看作 bug
我們將海戰棋遊戲中的戰艦看作軟件中的 bug,此遊戲映射出了一種現象—bug 傾向於在模塊中聚集,雖然沒有數據來佐證,但這一現象確實符合我們的日常工作體驗。
不同版本的海戰棋,戰艦類型、戰艦數量、棋盤大小等可能有所不同,但玩法是相通的。玩家在小表格上標記好(隱藏)己方戰艦的位置,然後雙方輪流出擊(交替猜測對方戰艦的座標),防守方宣佈“未命中”或“命中”。但是,在使用海戰棋遊戲教授軟件測試時,筆者會要求一半學員(玩家)提前規劃他們的行動。這也是傳統自動化測試所做的事情,提前定義好軟件運行的步驟,這些步驟既可以作為可執行的規範在編寫代碼前預先設定,也可以作為測試過程的一部分在代碼完成後編寫。同樣地,人工編寫的腳本化測試(包含測試用例、步驟和預期結果),本質上也是如此。
故在此教學中,我們會要求一支隊伍模仿自動化測試的方式,將他們的行動計劃詳細列出,而另一支隊伍則無需事先規劃,可以隨意行動。
如此一來,原本簡單的遊戲將會變得十分有趣。高度配合的小組至少會嘗試玩一下,以觀察整個遊戲的變化。那些喜歡規劃的人,尤其是有後續步驟測試經驗的人,非常樂意參與其中,他們會制訂大的 X 形、星形或對角線策略來尋找對方的戰艦。然而,那些個性較強、智商較高的人,特別是對“計劃型”測試不太熟悉的人,可能會表現出對規劃的牴觸。因為他們認為,一旦被鎖定在某一策略上,就無法在命中目標後靈活調整,無法圍繞已命中的位置快速判斷並找出剩餘船隻的確切位置,進而將其擊沉。
從結果來看,不受既定行動計劃約束的團隊往往會擊敗那些嚴格按照計劃行事的團隊。在開展了數百場雙人團隊的對抗模擬實驗後,我們發現按照計劃行事的團隊僅有寥寥幾次首先擊沉對方艦隊並贏得比賽。而且即使是在他們獲勝的比賽中,也多數是因為對方玩家來自不同的文化背景或不熟悉基本的遊戲規則,甚至沒有意識到當他們擊中目標時,應該及時調整策略。
將此模擬實驗對應到軟件測試,我們可以看到的是:首先,測試受文化差異的影響,就像迴文問題一樣,有些人雖然寫了測試用例,但受自身文化、工作等屬性的影響,一些場景不能充分考慮到;其次是覆蓋率,本書第 9 章會重點討論;最後,也是本節最重要的教訓,計算機(自動化測試)無法自行調整測試策略,相反,它們往往只會對要求檢測的內容進行檢查。此行為帶來的侷限性,將會在“2.5 維護問題”中進行探討。
2.4.2 自動化 VS 人工
在海戰棋模擬實驗中,許多人會對完全遵守計劃行事的規定提出意見,他們希望藉助人工智能(AI)改進測試代碼,以在發現 bug(戰艦)時進行自我調整。筆者並不反對這一點,如果有團隊成員可以在他們的項目中實現這一技術,或知道某個團隊擁有的測試軟件能夠做到這一點,筆者還是很樂意看到他們使用此項技術的。但這並不完全屬於模型驅動測試的範疇,模型驅動測試更傾向於全面檢查所有可能的情況。迄今為止,筆者還沒有發現有人在測試工具中應用這項技術,以在發現 bug 時可以像人一樣進行靈活調整和響應。
概要總結一下,人類探索與計算機測試自動化存在着根本區別,因為人類可以根據上一個測試結果來規劃下一次測試。在 2009 年敏捷大會上,邁克爾 · 博爾頓(Michael Bolton)做了一場閃電演講,他試圖區分“人類能做什麼”(帶着發現意圖去調查產品)和“計算機能做什麼”(檢查預先定義的場景)。為了突出兩者區別,他選擇了“testing”和“checking”兩個英語單詞。根據邁克爾 · 博爾頓的觀點:“測試(testing)是通過體驗、探索和實驗來了解產品,從而評估產品的一個過程,在一定程度上包括提問、研究、建模、觀察、推斷等活動。”( 引用自邁克爾 · 博爾頓的文章 Testing and Checking Refined,鏈接 2-2)。邁克爾 · 博爾頓對測試的定義與本書引用 Kaner 博士的觀點是一致的。博爾頓將檢查(checking)定義為“……通過將算法決策規則應用於對產品的具體觀察來進行評估的過程。”
用博爾頓的話來説,檢查是測試的一部分,是我們測試過程中的一項活動,並且在降低風險方面具有一定價值。理論上,讓一台計算機在角落裏獨自執行檢查是完全可以實現的,但其價值卻很有限。本書的重點是幫助讀者強化風險意識,以及如何通過測試降低風險,畢竟檢查只是完整風險管理策略的一個組成部分。對於動態機制(人類發現 bug 的方式與計算機所能完成的任務之間)的誤解,往往是軟件交付過程中許多問題的根源。所以,不妨邀請一位朋友一起玩海戰棋,然後,思考自己正在開發或想要開發的工具是否能夠發現邊緣場景下的 bug。