go build 无文件_Go 质量保证:集成测试(1) 用 Docker 执行测试
點擊上方藍色“Go語言中文網”關注我們,領全套Go資料,每天學習?Go?語言
簡介
“測試會帶來失敗,而失敗會帶來理解。” —— Burt Rutan
Burt Rutan 是一名航空航天工程師,他設計了 Voyager,這是第一架在不停車或加油的情況下環球飛行的飛機。雖然 Rutan 不是軟件工程師,但他的話充分說明了測試的重要性,甚至是軟件測試。所有形式的軟件測試都非常重要,無論是單元、集成、系統還是驗收測試。但是,根據項目的不同,一種形式的測試可能比其他形式更有價值。換句話說,有時一種形式的測試可以比其他形式更好地反映軟件的健康和完整性。
在開發 Web 服務時,我相信一組強大的集成測試可以比其他類型的測試更好地分析這個 Web 服務。集成測試是一種軟件測試形式,用于測試代碼與應用程序利用的依賴項(如數據庫和消息傳遞系統)之間的交互。如果沒有集成測試,很難信任 Web 服務的端到端操作。我之所以這么說,是因為在 Web 服務中的單元測試很少能提供與集成測試相媲美的信息量。
這是關于 Go 語言集成測試的三部曲系列中的第一篇文章。本系列中分享的想法、代碼和流程旨在輕松應用到您正在處理的 Web 服務項目。在這篇文章中,我將向您展示如何配置 Web 服務項目以使用 Docker 和 Docker Compose 在沒有預先安裝 Go 的受限計算環境中運行 Go 測試和依賴項。
為什么使用 Docker 和 Docker Compose
眾多開發者使用 Docker,是因為它能夠在無需手動安裝管理應用程序的前提下,在主機上加載應用程序。這意味著您可以加載復雜的軟件,包括但不限于數據庫(例如 Postgres),消息傳遞系統(例如 Kafka)和監控系統(例如 Prometheus)。所有這一切都是通過下載一組代表應用程序及其所有依賴項的鏡像來完成的。
注意:想要了解有關容器的更多信息,可以參考 Docker 專門用于定義容器的網頁[1],該網頁還重點說明了容器和虛擬機之間的異同。
Docker Compose 是一種容器編排工具,有助于在一個沙箱內構建、運行并用網絡連接一組容器。使用一個命令 docker-compose up,您可以使 Docker Compose 文件運行起來。在 Compose 文件中定義的所有服務將成為一組在其自己的網絡沙箱中依照配置運行的容器。這與手動構建、運行和聯網每個容器相比,是另一種使容器一起運行、相互通信并持久化數據的方式。
既然 Docker Compose 允許您將不同的應用組合到一起,并在一個網絡沙箱中運行,您就可以只用一條命令做到啟停一整套的應用。您甚至可以從一組應用中,手動挑選出個別應用來運行。這組應用可以被部署成一個獨立的單元,通過 CI (集成開發)環境構建并測試。Docker Compose 最終將幫助確保您的應用在所有測試和部署的環境中保持一致。
注意:想要了解更多關于 Docker Compose 的內容,請點此[2] 訪問 Docker 官方網站對于 Docker Compose 的介紹。
Docker 和 Docker Compose 的另一大好處是,它們能簡化新的開發者加入一個項目時的交接過程。不需要關于如何安裝、管理開發環境的復雜文檔,新開發者只需要執行幾條 Docker 和 Docker Compose 命令就可以開始工作了。如果在應用啟動時,主機上沒有所需的鏡像,Docker CLI 會負責處理鏡像的下載。
使用 Docker 和 Docker Compose 來運行測試
貫穿本系列的 Web 服務應用例子對外暴露簡單的增刪改查 REST API 接口,并使用 Postgres 數據庫。這個項目在生產環境和測試中,都使用 Docker 來運行 Postgres 數據庫。這個應用的測試要能夠在一個已經安裝了 Go 的本地開發環境以及一個沒有 Go 的受限環境中運行。
下面給出的 Docker Compose 文件支持在上述的兩種環境中運行這個項目的集成測試。本節中,我將分解我所采用的配置選項,并逐一解釋。
清單 1
version:在清單 1 中,可以看到這個 Docker Compose 文件定義了需要運行測試的所需要項目服務。這個文件有三個主要的鍵值:version,networks 以及 services。其中 version 鍵值定義了正在使用的 Docker Compose 版本。而 networks 鍵值定義了一個或多個供特定服務使用的網絡配置。services 鍵值則定義了要啟動的容器和容器的配置。
清單 2
networks:如果將服務定義在同一個 Compose 文件中,按照默認設定,它們就會被自動地放在同一個網絡中,因此可以相互之間通信。但最好的做法還是為服務創建一個網絡,而不是使用默認網絡。這頂層的 networks 配置定義了網絡的名字以及所用的驅動,在這里用到的是 bridge 驅動。
bridge 驅動是 Docker 提供的默認驅動,它將創建一個私有的內部網絡供容器進行通信。在 Compose 文件中的服務定義配置里,規定了這些服務將要使用這個新創建的網絡。
清單 3
services:services 鍵有兩個直接子鍵,分別是 listd_test 和 db。其中 listd_tests 用 dockerfile 的形式定義了它的鏡像。而 context 鍵說明所有的主機目錄都要相對于當前的工作目錄,如這里定義的 .。
清單 4
listd_tests:depends_on 鍵會讓 listd_tests 服務等待 db 服務啟動之后再開始運行。除了明確啟動的先后順序,這個鍵還禁止了 listd_tests 服務獨立于 db 服務運行。volumes 鍵告訴 Compose 在容器中將當前目錄(記為 $PWD,Print Working Directory)掛載到 /go/src/github.com/george-e-shaw-iv/integration-tests-example,這將成為代碼存放和測試的位置。
清單 5
listd_tests:最后,服務被賦予了一個網絡,以便在沙箱內進行通信。這個網絡最初在頂層的 networks 鍵中被定義,具體可見清單 2。
清單 6
db:在下一個服務定義中的容器 db,用 Docker Hub 中的鏡像[3]postgres:1.11 來定義自身的容器鏡像。Docker CLI 足夠的智能,在本地機器上找不到鏡像的話,會去 Docker Hub 鏡像倉庫尋找。
清單 7
db:出于安全考慮,默認情況下沒有一個容器端口是可以通過主機訪問的。這帶來了一個問題,當本地運行集成測試時,如果集成的服務無法被訪問,那測試將沒有多少價值。這個 prots 鍵定義了從主機到容器的端口映射,形式如下:" 主機端口 : 容器端口 "。按照清單 7 中的定義,主機上的 5432 端口將被映射到 db 容器上,這個端口是 Postgres 在容器中默認的運行端口。
清單 8
db:正如容器端口不會默認暴露給主機一樣,容器的端口也不會默認暴露給網絡沙箱中的其他容器。即使這些容器是在同一個網絡中運行也是如此。要想將端口暴露給運行在網絡沙箱中的其他容器,就要通過 expose 鍵來配置。
注意:在 postgres:1.11 鏡像中,端口 5432 已經由容器創建者設置成對外暴露。但除非您親自查看鏡像的 Dockerfile,您很難獲悉鏡像的端口是否已經被設為暴露,所以最好還是定義 expose 鍵,哪怕它是多余的。
清單 9
db:容器 db 需要的最后幾個配置選項是 environment,restart 和 networks。與之前的服務定義類似,networks 的值為已被定義過的網絡的名字。將 restart 鍵設為 on-failure 以確保服務會在運行中途崩潰時自動重啟。environment 選項包含了注入到容器 shell 中的一系列環境變量。大多數主流應用的鏡像,例如 postgres,都有用來配置其所提供的應用的環境變量。
運行測試
在 Docker Compose 文件準備好之后,下一步就是基于 listd_tests 服務中提到的 dockerfile 構建鏡像。這個 dockerfile 定義了一個能夠為整個服務運行集成測試的鏡像。一旦鏡像創建完成,測試就可以運行了。
構建一個能運行測試的鏡像
為了構建一個能運行測試的鏡像,在 dockerfile 中要定義四樣東西:
獲取一個帶有最新穩定版 Go 的基礎鏡像。為 Go Modules 安裝 git。將可測試的代碼復制到容器中。運行測試。
讓我們來分解這幾個步驟,并對 dockerfile 需要涉及的命令進行分析。
清單 10
FROM golang:清單 10 展示的是四步中的第一步。我選用的基礎操作系統鏡像是 golang:1.11-alpine。這個鏡像預裝了最新的穩定版 Go(在寫這篇博文的時候)。
清單 11
FROM golang:因為 Alpine OS 是非常輕量級的,您必須在基礎鏡像之上,手動安裝 git 依賴。清單 11 展示的是第二步,將 git 添加到鏡像中,為了后續使用 Go Modules。其中 apk update 命令要在添加 git 之前運行,以確保安裝的是最新版本的 git。如果您的項目恰好要使用 cgo,那么您必須手動安裝 gcc 以及它的依賴庫。
清單 12
FROM golang:為了方便使用,清單 12 中設置工作目錄為 /go/src/github.com/george-e-shaw-iv/integration-tests-example/,以便在后續的指令中可以使用基于這個目錄的相對路徑,這也是容器中的 $GOPATH。過程中的第三步,將測試代碼拷貝到容器里,實際已經在清單 4 中完成,含有測試代碼的目錄已經被掛載到容器中。
清單 13
FROM golang:最后,清單 13 代表第四步,運行測試。這是用一條 CMD 指令 go test ./... 實現的。
測試使用 CGO_ENABLED=0 作為內聯環境變量運行,因為示例項目的測試沒有用到 cgo 并且 Alpine 基礎鏡像也不包含 C 編譯器。即使您的項目中沒有 cgo 代碼,也必須以這種方式禁用 cgo,因為如果啟用了 cgo,Go 仍會嘗試使用標準 C 庫來執行某些網絡任務。
注意:定義這個能運行 Go 測試的鏡像的完整 Dockerfile 代碼可以訪問 這一網站[4] 獲取。
現在定義鏡像的 dockerfile 已經寫好了,下面的 Docker Compose 命令能夠啟動 listd_test 和 db 服務,它們將運行所有的集成測試并反饋結果。
清單 14
docker-compose -f docker-compose.test.yml up --build --abort-on-container-exit其中 --abort-on-container-exit 標志位不能省略,否則其他包含這個集成服務的容器會在測試結束后繼續運行。
善后工作
清單 15
test:停止并刪除容器、持久卷和網絡是完成測試后非常重要的一步,而這一步經常會被忽略。由上次測試的遺留數據所導致的測試失敗,其錯誤的原因難以發現,因此不容易解決,但這個問題是非常容易避免的。想要避免這個問題發生,我創建了一個簡單的 makefile 規則 test,如清單 15 所示,無需任何人力參與也能創建、運行并清除容器。
清單 16
test-db-up:在清單 15 中列出的規則最好在受限的環境中使用,因為它們將 compose 文件中的兩個服務都啟動了。為了在本地測試中達到相同的效果,test-db-up 規則可以在運行集成測試之前使用,在所有測試執行完成后使用 testdb-down。
結論
在本片博文中,我向您展示了如何用 Docker 和 Docker Compose 部署 Web 服務項目。我所提及的這些文件能夠使您在沒有預裝 Go 的受限環境下,運行 Go 測試和依賴項。在本系列的下一部分,我將展示為 Web 服務配置測試套件所需的 Go 代碼,這將是編寫富有洞察力的集成測試的基礎。
注意:本系列文章用到的例子都來自 這個倉庫[5]。
推薦閱讀
通過測試學習Go:Mocking
關于Go語言位移細節的幾個小測試
喜歡本文的朋友,歡迎關注“Go語言中文網”:
Go語言中文網啟用微信學習交流群,歡迎加微信:274768166
總結
以上是生活随笔為你收集整理的go build 无文件_Go 质量保证:集成测试(1) 用 Docker 执行测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米10谷歌连携失败_Android 1
- 下一篇: python 拆分excel工作表_Py