2016-11-18 7 views
0

私は現在、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 
} 

このコードとパッケージをhttp.httptest使用し、サーバーのように行動するために別のゴルーチンをスピンアップするために、これらの機能を使用するコード、または何か他のものをテストするための最も効率的な方法ですか?それは私が本当にどのように知っていないテストを書くことを試みることは初めてです。

+2

ゴーは、それがテストツールに組み込まれています所有しています。こちらをご覧くださいhttps://golang.org/pkg/testing/ ...うまく使用されている他のgoパッケージを見るためにgithubを見て回ると、_test.goで終わるファイルを見つけることがよくあります。これらのファイルは単体テスト用ですが、cmd goテストとテストパッケージを使用しています。また、あなたが言及したパッケージは、始めるのにも良い場所です。あなたのテストの後、これはサーバーなので、私は恐らくSiegeテストをフォローしてサーバーに何らかのストレスを加え、https://www.joedog.org/siege-home/ – reticentroot

答えて

1

本当に完全に依存します。 Goは、すべての単一レベルでアプリケーションをテストするのに必要なすべてのツールを提供します。

ユニットは

動的モック/スタブオブジェクトを提供するために、多くのトリックが存在しないので、デザインが重要であるかどうかをテストします。テスト用に変数をオーバーライドすることはできますが、クリーンアップを行うことであらゆる種類の問題が解消されます。私はあなたの特定のロジックが動作することを確認するIOフリーユニットテストに焦点を当てます。

たとえば、clientをインスタンス化時に要求し、テスト用のスタブ1を提供するインターフェイスにすることで、BBPeripheral.Getメソッドをテストできます。

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パッケージを提供します。

これを行うには、this.endpointが期待する応答を提供するためにハンドラを登録したhttptestサーバーを作成します。 NewBBPeripheralを要求し、Server.URLプロパティに対応するthis.endpointを渡して、パブリックインターフェイスを使用してコードを実行することができます。

これにより、コードをシミュレートして、実際のサーバーと通信することができます。

Goはそれがとても簡単に並行コードを書くことができ、それは同じように簡単にそれをテストすることができますルーチンをテストします。 NewBBPeripheralを実行するgoルーチンを生成するトップレベルコードをテストすると、上記のテストと非常によく似ています。テストサーバーを起動するだけでなく、テストでは非同期コードが完了するまで待つ必要があります。キャンセル/シャットダウン/シグナルの完全なサービスを提供していない場合は、goルーチンを使用してテストする必要があります。

競合状態/負荷テスト

使用して、外出先の-raceフラグと組み合わせbechmarkテストに建てられ、あなたが簡単にあなたが上に書いたテストを活用し、あなたのコードを行使し、競合状態のためにそれをプロファイルすることができます。


アプリケーションの実装が依然として流動的である場合、単体テストの作成には時間がかかることがあります。コードのパブリックインターフェイスを使用する2つのテストを作成することで、アプリケーションの動作を簡単に確認し、実装を変更できるようにする必要があります。