什么是Testcontainers,為什么你應(yīng)該關(guān)心?
Testcontainers 減少了設(shè)置和拆除測試環(huán)境的摩擦,簡化了測試,從而實現(xiàn)更自信、更健壯的開發(fā)。
譯自What Is Testcontainers, and Why Should You Care?,作者 Kevin Wittek。
在現(xiàn)代軟件開發(fā)中,隨著分布式系統(tǒng)和微服務(wù)架構(gòu)的持續(xù)趨勢,以及巨大的集成界面,編寫軟件也意味著與其他系統(tǒng)集成。集成測試是確保被測系統(tǒng)持續(xù)正確性的絕佳工具,并且可以在開發(fā)周期中提供系統(tǒng)行為的快速且持續(xù)的反饋。
然而,集成測試通常需要外部依賴項,例如數(shù)據(jù)庫、消息代理或 Web 服務(wù)器,所有這些依賴項都有自己的配置和正確運行的特殊性。傳統(tǒng)上,管理這些依賴項很麻煩,容易出現(xiàn)不一致,并且難以在不同機器上復(fù)制。
從歷史上看,這使得集成測試因編寫和維護成本高而聲名狼藉。你要么必須遵循可能過時的文檔以費力的手動方式設(shè)置環(huán)境(最終只得到一個略微損壞的環(huán)境),要么使用集中維護的共享測試環(huán)境,這通常會導(dǎo)致測試污染。
這就是Testcontainers的用武之地。我的同事Oleg ?elajev將在 All Things Open 2024 上以“制作你自己的 Testcontainers 模塊,既有趣又有利可圖!”為題的演講中展示這一點。
了解 Testcontainers
Testcontainers 是一個開源庫,用于提供一次性、輕量級的數(shù)據(jù)庫、消息代理、Web 瀏覽器或幾乎可以在 Docker 容器中運行的任何東西的實例。通過利用Docker根據(jù)需要從你的代碼庫中啟動這些服務(wù)的輕量級、隔離的實例,Testcontainers 解決測試和開發(fā)期間的環(huán)境管理問題。
Testcontainers 允許開發(fā)人員使用基礎(chǔ)設(shè)施即代碼 (IaC)方法,以最小的工作量創(chuàng)建可靠且可重復(fù)的測試和開發(fā)環(huán)境。它使用熟悉的語言編寫生產(chǎn)和測試代碼,并幫助確保代碼針對真實、一致的服務(wù)進行測試。這種方法減少了設(shè)置和拆除測試環(huán)境的摩擦,并使測試更可靠、更容易維護。對于開發(fā)人員來說,Testcontainers 是一款改變游戲規(guī)則的產(chǎn)品,它簡化了測試過程,并實現(xiàn)了更自信、更穩(wěn)健的開發(fā)。
清理
Testcontainers 還會自動清理它創(chuàng)建的所有Docker資源,確保你的系統(tǒng)在運行測試后保持整潔。此清理過程與你正在使用的測試框架(例如 JUnit)無縫集成,其中容器會在測試執(zhí)行后自動停止并刪除。
此外,Testcontainers 依賴于一個名為Ryuk的專用輔助容器,它會監(jiān)視并確保所有資源都得到正確清理,即使在測試進程可能崩潰或意外終止的情況下也是如此。通過將此清理過程綁定到測試進程的生命周期,并使用 Ryuk 作為監(jiān)視程序,Testcontainers 保證不會留下任何雜散容器、網(wǎng)絡(luò)或卷,從而保持你的環(huán)境清潔,并最大程度地降低后續(xù)測試運行中資源耗盡或沖突的風(fēng)險。
模塊
Testcontainers 提供了一組豐富的模塊,其中封裝了在測試上下文中使用容器的最佳實踐,從而使將各種技術(shù)集成到你的測試套件中變得更加容易。這些模塊是針對特定技術(shù)(例如數(shù)據(jù)庫(例如PostgreSQL、MySQL)、消息代理(例如Kafka、RabbitMQ)甚至像 Selenium 這樣的用于瀏覽器測試的成熟應(yīng)用程序環(huán)境)定制的預(yù)配置 Docker 容器。
通過使用這些模塊,開發(fā)人員可以利用經(jīng)過嘗試和測試的配置,這些配置針對測試場景中的可靠性和效率進行了優(yōu)化。Testcontainers 模塊目錄提供了可用模塊的全面列表,使你能夠快速查找和實現(xiàn)所需的容器化服務(wù)。
以下兩個最小示例展示了在Java和Go:如何使用Redis鏡像定義 Docker 容器,配置其公開端口,并以等待容器內(nèi) Redis 應(yīng)用程序就緒的方式啟動容器。
在 Java 中:
GenericContainer redis = new GenericContainer("redis:5.0.3-alpine")
.withExposedPorts(379);
redis.start()
在 Go 中:
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
Image: "redis:5.0.3-alpine",
ExposedPorts: []string{"6379/tcp"},
WaitingFor: wait.ForLog("Ready to accept connections"),
},
Started: true,
})
Testcontainers Cloud
除了這些廣泛建立的開源庫之外,Testcontainers 還提供了一個產(chǎn)品,可以將這些容器無縫地卸載到云中,而無需對 Testcontainers 代碼進行任何更改:Testcontainers Cloud。通過利用 Testcontainers Cloud,您可以顯著減少本地計算機上的負(fù)載,釋放資源以執(zhí)行其他任務(wù),同時仍然運行復(fù)雜、資源密集型的測試。
圖片
這種方法可以加快您的開發(fā)工作流,并使您的測試環(huán)境與所需的 Docker 運行時(例如,x86)具有架構(gòu)同等性,因為容器是在一致且可擴展的云環(huán)境中執(zhí)行的。無論您是處理繁重的工作負(fù)載還是只想簡化測試流程,Testcontainers Cloud 都提供無縫集成,既能提高性能,又能提高可靠性,讓您能更多地專注于編碼,而無需管理本地資源。
總結(jié)
Testcontainers 是一款多功能且強大的工具,它改變了開發(fā)人員處理集成測試和本地開發(fā)的方式。通過提供一個易于使用的界面來啟動針對特定測試需求量身定制的 Docker 容器,并且可以直接從所用編程語言的熟悉性中訪問,Testcontainers 消除了與管理測試環(huán)境相關(guān)的常見挑戰(zhàn)。
借助封裝最佳實踐的模塊、自動清理以保持系統(tǒng)整潔以及將容器執(zhí)行卸載到 Testcontainers Cloud 的能力,這種方法為在測試流程中保持一致性、可靠性和效率提供了一個全面的解決方案。
無論您是希望簡化本地工作流的開發(fā)人員,還是旨在擴展云中測試的團隊,Testcontainers 都為您提供了必要的工具,以確保您的代碼在不同環(huán)境中無縫運行。通過采用 Testcontainers,您不僅可以提高測試質(zhì)量,還可以為更強大、更自信的開發(fā)周期鋪平道路。