大型的軟件工程項目除了大量的產品級代碼外必不可少的還有大量的自動化測試。自動化測試包含從前端到後端甚至到產品線上不一樣模塊和環境的各類類型的測試。一個比較經典的關於自動化測試分佈的理論就是測試金字塔,是說在一個正常的項目中合理的測試數量應該是單元測試 > 組件測試 > 集成測試 > 端到端測試(系統測試)> 人工驗證測試。這個理論大致上是合理的,由於從測試代碼的複雜度和執行時間看單元測試 < 組件測試 < 集成測試 < 端到端測試(系統測試)< 人工驗證測試,因此咱們理所固然應該分配更多的時間和精力到容易理解和執行快速的測試中去,好比單元測試。固然關於這些測試分類和界定的見解衆說紛紜,好比組件測試和集成測試,有時甚至是端到端測試,都一律被稱爲集成測試,由於它們在不一樣的系統層面試圖去測試兩個模塊或者系統間的集成情況。前端
最經典的集成測試的例子應該是後端系統應用層和數據層之間的集成測試了吧。數據層能夠是傳統的數據庫,也能夠是Kafka Stream這樣的新寵。一般這種集成測試有幾種思路:java
部署到staging環境中,而後在測試中發送請求到系統A,那個請求會包含對數據層系統B的讀寫操做。這個其實算是跳過集成測試到了端到端測試。但這種思路弊端不少,測試代碼複雜度高,路徑覆蓋率低,從寫出bug到檢測到bug的週期也很長,不是理想的解決方案。git
在測試中使用In-memory Embedded Database(一般是實際數據庫系統B的純內存化實現版本,主要用於這種測試環境裏),這樣就能細化到測試系統A裏面模塊X對數據庫B的某個寫操做,並且能夠在本地編寫、運行、調試,和上面的解決方案比已經有了很大的改進。可是這個解決方案仍是有幾個弊端:github
不少In-memory Embedded Database只提供一個特定版本的實現,好比MongoDB 3.2,但若是你的實際數據庫版本是4.0,那麼不少新的數據庫功能在測試里根本覆蓋不了。
有些In-memory Embedded Database甚至沒有實現100%的接口兼容,或者不同的實現方式,好比關係型數據庫的transaction實現。這意爲着就算你的測試過了,線上的代碼仍是可能會出錯。這是常見的生產環境和測試環境不一致性問題。面試
受益於Docker的普及化,testcontainers提供了另一種更爲友好的集成測試解決方案。簡單地講就是在測試環境中動態建立須要的依賴服務的容器,好比動態建立一個Mongo 3.6的容器、建立一個RabbitMQ 最新發布版的容器,而後在測試中配置測試環境讓測試應用使用建立好的容器暴露的可調用地址,測試結束後把使用過的容器銷燬防止依賴服務狀態遷移致使其餘的測試莫名地掛掉。redis
這種解決方案有如下幾個優勢:docker
固然,它也有幾個劣勢:數據庫
從編程語言支持度來講,目前testcotainers的github org上提供了Java, Scala, Go, Rust, NodeJs, Python, C#的類庫。從成熟度來講確定是Java的類庫最爲成熟,已被很多開源項目使用。其餘語言的類庫能夠想象不可避免會有些坑須要踩。編程
舉一個官網的例子來講明如何使用testcontainers類庫:後端
public class RedisBackedCacheIntTestStep0 { private RedisBackedCache underTest; @Before public void setUp() { // Assume that we have Redis running locally? underTest = new RedisBackedCache("localhost", 6379); } @Test public void testSimplePutAndGet() { underTest.put("test", "example"); String retrieved = underTest.get("test"); assertEquals("example", retrieved); } }
上面的JUnit測試中動態建立了一個redis:5.0.3-alphine容器,在setUp方法裏獲取該容器的公開地址和接口從而建立咱們要測試的RedisBackedCache實例,而後在測試裏輕輕鬆地調用該實例的方法、驗證結果。
testcontainers Java 提供了幾個現成的使用頻率較高的容器的類封裝,好比大部分數據庫(MySQL, Postgres, Cassandra, Neo4j), UI測試的Webdriver,ElasticSearch,Kafka, Nginx等等。若是你沒找到現成的封裝,你老是能夠調用更底層的GenericContainer
。它也支持主流的Java測試框架,JUnit4, JUnit 5, TestNG,Spock。總的來講對於寫Java的同窗這個類庫使用起來仍是很是爽的!