搜尋
首頁後端開發Golang透過 testcontainers-go 和 docker-compose 來利用您的測試套件

Leverage Your Test Suite With testcontainers-go & docker-compose

皆さん、おかえりなさい!今日は、興味深いブログ投稿でエンドツーエンドのテストについて取り上げます。このような種類のテストを書いたことがない場合、またはテストを改善しようと努力している場合は、このエキサイティングな旅を説明するので読み続けてください。この記事を最後まで読むと、testcontainers-go パッケージを使用してテスト スイートを有効に活用する方法がわかります。

前提?

先に進む前に、このブログ投稿の境界線を設定しましょう。いくつかの概念、ツール、テクニックについて説明するためです。

サバイバルリスト?️

このブログ投稿の残りの部分でいくつかのトピックに触れることになるので、ここでそれらをまとめておくのが良いと思います。

このブログ投稿全体で私が紹介するツールには、私がよく知っているツールと初めて使用したツールが混在しています。これらのツールをむやみに使用するのではなく、シナリオに基づいて評価してください。

私たちは以下に依存します:

  • Go プログラミング言語
  • ドッカー
  • compose モジュールを含む testcontainers-go パッケージ
  • ginkgo テスト フレームワークと gomega アサーション パッケージ

読み物が膨大になるのを避けるため、ここで紹介するトピックのすべての側面や側面を取り上げるつもりはありません。必要に応じて、関連ドキュメントの URL を記載します。

シナリオ?

私たちが所有していないプロジェクトに対してエンドツーエンドのテストを作成する必要があると仮定しましょう。私の場合、Java プログラミング言語で書かれたプロジェクトに対してエンドツーエンドのテストを書きたいと考えています。私は Java でコーディングする方法を知らなかったので、テストのオプションはエンドツーエンドのテストのみでした。私がテストしなければならなかったサービスは、REST API のセットでした。解決策は明らかです。HTTP リクエストを発行してエンドポイントを実行します。

ブラック ボックスのように公開された機能をテストできます。処理する必要があるのは、サーバーに何を送信し、サーバーから何を取得するかという公開表面だけです。それ以上でもそれ以下でもありません。

私たちは、データベース (MySQL インスタンス) 内の銀行口座をリストする API/accounts エンドポイントに注目します。次の 2 つのリクエストを発行します:

HTTP Method Address Expected Status Code
GET api/accounts?iban=IT10474608000005006107XXXXX 200 StatusOK
GET api/accounts?iban=abc 400 StatusBadRequest

現在,您應該對我們的目標有了更清晰的了解。那麼,讓我們進入測試程式碼。

讓我們玩得開心嗎?

在本節中,我將介紹我們需要為可怕的端到端測試編寫的所有相關程式碼。

docker-compose.yml 文件

由於我們不關心原始程式碼,因此起點是 docker-compose.yml 檔案。相關代碼為:


services:
  mysqldb:
    image: "mysql:8.0"
    container_name: mysqldb
    restart: always
    ports:
      - 3307:3306
    networks:
      - springapimysql-net
    environment:
      MYSQL_DATABASE: transfers_db
      MYSQL_USER: bulk_user
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  api_service:
    build: .
    container_name: api_service
    restart: always
    ports:
      - 8080:8080
    networks:
      - springapimysql-net
    environment:
      - spring.datasource.url=jdbc:mysql://mysqldb:3306/transfers_db
      - spring.datasource.username=bulk_user
      - spring.datasource.password=root
    depends_on:
      mysqldb:
        condition: service_healthy
    volumes:
      - .m2:/root/.m2

networks:
  springapimysql-net:



文件內容非常簡單。我們可以總結以下列表中定義的內容:

  • mysqldb 服務不需要任何進一步的解釋
  • api_service 服務是我們正在測試的系統
  • springapimysql-net 網站寄存上面定義的兩個服務

更多 Docker Compose 參考,您可以查看此處。現在,讓我們看看端到端的測試程式碼。

銀杏測試框架

ginkgo 測試框架幫助我們建立測試套件。它完全是用 Go 寫的。此外,它還提供了一個 CLI 實用程式來設定和運行測試。因為稍後我們會使用它,所以我們從這裡下載它。您可以透過兩種方式下載:

  1. 使用 go install 指令(如果您已在系統上安裝了 Go)
  2. 透過下載已編譯的二進位(如果您的系統上沒有安裝 Go,則很有用)

要檢查您的電腦上是否有可用的實用程序,您可以執行命令 ginkgo version (在撰寫本文時,我的版本是 2.20.2)。

請注意,ginkgo 指令不是執行測試所必需的。您仍然可以透過堅持 go test 命令來在沒有此實用程式的情況下執行測試。

但是,我強烈建議下載它,因為我們將使用它來產生一些樣板程式碼。

以銀杏打基礎

位於根目錄中,讓我們建立一個名為 end2end 的資料夾來託管我們的測試。在這個資料夾中,透過發出指令 go mod init path/to/your/module 來初始化 Go 模組

現在,是時候執行 ginkgo bootstrap 指令了。它應該會產生一個名為 end2end_suite_test.go 的新檔案。該文件會觸發我們稍後定義的測試套件。

此方法類似 testify/suite 套件的方法。由於定義和運行階段是分開的,它增強了程式碼的模組化和穩健性。

現在,讓我們將測試添加到我們的套件中。要產生我們的測試所在的文件,請執行另一個 ginkgo 指令:ginkgogeneratecounts。這次,檔案accounts_test.go 彈出。現在,讓我們保持原樣並切換到終端。我們透過執行 Go 命令 go mod tidy 將缺少的依賴項下載到我們的電腦本機來修復遺失的軟體包。

end2end_suite_test.go 文件

讓我們從測試套件的入口點開始。文件內容看起來很整潔:


//go:build integration

package end2end

import (
 "testing"

 . "github.com/onsi/ginkgo/v2"
 . "github.com/onsi/gomega"
)

func TestEnd2End(t *testing.T) {
 RegisterFailHandler(Fail)
 RunSpecs(t, "End2End Suite")
}



唯一不尋常的事情可能是導入部分中的點導入。您可以在此處的文檔中閱讀有關它的更多資訊。

哎喲!出現野生測試容器?

在某些時候,我們需要一些魔法才能進入下一個測試等級。恰好是 testcontainers-go。為了這個演示,我們使用 compose 模組(更多參考,請參閱此處)。

該工具可以運行我們之前看到的 compose 文件,並對正在運行的容器執行端到端測試。

這是 testcontainers-go 功能的摘錄。如果您想了解更多信息,請參閱文件或聯絡我們。我很樂意帶您了解其令人驚嘆的功能。

這個套件允許使用單一指令運行端到端套件。這是運行這些測試的更一致和原子的方式。它讓我能夠:

  1. 在套件之前啟動容器
  2. 依賴這些容器運行測試
  3. 套件後拆除容器並清理所使用的資源

以這種方式編寫程式碼可以幫助您避免處理 docker cli 命令和 makefile 的麻煩。

accounts_test.go 文件

現在,讓我們來看看我們的測試所在的程式碼。


//go:build integration

package end2end

import (
 "context"
 "net/http"
 "os"

 . "github.com/onsi/ginkgo/v2"
 . "github.com/onsi/gomega"
 tc "github.com/testcontainers/testcontainers-go/modules/compose"
 "github.com/testcontainers/testcontainers-go/wait"
)

var _ = Describe("accounts", Ordered, func() {
 BeforeAll(func() {
 os.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true")
 composeReq, err := tc.NewDockerComposeWith(tc.WithStackFiles("../docker-compose.yml"))
  Expect(err).Should(BeNil())
  DeferCleanup(func() {
   Expect(composeReq.Down(context.Background(), tc.RemoveOrphans(true), tc.RemoveImagesLocal)).Should(BeNil())
  })
 ctx, cancel := context.WithCancel(context.Background())
  DeferCleanup(cancel)
 composeErr := composeReq.
   WaitForService("api_service", wait.ForListeningPort("8080/tcp")).
   Up(ctx, tc.Wait(true))
  Expect(composeErr).Should(BeNil())
 })

 Describe("retrieving accounts", func() {
  Context("HTTP request is valid", func() {
   It("return accounts", func() {
 client := http.Client{}
 r, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/accounts?iban=IT10474608000005006107XXXXX", nil)
 res, err := client.Do(r)
    Expect(err).Should(BeNil())
    Expect(res).To(HaveHTTPStatus(http.StatusOK))
   })
  })

  Context("HTTP request is NOT valid", func() {
   It("err with invalid IBAN", func() {
 client := http.Client{}
 r, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/accounts?iban=abcd", nil)
    Expect(err).Should(BeNil())
 res, err := client.Do(r)
    Expect(err).Should(BeNil())
    Expect(res).To(HaveHTTPStatus(http.StatusBadRequest))
   })
  })
 })
})



乍一看,似乎很難消化。為了讓事情變得更簡單,讓我們把它分成更小的部分。

描述容器節點

Describe 容器節點只不過是一個包裝器,用來保存我們套件的相關程式碼。一切都必須生活在其中。它是腳手架程式碼的一部分:var _ =Describe("accounts", Ordered, func() {}。在{} 中,您應該放置所有相關程式碼。要強制使用設定節點(像BeforeAll一樣),我們必須將Describe容器定義為Ordered。

如果您忘記添加它,請不要擔心,因為 Go 編譯器會抱怨。

我們繼續吧。

BeforeAll 設定節點

這個節點允許我們提取通用的設定邏輯。此程式碼部分在套件內的測試之前執行一次。讓我們回顧一下正在做的事情:

  • 將環境變數 TESTCONTAINERS_RYUK_DISABLED 設定為 true。您可以在此處了解配置資訊。如果你對 Ryuk 感到好奇,你可能想看看這個
  • 根據我們提供的 docker-compose.yml 檔案建立一個 *tc.DockerCompose 變數
  • 延後函數呼叫以終止容器和清理資源
  • 啟動撰寫堆疊並等待名為 api_service 的容器啟動並準備好偵聽 8080/tcp 連接埠

我簡化了測試程式碼,因為我不想讓這篇文章變得更長? .

最後,測試! ?

測試函數位於描述容器節點中。您可以參考這裡來了解ginkgo是如何處理測試規範的。描述節點可讓您根據測試範圍對測試進行分組和組織。您可以將此節點巢狀在其他描述節點中。

Describe節點嵌套越多,測試範圍就越窄。

然後,我們就有了限定父描述的上下文容器節點。它限定了測試有效的情況。最後,我們有 It 部分,即 Spec 主題。這是我們正在執行的實際測試,並且是層次結構樹的葉子層級。測試程式碼是不言自明的,因此我將跳到執行測試的部分。

3, 2, 1...?

恭喜?我們設法到達這裡。現在,我們只錯過了試運行操作。眨眼間,我們的測試執行報告就會印到終端上。

讓我們切換到終端並執行命令 ginkgo --tags=integration -v。一段時間後,您將看到終端上列印的輸出。

結束語 ?

我知道這篇文章濃縮了很多內容。我的目標是提供有關如何編寫良好的測試套件的見解和方法。您可能希望使所提供的工具、套件和技術適應其他類型的測試或用例。

在離開之前,我想強調一下 testcontainers-go 套件的 compose 模組的另一個優點。

如果您堅持使用我提供的配置,您一定會使用最新的 Docker 映像,並且可以避免因使用過時的映像而花費數小時進行故障排除。它類似於命令 docker compose build --no-cache && docker compose up。你會感謝我嗎?

感謝各位朋友的關注!如果您有任何問題、疑慮、回饋或意見,我可以一起傾聽和說話。如果您希望我介紹一些具體概念,請與我聯絡。下次見,保重,再見?

以上是透過 testcontainers-go 和 docker-compose 來利用您的測試套件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Go語言包導入:帶下劃線和不帶下劃線的區別是什麼?Go語言包導入:帶下劃線和不帶下劃線的區別是什麼?Mar 03, 2025 pm 05:17 PM

本文解釋了GO的軟件包導入機制:命名imports(例如導入“ fmt”)和空白導入(例如導入_ fmt; fmt;)。 命名導入使包裝內容可訪問,而空白導入僅執行t

Beego框架中NewFlash()函數如何實現頁面間短暫信息傳遞?Beego框架中NewFlash()函數如何實現頁面間短暫信息傳遞?Mar 03, 2025 pm 05:22 PM

本文解釋了Beego的NewFlash()函數,用於Web應用程序中的頁間數據傳輸。 它專注於使用newflash()在控制器之間顯示臨時消息(成功,錯誤,警告),並利用會話機制。 Lima

Go語言中如何將MySQL查詢結果List轉換為自定義結構體切片?Go語言中如何將MySQL查詢結果List轉換為自定義結構體切片?Mar 03, 2025 pm 05:18 PM

本文詳細介紹了MySQL查詢結果的有效轉換為GO結構切片。 它強調使用數據庫/SQL的掃描方法來最佳性能,避免手動解析。 使用DB標籤和Robus的結構現場映射的最佳實踐

如何編寫模擬對象和存根以進行測試?如何編寫模擬對象和存根以進行測試?Mar 10, 2025 pm 05:38 PM

本文演示了創建模擬和存根進行單元測試。 它強調使用接口,提供模擬實現的示例,並討論最佳實踐,例如保持模擬集中並使用斷言庫。 文章

如何定義GO中仿製藥的自定義類型約束?如何定義GO中仿製藥的自定義類型約束?Mar 10, 2025 pm 03:20 PM

本文探討了GO的仿製藥自定義類型約束。 它詳細介紹了界面如何定義通用功能的最低類型要求,從而改善了類型的安全性和代碼可重複使用性。 本文還討論了局限性和最佳實踐

Go語言如何便捷地寫入文件?Go語言如何便捷地寫入文件?Mar 03, 2025 pm 05:15 PM

本文詳細介紹了在GO中詳細介紹有效的文件,將OS.WriteFile(適用於小文件)與OS.openfile和緩衝寫入(最佳大型文件)進行比較。 它強調了使用延遲並檢查特定錯誤的可靠錯誤處理。

您如何在GO中編寫單元測試?您如何在GO中編寫單元測試?Mar 21, 2025 pm 06:34 PM

本文討論了GO中的編寫單元測試,涵蓋了最佳實踐,模擬技術和有效測試管理的工具。

如何使用跟踪工具了解GO應用程序的執行流?如何使用跟踪工具了解GO應用程序的執行流?Mar 10, 2025 pm 05:36 PM

本文使用跟踪工具探討了GO應用程序執行流。 它討論了手冊和自動儀器技術,比較諸如Jaeger,Zipkin和Opentelemetry之類的工具,並突出顯示有效的數據可視化

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能