批駁:單元測試自己測效果不好,別人測效果纔好

    有一種說法:程序員測自己的代碼效果不好,因爲測試是找錯,程序員不願意去證明自己是錯的,別人測效果纔好,對嗎?這種說法是根本錯誤的,誤導了無數人。正好相反,單元測試要自己測效果纔好,別人測則幾乎沒有效果,除非有函數級的詳細文檔。

    單元測試的三種方式:程序員編碼同時測試、程序員編碼後測試、由別人測試,成本的比例大概爲1:3:5,測試效果的比例大概爲5:3:1。這是指一般的開發過程,其特徵是沒有函數級的詳細文檔。

    我們先來看看大家耳熟能詳的幾個概念:需求、設計、實現。需求是“要做什麼”,設計是“具體怎麼做”,實現是“做出來”。寫一個函數,不管寫不寫文檔,需求、設計、實現仍然是必經的過程,只不過面對的目標很小而已。

    寫一個函數,程序員要想清楚“要做什麼”和“具體怎麼做”,這是所想。顯然,所想的就是需求和設計。把代碼寫出來則是實現,這是所做。

    如果在寫代碼同時測試,測試用例一定是依據“所想”而設計的,測試的結果是驗證“所做”是否符合“所想”,也就是說,測試的結果是:驗證實現是否符合需求。這種方式,需求是清晰的(雖然只是在程序員的腦子裏),所以效果最好,而用例只需根據“所想”直接設計就行,還可以利用測試來驅動開發,所以成本最低。

    程序員編碼後測試,“所想”已經忘了一部分,要根據代碼來“恢復”,但是不可能全部“恢復”。測試的結果,有可能是“驗證實現是否符合需求”,也有可能不是,所以效果會打折扣,由於要花時間來“恢復”所想,且不能利用測試來驅動開發,所以成本也會高得多。

    由別人測試,用例設計的依據是什麼?除非程序員在編碼時把“所想”記錄下來,形成函數級的詳細文檔,否則,“別人”只能讀代碼來確定需求,實際上,這個“需求”是實現本身,測試的結果是:驗證實現是否符合實現,俗稱“跟着代碼走”,這樣的測試有什麼意義?成本方面,需要讀代碼來確定需求,無疑很費時間,所以成本最高。

    舉個簡單的例子來說明。程序員要一個加法函數,結果寫成了:

    int fun(inta, int b)      {          return a - b;     };

    編碼時測試,程序員一定知道自己要寫的是加法函數,用例爲a=1; b=2;ret==3,當然能發現錯誤。

    編碼後測試,程序員有可能想起這是加法函數,測試能發現錯誤,也有可能忘了,讀代碼後認爲這是一個減法函數,這樣測試就沒意義了。

    別人測試,只能讀代碼,認爲是減法函數,測試沒意義。

    當然,實際的情形不會那麼單純,代碼可能有一些註釋,“別人”也許能瞭解代碼的大致需求,所以“別人”測試也會有一些效果,但是,單元測試主要做的,是找出實現與需求之間的細微偏差,例如,一些輸入下代碼是正確的,一些輸入下,代碼有問題(未分類處理這些輸入或處理錯誤),“別人”即使能夠了解代碼的大致需求,也難於瞭解全部需求,測試效果總是很有限的。

    也許有人會說,邊編碼邊測試,雖然依據的是代碼的需求(小需求),但是這個需求是否符合系統的整體需求(大需求)呢?換幾句話說,本來這個函數要做的是A功能,但程序員所想的是B功能,那測試不是沒有意義嗎?一、由別人測試,跟着代碼走,這個問題同樣存在;二、這種錯誤在集成後很容易發現;三、這種錯誤很少。用小需求不一定符合大需求來否定程序員測試自己的代碼,那就是因噎廢食了。

    總之,一般情形下,程序員編碼同時測試、程序員編碼後測試、由別人測試,三種方式的成本的比例大概爲1:3:5,測試效果的比例大概爲5:3:1。這個比例只是定性,我無法精確證明,信不信由你,反正經過十多年的實踐,我是信的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章