知乎服務端 Golang單元測試框架gocheck使用介紹

什麼是好的單元測試框架?

單元測試應該在的功能和參數上驗證程序的正確性;單元測試過後,機器狀態應該保持不變;單元測試的運行、通過、失敗不依賴於別的測試,可以人為構造數據,以保持單元測試的獨立性。

Gocheck簡介

gocheck是golang語言比較健全且簡單的單元測試框架,gocheck在golang官方的testing package之上,豐富了很多功能,豐富了單元測試常用的assert斷言,判斷動詞deep multi-type 對比,字元串比較以及正則匹配。測試用例組織集合方面按suite組織測試用例,支持suite級別的setup()和teardown()。對於臨時文件支持創建、刪除臨時文件和目錄。

Assert斷言的使用

Assert根據預期Checker值檢驗介面返回值與預期值是否匹配,如果它們不匹配,則會記錄錯誤,測試記錄不通過,並且測試用例將停止。func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{})那麼如上代碼所示的checker介面是怎麼來實現驗證的呢?checker介面是必須與Assert和Check驗證方法一起使用的檢查器。

首先需要定義好Checker介面,代碼如下:

其中的CheckerInfo為一個結構體,用來定義我們基準校驗的參數格式。

checker中有比較多的檢查器,一般可以滿足我們正常情況下的各種檢查需求,比如ErrorMatches檢查器驗證錯誤值是否為非零並與提供的正則表達式匹配。

檢查器代碼可以這麼寫:

Assert校驗代碼:

以上就是一個介面的簡單校驗流程。同時Checker檢查器提供了比較豐富的檢查器方法,下面簡單列幾種:

DeepEquals 全等校驗,類型必須相同,校驗比較嚴格,一般很少使用,因為校驗結果失敗的概率比較高;

Equals 相當於 ==校驗,比全等校驗相對來說要寬鬆一點;

FitsTypeOf 校驗類型是否一致;

HasLen 校驗長度是否一致;

IsNil 校驗返回值是否為空;

func Not(checker Checker)反轉提供的檢查器的邏輯,生成的檢查器將在原始檢查器失敗的情況下成功,反之亦然。

臨時文件的使用

採用臨時文件方法,滿足單元測試要讀寫文件需求。

對於測試的過程中我們經常要用到前期的大批量的讀寫文件操作,但是大量的數據文件可能會導致測試完成後伺服器狀態改變,為了遵循」單元測試過後,機器狀態保持不變」的原則,我們需要在單元測試結束後自動清理掉單元測試運行中用到和產生的大量臨時文件存儲的數據。gocheck可以創建一個臨時目錄,在測試結束時自動刪除它,省去了手動清理的步驟。

示例代碼:

跳過測試的使用

用於對測試suite的過濾,當有些測試suite是特定情況才需要在報告中體現的時候,可以選擇用這個方法,方便測試報告生成和測試過程中的特意過濾。

可以使用SetUpSuite,SetUpTest中的skip方法或測試方法本身跳過測試。這允許根據自定義因素選擇性地忽略測試,例如正在運行的體系結構,提供給測試的標誌或資源的可用性(網路等)。

例如,除非提供-live選項進行測試,否則以下測試套件將跳過套件中的所有測試

示例代碼:

Mock server api 相關的測試使用

對於測試的過程中我們經常會遇到需要調用外部api的情況,這樣的話外部api的響應成功與否直接影響我們當前單元測試的成功與否,與單元測試要求的獨立性背道而馳,所以我們最後用mock數據的方法來保證單元測試的獨立性。

利用gocheck的SetUpSuite()和TearDownSuite()方法,可以新建一個http test server,結束時關閉它。

知乎提問代碼測試實例

大家都知道知乎的提問和回答功能是整個知乎社區比較重要的一個功能,在知乎社區有疑問提出問題後,想要修改自己提出的問題的詳細描述這部分功能代碼要怎麼進行測試呢?下面就來講講這個比較小的點要怎麼去進行單元測試。

1. 需求分析

測試提問的詳細內容更新這個功能函數,變數有詳細內容具體信息,更新原因,更新時間,更新用戶這個四個變化的參數,其中更新時間和更新用戶部分可以直接獲取,也不是我們單測的重點,那麼重點就剩兩個更新具體信息和更新原因,更新原因是一個給出的list去篩選,所以不是關注重點,更新具體詳細內容是此次測試的重點。開始分析這個參數的限制條件,在提問中問題詳情字數限制3000字,並且必填。

2. 測試代碼編寫

2.1 所用函數庫分析

因為需求中要求3000字,所以為了保證伺服器測試前後一致性,需要用到臨時文件函數,對3000字文檔進行臨時存儲,用完銷毀操作。

2.2 具體單元測試函數編寫

2.2.1 命名規範

單元測試文件命,根據需要測試的文件命名,比如被測試文件名為question.go,那麼測試文件名即為question_test.go

2.2.2 代碼編寫

創建臨時文件夾以及臨時文件內容

參數傳遞時將臨時文件內容當問題詳細內容參數,這樣在測試代碼運行結束後問題詳細內容的參數就會被銷毀不會在伺服器上產生多餘的文件。

3. 結果分析

每次底層資料庫變成,存儲變更,外部以來介面服務變更,但是數據結構和調用結果不變更的情況下可以利用單元測試結果對現有業務邏輯進行快速檢查。

4. 弊端

單元測試一般代碼量比較大,所以盡量選擇最底層的重要的部分寫單元測試,比如第三方調用等函數部分進行單元測試編寫,上層的業務耦合度高的函數結構不適合寫太多的單元測試。

最後

  • Gocheck框架對golang代碼進行單元測試比原生的單元測試框架寫起來更方便和快速,函數庫基本可以滿足大部分的使用場景。
  • 整個框架本身在github開源可以添加自己需要的函數庫。
  • 更詳細的使用說明參見 gocheck的api文檔。

推薦閱讀:

相關文章