Unit Test In Go With Docker

本篇文章主要講解如何在 Docker 中進行 Go 單元測試,依賴 Docker 和 Go Modules。

爲什麼是 Docker

在 Docker 之前我們往往需要在 Jenkins 服務器上配置不同的 Go 版本以及針對每個項目配置 GOPATH,項目之間的隔離性差,經常出現基礎庫版本衝突的問題。

有了 Docker,我們可以在不同容器中運行單元測試,該測試不侷限不同項目,甚至可以是同一項目不同分支。

所以在測試隔離性和項目測試併發度上都有很大提升,而且測試結束後,環境清理也簡單許多。

爲什麼是 Go Modules

Go Modules 作爲官方默認的包管理工具,基本解決了 Go 長期存在的包管理問題,它爲我們的項目管理帶來很多好處:

  • 自動解析和添加依賴
  • 簽名驗證
  • 依賴緩存
  • 支持相對路徑依賴
  • 支持依賴一鍵打包,方便在離線環境下運行程序

實際例子

下面我們來看一個簡單例子,來自 Gin Testing Example,項目目錄結構爲:

$ tree .
.
├── go.mod
├── go.sum
├── main.go
└── main_test.go

0 directories, 4 files

main.go 內容:

package main

func setupRouter() *gin.Engine {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.String(200, "pong")
	})
	return r
}

func main() {
	r := setupRouter()
	r.Run(":8080")
}

main_test.go 內容:

package main

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestPingRoute(t *testing.T) {
	router := setupRouter()

	w := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/ping", nil)
	router.ServeHTTP(w, req)

	assert.Equal(t, 200, w.Code)
	assert.Equal(t, "pong", w.Body.String())
}

首先嚐試在主機執行 go test ./... ,測試通過,下面我們想辦法在 Docker 中進行測試。

Docker 運行測試

步驟1: 對項目依賴進行打包,方便在 Docker 無網環境下運行單元測試

go mod vendor

此時所有的依賴都打包放在項目根目錄的 vendor 下面:

$ tree .
.
├── go.mod
├── go.sum
├── main.go
├── main_test.go
└── vendor
    ├── github.com
    │   ├── davecgh
    │   │   └── go-spew
    │   │       ├── LICENSE
    │   │       └── spew
    │   │           ├── bypass.go
    │   │           ├── bypasssafe.go
    │   │           ├── common.go

步驟2: 製作 Go Docker 鏡像

因爲我們只需要 Go 的標準環境,所以可以使用官方的標準鏡像,例如 golang:1.12.1。

如果你有特殊需求,可以定製自己的 Go 鏡像, 例如自定義啓動命令,添加數據庫依賴等:

  • Dockerfile:
FROM ubuntu
RUN apt-get update && apt-get install -y libssl1.0.0 libssl-dev gcc

RUN mkdir -p /data/db /opt/go/ /opt/gopath

# go1.xx.x.linux-amd64.tar.gz 解壓縮後爲 go
ADD go /opt/go 
RUN cp /opt/go/bin/* /usr/local/bin/
ENV GOROOT=/opt/go GOPATH=/opt/gopath

WORKDIR /ws
CMD GOPROXY=off go test -mod=vendor ./...
  • 執行 docker build:
docker build . -t gotesting:v0.0.1

步驟3: 在 Docker 中運行 Golang 測試

  • 使用 golang:1.12.1:
$ docker run --volume=$(pwd):/ws \
     --workdir=/ws golang:1.12.1 \
    /bin/bash -c "GOPROXY=off go test -mod=vendor ./..."
ok  	github.com/songjiayang/gin-test	0.011s
  • 使用自定義鏡像 gotesting:v0.0.1:
docker run --volume=$(pwd):/ws gotesting:v0.0.1
ok  	github.com/songjiayang/gin-test	0.014s

可以看到兩種方式都能在 Docker 中運行 Go 單元測試,自定義鏡像可以指定默認運行命令,使操作更簡單,上面命令的含義是:

  • –volume=$(pwd):/ws :將項目根目錄映射到 Docker 容器中的 /ws 目錄。
  • –workdir=/ws : 指定容器運行工作目錄爲 /ws, 即映射外面項目根目錄。
  • /bin/bash -c “GOPROXY=off go test -mod=vendor ./…” : 表示在 Docker 中以離線,vendor 模式運行 Go 單元測試。

做的更好

到目前爲止,我們已經掌握在 Docker 中運行 Go 單元測試的方法。當然我們還可以做的更好,Docker 運行的標準輸出可以和 Jenkins 天然集成,實現項目的自動測試。

作者:songjiayang

出處:http://www.songjiayang.com/posts/go-http-zhong-flusher-zai-shi-ji-kai-fa-zhong-de-ying-yong

 

通知

51Reboot 的 Golang課程將於 1.18 日開課,Python自動化進階課程、K8s 課程 預約試聽諮詢小助手

小助手WeChat:17812796384

發佈了46 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章