1.1 名詞定義
SUT 被測試系統 System Under Test(或者CUT,也就是被測試的東西)
TDD 測試驅動開發 Test-Driven Development
1.2 理解單元測試
工作單元是一個什麼樣的存在?如果按照字面意思來看,單元測試是一個小的部分,也就是一個單元,但這個單元又有着不同的範圍,它可以是一個方法,可以是一個類,甚至可以是多個類,一整個組件,當然這種時候都已經不能算是純粹意義上的單元測試了。
在《單元測試的藝術》中,認爲被測試的單元不能儘可能的小。如果單元測試儘可能小,我們可以對每個方法,每個類進行單元測試,但是這樣會發現我們需要僞造很多的數據,很多的中間狀態,用以支撐我們的單元測試。但是這就有些做無用功了。
一個單元測試,目的在於調用一個工作單元,並且檢驗這個單元的具體最終結果,如果關於這個最終結果的假設是錯誤的,那這個單元測試就失敗了。這個比較好理解,也就是我們想要失敗或者成功,都需要最後的結果與預期相符合,纔算成功的單元測試。
1.3 優秀的單元測試
單元測試從本質上來說也是代碼,既然是代碼,我們當然要編寫優秀的代碼。優秀的單元測試要有幾個特點:
- 自動化可重複執行(需要計算機能自己動手,不需要人工參與)
- 容易實現
- 結果穩定(每次運行相同的測試得到的應該是相同結果)
- 任何人都能一鍵運行
- 運行速度很快
- 完全控制被測試的部分
- 完全隔離(獨立於其他測試)
- 能通過失敗發現問題所在
- 在第二天(之後)還能有存在的意義
如果我代碼中使用了當前時間,那我每次運行的時候時間都不一樣,每次也就不是同一個測試,也就不穩定了, 也就不能算單元測試。諸如此類。
1.4 集成測試和單元測試
思考幾個問題:
- 兩週前寫的一個單元測試,今天還能運行並得到結果嗎?
- 兩個月前的單元測試,團隊中的其他人能運行並得到結果嗎?
- 能幾分鐘跑完全部的單元測試嗎?
- 能一鍵運行全部單元測試嗎?
- 能幾分鐘就寫出一個單元測試嗎?
這幾個問題關注的,都只在於一個單元上的測試結果,集成測試無法做到這些,它更多的依賴於真實的產品環境,而單元測試把被測試的單元和其依賴物分隔開,以保證它能穩定和高效,還能輕易控制和模擬被測試單元的任何行爲。
單元測試的具體定義:一個單元測試是一段自動化的代碼,這段代碼調用被測試的工作單元,之後對這個單元的單個最終結果的某些假設進行檢驗。單元測試幾乎都是用單元測試框架編寫的。單元測試很容易編寫,能快速運行。單元測試可靠,可讀,並且可維護。只要產品代碼不發生變化,單元測試的結果就是穩定的。
1.5 擴展–測試驅動開發
TDD的運行邏輯在於,你需要先編寫一個會失敗的測試,然後創建產品代碼,這個產品代碼的目的就是讓這個測試通過,接下來是重構代碼或者創建另一個會失敗的測試。TDD的技術核心就在於編寫一個會失敗的測試以證明產品中代碼或者功能的缺失,編寫符合測試預期的代碼使產品測試通過,以及重構代碼。TDD的要求在於,你預期的成功與失敗,都必須要在最後得到相同結論,不然一定是你的測試或者你的產品代碼出現了問題。TDD要求你能知道如何編寫優秀的測試,在編碼前編寫測試,以及良好的測試設計。