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