###### tags: `提升程式設計師的面試力`
# chapter 11 測試
## 11.2 隨機當機 :
你拿到一個會當機的應用程式的原始碼。
在除錯工具中執行十次都~~不會當機~~不在同一個點當機。
此應用程式是單執行緒,只使用 C 的標準函式庫。
有什麼程式設計錯誤導致當機? 要如何測試?
Random Crashes: You are given the source to an application which crashes when it is run. After
running it ten times in a debugger, **you find it never crashes in the same place**. The application is
single threaded, and uses only the C standard library. What programming errors could be causing
this crash? How would you test each one?
### 解答
主要是看應用程式的類型.但我們可以給出一些基本原因。
**1. 随機變数:**
此應用程式可能使用了一些執行時不固定的随機数字或變數元件,例如
使用者輸入、程式產生的隨機數字、或時間。
**2. 未初始化的變數:**
此應用程式可能具有未初始化的變數,在某些語言中他可能
會有不定值。此變數的值可能讓程式每次採取稍微不同的路徑。
**3. 記憶體洩漏:**
程式可能會耗盡記憶體。其他原因包括完全随機的執行期行程數量
以及堆積(heap)溢流或堆疊的資料損毀。
**4. 外部相依性:**
此程式可能相依於其他應用程式機器、或資源,若有多個相依,
則程式可能在任何時間當機。
要解決這個問題,我們應該盡可能的認識該應用程式。
**誰執行的?如何使用?是什麼應用程式?**
**應用程式不在同一個點當機,但可能與特定元件或狀況有關。**
應用程式可能在啟動後不碰就不會當機,且只會在載入檔案後的某個時間點當機。或
者所有當機都發生在檔案 I/O 等低階元件上。
**排除法**也許有用。關閉其他應用程式。仔細觀察資源。若有可能就關閉部分應用程
式。在其他機器上執行看看是否也有相同問題。能排除(或改變)越多則越容易解決
問題。
此外,我們或許能夠使用工具檢查特定狀況。舉例來說,原因#2可使用執行期工具
檢查是否有未初始化的工具。
這些問題與你的思路以及方法有關。**你是隨意檢測或有邏輯、結構的進行?**
## 11.3 ~~象棋~~西洋棋測試:
有個方法用於象棋遊戲:boolean canMoveTo (int x , int y)
方法是 Piece 類別的成員,回傳棋子是否能移動到 (x,y) 位置如何測試這個方法。
Chess Test: We have the following method used in a chess game: boolean canMoveTo(int x,
int y). This method is part of the Piece class and returns whether or not the piece can move to
position (x, y). Explain how you would test this method.
### 解答
這一題主要有兩種測試:極端條件檢驗(確保程式不會因不良輸入當機)以及
況測試.我們先從第一種開始。

#### 測試類型 #1 : 極端條件
必須確保程式能優雅的處理不良或不尋常的輸入。這表示要檢查:
* 負的 X 與 y
* 大於寬的 x
* 大於高的 y
* 已經佔滿的棋盤
* 空或接近空的棋盤
* 白子比黑子多
* 黑子比白子多
與面試官討論以上的錯誤應該要回傳 false 或拋出例外並依據此進行檢查。
#### 測試類型 #2 : 一般測試
一般測試的成本更高。最好能測試各種可能,但可能性太多了。然而我們可以執行合
理範圍內的不同測試。
有 6 個棋子、因此我們可以相互測試各種方向。這會產生類似以下的程式:
對每個棋子 a :
對每其他類型的棋子 b (6 種類型+空格)
對每個方向 d
建構帶有 a 的棋盤
將 b 放在方向 d
嘗試移動――檢查回傳值
foreach piece a:
for each other type of piece b (6 types + empty space)
foreach direction d
Create a board with piece a.
Place piece b in direction d.
Try to move – check return value.
**重點是我們不可能測試所有狀況,就算是我們很想要這麼做。因此,我們必須專注於基本範圍。**
## 11.4 沒有測試工具 : 如何在沒有測試工具下對網頁做負載測試?
No Test Tools: How would you load test a webpage without using any test tools?
### 解答
負載測試可幫助找出**網頁應用程式的最大處理能力以及瓶頸**。同樣的,他也可以找出
應用程式對各種負載的反應時間。
要執行負載測試.我們必須先找出**重效能的情境與效能目標的指標**。指標包括:
* 回應時間
* 吞吐量
* 資源利用率
* 系統的最大負載
然後我們設計模擬該負載的測試,仔細的評估每個指標。
**缺少適當的測試工具時,我們基本上可以自己製作**。舉例來說,我們可以建構數千個
建使用者來模擬同時使用者。我們可以撰寫有數千個執行緒的多執行緒程式,每
個執行緒模擬一個真正的使用者。對每個使用者,我們以程式評估**回應時間與資料
I/O**等。
然後根據收集到的資料進行分析並與可接受的數據進行比較。
## 11.5 筆 : 如何測試一支筆?
Test a Pen: How would you test a pen?
### 解答
重點在於**認識限制並以結構化的方式解決問題**。
要認識限制你必須提很多問題以理解 who, what, where, when, how 與 why
(或其他部分).要記得好的測試者在開始工作前會完全清楚測試的對象。
為展示這種技術。讓我們進行一場模擬對話。
* 面試官:如何測試一支筆?
* 求職者:讓我們進一步認識他。誰會使用這支筆? Who
* 面試官:可能是小孩子。
* 求職者:嗯很有趣。他們用他做什麼?寫字、畫圖、還是其他事情? what
* 面試官:畫圖.
* 求職者:OK.很好。畫在什麼東西上面?紙?衣服? where
* 面試官:衣服.
* 求職者:很好。筆是什麼頭?平頭?球尖頭?要可以洗掉嗎?或是要擦不掉?
* 面試官:要能洗掉。
經過許多問題後,你可能得到這樣的結論:
* 求職者:好.我知道了筆給5到10歲小朋友使用。筆是紅、綠、藍、與黑色。畫在衣服上能洗掉。對嗎?
求職者現在有了與一開始很不一樣的題目。這不常見,事實上面試
看似明確的題目(每個人都知道筆是什麼!)讓你發掘出不一樣的題目·
一般認為使用者會做同樣的事,但不一定。
現在你知道要測試什麼,是時候提出計劃。關鍵在於**結構**。
從思考物件或問題有什麼不同的元件開始。此例中,元件可能是:
* 事實檢驗:檢查筆是否為平頭與顏色是否正確·
* 設計使用方式:畫。是否能畫在衣服上?
* 設計使用方式:洗。是否能洗掉(一段時間後)?要熱水或冷水?
* 安全性:筆對小朋友是否安全(有毒)?
* 非設計使用方式:小朋友還會對筆做什麼?他們可能會畫在牆
此行為是否正確·他們可能會踩上去或摔出去等。
你必須確保筆能承受這些條件。
任何測試題目要記得你必須**測試設計與非設計的情境**。人們不一定以你想像的方式
使用產品
## 11.6 測試ATM : 如何測試分散式銀行的ATM?
Test an ATM: How would you test an ATM in a distributed banking system?
### 解答
首先要澄清假設。詢問下列問題:
* 誰會使用ATM? 答案可能是“任何人”或可能是“盲人”以及其他答案
* 他們會怎麼用? 答案可能是“提款”、“轉帳”、“查詢餘额”、或其他答案
* 有什麼測試工具? 我們可以存取原始碼還是只有ATM?
要記得 : **一個好的試者會知道他要測試的是什麼**!
了解系統後。我們想要**將問題分成不同的可測試元件**。這些元件包含
* 登入
* 提款
* 檢查餘額
* 轉帳
我們或許會組合手動與自動測試。
手動測試涉及上述步驟,確保檢查到各種錯誤案例(餘額不足、新帳戶、帳戶不存在
等)。
自動化測試比較複雜。我們想要將上述所有標準案例自動化並檢查一些特定問題,像
是競爭狀況等。理想中,我們能夠設置一個有假帳戶的封閉系統,確保就算有人快速
的從不同地方提存也不會造成溢領或短少。
此外·我們必須確保安全性與可靠性。帳戶一定要受保護。我們必須確保
不能有預料外的損失!一個好的測試者會知道系統的重點。
> A good tester understands the system priorities.