摘要:TDD(Test Driven Development),測試驅動開發。指望局部最優到全局最優,這個是一種很是不錯的好習慣。
瞭解Golang的測試以前,咱們先了解一下go語言自帶的測試工具。程序員
Go語言中的測試依賴go test命令。編寫測試代碼和編寫普通的Go代碼過程是相似的,並不須要學習新的語法、規則或工具。算法
go test命令是一個按照必定約定和組織的測試代碼的驅動程序。在包目錄內,全部以_test.go爲後綴名的源代碼文件都是go test測試的一部分,不會被go build編譯到最終的可執行文件中。編程
在*_test.go文件中有三種類型的函數,單元測試函數、基準測試函數和示例函數。segmentfault
go test命令會遍歷全部的*_test.go文件中符合上述命名規則的函數,而後生成一個臨時的main包用於調用相應的測試函數,而後構建並運行、報告測試結果,最後清理測試中生成的臨時文件。併發
如下是來自wiki對於單元測試的定義函數
在計算機編程中,單元測試(英語:Unit Testing)又稱爲模塊測試,是針對程序模塊(軟件設計的最小單位)來進行正確性檢驗的測試工做。程序單元是應用的最小可測試部件。在過程化編程中,一個單元就是單個程序、函數、過程等;對於面向對象編程,最小單元就是方法,包括基類(超類)、抽象類、或者派生類(子類)中的方法。工具
一般來講,程序員每修改一次程序就會進行最少一次單元測試,在編寫程序的過程當中先後極可能要進行屢次單元測試,以證明程序達到軟件規格書要求的工做目標,沒有程序錯誤;雖然單元測試不是必須的,但也不壞,這牽涉到項目管理的政策決定。性能
每一個理想的測試案例獨立於其它案例;爲測試時隔離模塊,常用stubs、mock[1]或fake等測試馬甲程序。單元測試一般由軟件開發人員編寫,用於確保他們所寫的代碼符合軟件需求和遵循開發目標。它的實施方式能夠是很是手動的(透過紙筆),或者是作成構建自動化的一部分。單元測試
簡單來講,單元測試就是程序員本身對於本身的代碼進行測試,而一個單元就是單個程序、函數、過程等;對於面向對象編程,最小單元就是方法,包括基類(超類)、抽象類、或者派生類(子類)中的方法。學習
更有一種開發手法,那就是TDD(Test Driven Development),測試驅動開發。指望局部最優到全局最優,這個是一種很是不錯的好習慣。
請注意這裏的局部最優的,局部,並非函數內的詳細。而是整個函數。甚至是一個類,等等。
由於有些函數內部的最優,並不是這個函數的最優。這點咱們須要格外的注意。如有興趣,可瞭解一下有點關係的貪心算法。
其中參數t用於報告測試失敗和附加的日誌信息。
testing.T的擁有的方法以下:
說了這麼多,那麼咱們來實現一個簡單的string中的Split函數,並對他進行單元測試,而後咱們在剖析代碼。瞭解單元測試的相關規範。
運行結果以下
說明測試成功,本次經過。固然你也能夠在Terminal裏面直接運行go test,命令,以下所示
舒適提示:關於可能形成運行test不成功緣由
直接在split_test.go,運行。
咱們或許知道,go是以文件夾的方法來區分項目。因此當前文件,並不能跑到旁邊文件中去找到Split,以致於測試失敗。或未達到預期效果。
那麼正確的打開方式應該是?
在goland中,鼠標右鍵點擊run測試文件所在的文件夾,選擇後面第二個 go test projectFileName。
在Terminal中,應在測試文件所在的文件夾的路徑中,進行go test [arge...]。
示例看完了,那麼咱們進行簡單的剖析。咱們先從函數文件提及,(也就是這裏的splits.go)。
測試文件
基準測試
基準測試函數格式
基準測試就是在必定的工做負載之下檢測程序性能的一種方法。基準測試的基本格式以下:
基準測試以Benchmark爲前綴,須要一個*testing.B類型的參數b,基準測試必需要執行b.N次,這樣的測試纔有對照性,b.N的值是系統根據實際狀況去調整的,從而保證測試的穩定性。 testing.B擁有的方法以下:
基準測試示例
咱們爲咱們本身寫的Split函數編寫基準測試以下:
其中BenchmarkSplit:表示對Split函數進行基準測試
BenchmarkSplit-8:數字8表示GOMAXPROCS的值,這個對於併發基準測試很重要
5188407和206ns/op:表示每次調用Split函數耗時203ns
咱們還能夠爲基準測試添加-benchmem參數,來得到內存分配的統計數據。
112 B/op:表示每次操做內存分配了112字節
3 allocs/op:則表示每次操做進行了3次內存分配!!!
優化後代碼以下:
優化後代碼以下
這個使用make函數提早分配內存的改動,減小了2/3的內存分配次數,而且減小了一半的內存分配。
僅僅小小的一處改動,就引發如此大的性能改變。so good量變產生質變
上面的基準測試只能獲得給定操做的絕對耗時,可是在不少性能問題是發生在兩個不一樣操做之間的相對耗時,好比同一個函數處理1000個元素的耗時與處理1萬甚至100萬個元素的耗時的差異是多少?再或者對於同一個任務究竟使用哪一種算法性能最佳?咱們一般須要對兩個不一樣算法的實現使用相同的輸入來進行基準比較測試。
性能比較函數一般是一個帶有參數的函數,被多個不一樣的Benchmark函數傳入不一樣的值來調用。舉個例子以下:
例如咱們編寫了一個計算斐波那契數列的函數以下:
咱們編寫的性能比較函數以下:
運行基準測試:
這裏須要注意的是,默認狀況下,每一個基準測試至少運行1秒。若是在Benchmark函數返回時沒有到1秒,則b.N的值會按1,2,5,10,20,50,…增長,而且函數再次運行。
最終的BenchmarkFib40只運行了兩次,每次運行的平均值只有不到一秒。像這種狀況下咱們應該可使用-benchtime標誌增長最小基準時間,以產生更準確的結果。例如:
這一次BenchmarkFib40函數運行了50次,結果就會更準確一些了。
使用性能比較函數作測試的時候一個容易犯的錯誤就是把b.N做爲輸入的大小,例如如下兩個例子都是錯誤的示範:
本文分享自華爲雲社區《Golang代碼測試(code review)》,原文做者:PayneWu 。