聚會時間公告: 因應COSCUP 2011, Kalug 8月份休會一次

十一月 17, 2016

小惡魔AppleBOY
AppleBOY
is about »

tag cloud

» 輕量級 Gofight 支援 Echo 框架測試

Go-brown-side.sh Gofight 是一套用 Golang 撰寫的輕量級測試工具,專門測試 Golang Web Framework API,可以參考之前一篇教學: 用 gofight 來測試 golang web API handler,在 Echo 框架發布 v3.0.0 之前,Echo 不支援 golang 標準的 http.Requesthttp.ResponseWriter,反倒是支援 fasthttp,所以我發了 Issue 希望作者可以支援原生的 http 標準,最後沒有得到回應。就在前幾天 Echo 在 v3.0.0 版本把 fasthttp 拿掉,這樣 Gofight 就可以移除特定函示,改用原生 http。

gofight v1 寫法 (舊式)

舊版 gofight v1 針對 Echo 框架測試寫法
func TestEchoPostFormData(t *testing.T) {
    r := New()

    r.POST("/form").
        SetBody("a=1&b=2").
        RunEcho(framework.EchoEngine(), func(r EchoHTTPResponse, rq EchoHTTPRequest) {
            data := []byte(r.Body.String())

            a, _ := jsonparser.GetString(data, "a")
            b, _ := jsonparser.GetString(data, "b")

            assert.Equal(t, "1", a)
            assert.Equal(t, "2", b)
            assert.Equal(t, http.StatusOK, r.Status())
        })
}

gofight v2 寫法 (新式)

新版 gofight v2 針對 Echo 框架測試寫法
func TestEchoPut(t *testing.T) {
    r := New()

    r.PUT("/update").
        SetBody("c=1&d=2").
        Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) {
            data := []byte(r.Body.String())

            c, _ := jsonparser.GetString(data, "c")
            d, _ := jsonparser.GetString(data, "d")

            assert.Equal(t, "1", c)
            assert.Equal(t, "2", d)
            assert.Equal(t, http.StatusOK, r.Code)
        })
}
可以看到只要取代底下 func 就可以無痛轉換
  • RunEcho => Run
  • EchoHTTPResponse => HTTPResponse
  • EchoHTTPRequest => HTTPRequest

載入新版方式

下載 Gofight v2

$ go get gopkg.in/appleboy/gofight.v2

載入 Gofight v2

import "gopkg.in/appleboy/gofight.v2"

後記

Gofight 有用 glide 做 vendor 套件控管,但是支援 Echo 框架後,發現測試突然壞了,產生了另外 Issue,如果是使用 go get -d -t ./... 安裝方式就沒有問題,之後再找時間解決此問題。

四月 6, 2016

小惡魔AppleBOY
AppleBOY
is about »

tag cloud

» 用 gofight 來測試 golang web API handler

Go-brown-side.sh 身為一位後端工程師,如果專案初期階段不導入測試,等到專案越來越大時,您就會發現,解了一個 bug,又產生好多個額外 bug,讓產品一直處於不穩定狀態。後端最主要提供前端或手機端 RESTFul API,所以今天來介紹一套 gofight 工具,用來測試 Golang 的 http handler,讓開發者可以送 Form, JSON, Raw 資料,後端處理後,可以拿到 response 資料,透過 Testify 來測試資料是否符合需求。 目前大部份的 Golang Web Framework 都可以透過 gofight 來測試,除非作者有把 ServeHTTP 改成自己定義 Response,不然基本上都是可以支援的,我自己測試了 Gin, Mux, HttpRouter 都是可以使用的,底下來看看 gofight 該如何使用。

安裝方式

$ go get -u github.com/appleboy/gofight
-u 代表將 local 端程式碼更新到最新

使用方式

不多說直接先看例子,用 golang 基本的 http handler
package main

import (
  "io"
  "net/http"
)

func BasicHelloHandler(w http.ResponseWriter, r *http.Request) {
  io.WriteString(w, "Hello World")
}

func BasicEngine() http.Handler {
  mux := http.NewServeMux()
  mux.HandleFunc("/", BasicHelloHandler)

  return mux
}
撰寫測試
package main

import (
  "github.com/appleboy/gofight"
  "github.com/stretchr/testify/assert"
  "net/http"
  "testing"
)

func TestBasicHelloWorld(t *testing.T) {
  r := gofight.New()

  r.GET("/").
    // trun on the debug mode.
    SetDebug(true).
    Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {

      assert.Equal(t, "Hello World", r.Body.String())
      assert.Equal(t, http.StatusOK, r.Code)
    })
}

自訂 header

透過 SetHeader 可以自訂 Request header
func TestBasicHelloWorld(t *testing.T) {
  r := gofight.New()
  version := "0.0.1"

  r.GET("/").
    // trun on the debug mode.
    SetDebug(true).
    SetHeader(gofight.H{
      "X-Version": version,
    }).
    Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {

      assert.Equal(t, version, rq.Header.Get("X-Version"))
      assert.Equal(t, "Hello World", r.Body.String())
      assert.Equal(t, http.StatusOK, r.Code)
    })
}

自訂 Form Data

透過 SetFORM 來傳送 Form Data
func TestPostFormData(t *testing.T) {
  r := gofight.New()

  r.POST("/form").
    SetFORM(gofight.H{
      "a": "1",
      "b": "2",
    }).
    Run(BasicEngine(), func(r HTTPResponse, rq HTTPRequest) {
      data := []byte(r.Body.String())

      a, _ := jsonparser.GetString(data, "a")
      b, _ := jsonparser.GetString(data, "b")

      assert.Equal(t, "1", a)
      assert.Equal(t, "2", b)
      assert.Equal(t, http.StatusOK, r.Code)
    })
}

自訂 JSON Data

透過 SetJSON 來傳送 JSON Data
func TestPostJSONData(t *testing.T) {
  r := gofight.New()

  r.POST("/json").
    SetJSON(gofight.D{
      "a": 1,
      "b": 2,
    }).
    Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
      data := []byte(r.Body.String())

      a, _ := jsonparser.GetInt(data, "a")
      b, _ := jsonparser.GetInt(data, "b")

      assert.Equal(t, 1, int(a))
      assert.Equal(t, 2, int(b))
      assert.Equal(t, http.StatusOK, r.Code)
    })
}

自訂 RAW Data

透過 SetBody 來傳送 RAW Data
func TestPostRawData(t *testing.T) {
  r := gofight.New()

  r.POST("/raw").
    SetBody("a=1&b=1").
    Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
      data := []byte(r.Body.String())

      a, _ := jsonparser.GetString(data, "a")
      b, _ := jsonparser.GetString(data, "b")

      assert.Equal(t, "1", a)
      assert.Equal(t, "2", b)
      assert.Equal(t, http.StatusOK, r.Code)
    })
}
更多測試可以直接參考 gofight_test.go 程式碼

support:

biggo.com.tw

biggo.sg

A Django site.