2016-11-18 132 views
0

我目前正在研究爲Go中的服務創建一些單元測試,以及在該功能之上構建的其他函數,我想知道什麼是單元測試的最佳方式那在Go?我的代碼如下所示:golang中的單元測試

type BBPeripheral struct { 
    client *http.Client 
    endpoint string 
} 

type BBQuery struct { 
    Name string `json:"name"` 
} 

type BBResponse struct { 
    Brand   string `json:"brand"` 
    Model   string `json:"model"` 
    ... 
} 

type Peripheral struct { 
    Brand   string 
    Model   string 
    ... 
} 

type Service interface { 
    Get(name string) (*Peripheral, error) 
} 

func NewBBPeripheral(config *peripheralConfig) (*BBPeripheral, error) { 
    transport, err := setTransport(config) 
    if err != nil { 
     return nil, err 
    } 

    BB := &BBPeripheral{ 
     client: &http.Client{Transport: transport}, 
     endpoint: config.Endpoint[0], 
    } 

    return BB, nil 
} 


func (this *BBPeripheral) Get(name string) (*Peripheral, error) { 

    data, err := json.Marshal(BBQuery{Name: name}) 
    if err != nil { 
     return nil, fmt.Errorf("BBPeripheral.Get Marshal: %s", err) 
    } 

    resp, err := this.client.Post(this.endpoint, "application/json", bytes.NewBuffer(data)) 
    if resp != nil { 
     defer resp.Body.Close() 
    } 
    if err != nil { 
     return nil, err 
    } 
    if resp.StatusCode != http.StatusOK { 
     return nil, fmt.Errorf(resp.StatusCode) 
    } 

    var BBResponse BBResponse 

    body, err := ioutil.ReadAll(resp.Body) 
    if err != nil { 
     return nil, err 
    } 

    err = json.Unmarshal(body, &BBResponse) 
    if err != nil { 
     return nil, err 
    } 

    peripheral := &Peripheral{} 

    peripheral.Model = BBResponse.Model 
    if peripheral.Model == "" { 
     peripheral.Model = NA 
    } 

    peripheral.Brand = BBResponse.Brand 
    if peripheral.Brand == "" { 
     peripheral.Brand = NA 
    } 

    return peripheral, nil 
} 

測試該代碼,並使用這些功能來旋轉了一個單獨的goroutine要像服務器上,使用http.httptest包,還是其他什麼東西的代碼的最有效的方法是什麼?這是我第一次嘗試編寫測試,然後我不知道如何。

+2

Go有自己內置的測試工具。看到這裏https://golang.org/pkg/testing/ ...如果你在github上玩遊戲以查看其他使用得當的軟件包,你會經常遇到以_test.go結尾的文件..這些文件是進行單元測試,但使用cmd go測試並使用測試包。你提到的軟件包也是一個很好的開始。在測試之後,因爲這是一個服務器,我可能會跟進一個Siege測試來給服務器增加一些壓力,看看它是如何處理的https://www.joedog.org/siege-home/ – reticentroot

回答

1

它確實完全取決於。 Go提供了幾乎所有的測試應用程序所需的工具。

單元測試,因爲不會有太多的技巧,以動態地提供模擬/存根對象

設計是非常重要的。您可以覆蓋測試的變量,但它可以解決清理時出現的各種問題。我會專注於IO免費單元測試,以檢查您的特定邏輯是否有效。

例如,您可以測試BBPeripheral.Get方法,使client爲接口,在實例化時需要它,併爲測試提供一個存根。

func Test_BBPeripheral_Get_Success(*testing.T) { 
    bb := BBPeripheral{client: &StubSuccessClient, ...} 
    p, err := bb.Get(...) 
    if err != nil { 
    t.Fail() 
    } 
} 

然後,你可以創建一個練習錯誤處理的Get方法存根錯誤客戶端:

func Test_BBPeripheral_Get_Success(*testing.T) { 
    bb := BBPeripheral{client: &StubErrClient, ...} 
    _, err := bb.Get(...) 
    if err == nil { 
    t.Fail() 
    } 
} 

組件/集成測試

這些測試可以幫助鍛鍊是每個單位在你的包裹裏可以一起工作。由於您的代碼通過http協商,Go提供了可以使用的httptest包。

要做到這一點,測試可以創建一個httptest服務器,並註冊一個處理程序來提供this.endpoint所期望的響應。然後,您可以使用其公共界面請求NewBBPeripheral,傳入this.endpoint對應的Server.URL屬性。

這使您可以模擬您的代碼與真實服務器交談。

去例行檢驗

轉到使得它很容易編寫併發代碼,並使它一樣容易測試。測試生成執行NewBBPeripheral的去例程的頂級代碼可能看起來非常像上面的測試。除了啓動測試服務器之外,測試還需要等待異步代碼完成。如果您沒有廣泛的服務取消/關閉/信號完整的服務,那麼可能需要使用go例程對其進行測試。

競爭危害/負載測試

使用轉到內置的bechmark測試與-race標誌結合在一起,你可以輕鬆地鍛鍊你的代碼,並簡介它競爭條件,充分利用你上面寫的測試。


有一點要記住,如果你的應用的實現仍然在不斷變化,編寫單元測試可能會花費大量的時間。創建一個測試代碼,這些測試代碼可以執行代碼的公共接口,可以讓您輕鬆驗證您的應用程序是否正在運行,同時允許實現發生變化。