有一種說法:程序員測本身的代碼效果很差,由於測試是找錯,程序員不肯意去證實本身是錯的,別人測效果纔好,對嗎?這種說法是根本錯誤的,誤導了無數人。正好相反,單元測試要本身測效果纔好,別人測則幾乎沒有效果,除非有函數級的詳細文檔。程序員
單元測試的三種方式:程序員編碼同時測試、程序員編碼後測試、由別人測試,成本的比例大概爲1:3:5,測試效果的比例大概爲5:3:1。這是指通常的開發過程,其特徵是沒有函數級的詳細文檔。ide
咱們先來看看你們耳熟能詳的幾個概念:需求、設計、實現。需求是「要作什麼」,設計是「具體怎麼作」,實現是「作出來」。寫一個函數,無論寫不寫文檔,需求、設計、實現仍然是必經的過程,只不過面對的目標很小而已。函數
寫一個函數,程序員要想清楚「要作什麼」和「具體怎麼作」,這是所想。顯然,所想的就是需求和設計。把代碼寫出來則是實現,這是所作。單元測試
若是在寫代碼同時測試,測試用例必定是依據「所想」而設計的,測試的結果是驗證「所作」是否符合「所想」,也就是說,測試的結果是:驗證明現是否符合需求。這種方式,需求是清晰的(雖然只是在程序員的腦子裏),因此效果最好,而用例只需根據「所想」直接設計就行,還能夠利用測試來驅動開發,因此成本最低。測試
程序員編碼後測試,「所想」已經忘了一部分,要根據代碼來「恢復」,可是不可能所有「恢復」。測試的結果,有多是「驗證明現是否符合需求」,也有可能不是,因此效果會打折扣,因爲要花時間來「恢復」所想,且不能利用測試來驅動開發,因此成本也會高得多。編碼
由別人測試,用例設計的依據是什麼?除非程序員在編碼時把「所想」記錄下來,造成函數級的詳細文檔,不然,「別人」只能讀代碼來肯定需求,實際上,這個「需求」是實現自己,測試的結果是:驗證明現是否符合實現,俗稱「跟着代碼走」,這樣的測試有什麼意義?成本方面,須要讀代碼來肯定需求,無疑很費時間,因此成本最高。設計
舉個簡單的例子來講明。程序員要一個加法函數,結果寫成了:code
int fun(inta, int b) { return a - b; };
編碼時測試,程序員必定知道本身要寫的是加法函數,用例爲a=1; b=2;ret==3,固然能發現錯誤。blog
編碼後測試,程序員有可能想起這是加法函數,測試能發現錯誤,也有可能忘了,讀代碼後認爲這是一個減法函數,這樣測試就沒意義了。ip
別人測試,只能讀代碼,認爲是減法函數,測試沒意義。
固然,實際的情形不會那麼單純,代碼可能有一些註釋,「別人」也許能瞭解代碼的大體需求,因此「別人」測試也會有一些效果,可是,單元測試主要作的,是找出實現與需求之間的細微誤差,例如,一些輸入下代碼是正確的,一些輸入下,代碼有問題(未分類處理這些輸入或處理錯誤),「別人」即便可以瞭解代碼的大體需求,也難於瞭解所有需求,測試效果老是頗有限的。
也許有人會說,邊編碼邊測試,雖然依據的是代碼的需求(小需求),可是這個需求是否符合系統的總體需求(大需求)呢?換幾句話說,原本這個函數要作的是A功能,但程序員所想的是B功能,那測試不是沒有意義嗎?1、由別人測試,跟着代碼走,這個問題一樣存在;2、這種錯誤在集成後很容易發現;3、這種錯誤不多。用小需求不必定符合大需求來否認程序員測試本身的代碼,那就是因噎廢食了。
總之,通常情形下,程序員編碼同時測試、程序員編碼後測試、由別人測試,三種方式的成本的比例大概爲1:3:5,測試效果的比例大概爲5:3:1。這個比例只是定性,我沒法精確證實,信不信由你,反正通過十多年的實踐,我是信的。