五分鐘教程:如何在Docker當中運行平行測試
譯文【51CTO.com快譯】 如果想在Docker中運行平行測試,你可能會引起容器名沖突的錯誤,下面我們來談談如何避免這種錯誤。當你在CI環境下運行測試時,有時候要運行平行測試。這種平行程序需要使用編譯工具,如詹金斯、Gradle或者Maven插件。
如果你在使用Docker作為應用程序的外部測試工具(例如數據庫、郵件服務器、FTP服務器),你會發現一個大問題,就是在運行平行測試時,在Docker主機里,所有文件會新建一個相同命名的容器,以至于在你開始第二個平行測試時,你會得到一個關于沖突的容器名失敗,因為Docker主機試圖啟動兩個相同命名的容器,或者這兩個容器具有相同的綁定端口。
針對這個問題,你可以這樣解決:
·你可以用一個Docker主機分別給每個文件做平行測試。
·你可以重復使用相同的Docker主機并且使用Arquillian Cube Star運算器。
Arquillian Cube是Arquillian的一個擴展,可以用來在你的測試中管理Docker容器。使用Arquillian Cube,你需要在計算機上運行一個Docker保護(可以是本地的或者不是),但大多數是本地的。
Arquillian Cube提供了三種不同的方法來定義容器:
·定義一個容器組成文件
·定義一個容器對象
·使用容器對象DSL
在下面的事例中,我將向您展示如何使用Docker組成和容器對象DSL。Star運算器可以讓你指示Arquillian Cube隨機命名Cube,并且可以調整鏈接。這樣一來,在執行平行測試時,就不會因為名稱或者綁定端口發生沖突了。
我們來看一個例子:
- plugins {
- id "io.spring.dependency-management" version "1.0.2.RELEASE"
- }
- apply plugin: 'java'
- repositories {
- mavenCentral()
- jcenter()
- }
- dependencyManagement {
- imports {
- mavenBom 'org.jboss.arquillian:arquillian-bom:1.1.13.Final'
- }
- }
- dependencies {
- testCompile 'junit:junit:4.12'
- testCompile 'org.jboss.arquillian.junit:arquillian-junit-standalone'
- testCompile 'org.arquillian.cube:arquillian-cube-docker:1.3.2'
- }
- test {
- maxParallelForks = 2
- testLogging.showStandardStreams = true
- }
- #src/test/docker/docker-compose.yml
- redis*:
- image: redis:3.0.7
- ports:
- - "6379"
- @RunWith(Arquillian.class)
- public class TestOne {
- @HostPort(containerName = "redis*", value = 6379)
- private int portBinding;
- @Test
- public void should_print_port_binding() throws InterruptedException {
- System.out.println(TestOne.class.getCanonicalName() + " - " + portBinding);
- TimeUnit.SECONDS.sleep(4);
- }
- }
你可以看到Docker-組成yml文件從一個典型的Docker-組成文件發生的重要轉變,它的名字是以星號(*)或者redis*結束的,這個名字應該是動態生成的。這里有三個測試,我們給大家演示***個,其他兩個也大同小異。
基本上,打印控制臺綁定端口連接到服務器。最終建立一個gradle文件,執行兩個平行試驗,所以如果你在gradle運行測試,你會發現兩個測試是同時執行的,當一個完成的時候,另一個也執行完畢了。然后,當你檢查輸出時,你會看到下一個輸出。
- org.superbiz.parallel.runner.TestOne STANDARD_OUT
- CubeDockerConfiguration:
- serverUri = tcp://192.168.99.100:2376
- machineName = dev
- certPath = /Users/alex/.docker/machine/machines/dev
- tlsVerify = true
- dockerServerIp = 192.168.99.100
- definitionFormat = COMPOSE
- clean = false
- removeVolumes = true
- dockerContainers = containers:
- redis_9efae4a8-fcb5-4f9e-9b1d-ab591a5c4d5a:
- alwaysPull: false
- image: redis:3.0.7
- killContainer: false
- manual: false
- portBindings: !!set {56697->6379/tcp: null}
- readonlyRootfs: false
- removeVolumes: true
- networks: {}
- org.superbiz.parallel.runner.TestThree STANDARD_OUT
- CubeDockerConfiguration:
- serverUri = tcp://192.168.99.100:2376
- machineName = dev
- certPath = /Users/alex/.docker/machine/machines/dev
- tlsVerify = true
- dockerServerIp = 192.168.99.100
- definitionFormat = COMPOSE
- clean = false
- removeVolumes = true
- dockerContainers = containers:
- redis_88ff4b81-80cc-43b3-8bbe-8638dd731d8e:
- alwaysPull: false
- image: redis:3.0.7
- killContainer: false
- manual: false
- portBindings: !!set {56261->6379/tcp: null}
- readonlyRootfs: false
- removeVolumes: true
- networks: {}
- //......
- org.superbiz.parallel.runner.TestThree > should_print_port_binding STANDARD_OUT
- org.superbiz.parallel.runner.TestOne - 56261
- org.superbiz.parallel.runner.TestOne > should_print_port_binding STANDARD_OUT
- org.superbiz.parallel.runner.TestOne - 56697
- org.superbiz.parallel.runner.TestTwo > should_print_port_binding STANDARD_OUT
- org.superbiz.parallel.runner.TestOne - 56697
正如你在日志中看到的,容器的名字不是Redis或redis*,但是redis后面跟一個UUID。此外你還可以看到,當輸出打印時,綁定端口在每個情況下都是不同的。
如果你不想用docker組成的方式,你也可以用DSL容器對象的方法以編程方式定義容器,也可以支持Star運算器。我們來看看這種情況下的事例:
- @ClassRule
- public static ContainerDslRule redisStar =
- new ContainerDslRule("redis:3.2.6", "redis*")
- .withPortBinding(6379);
這個使用容器對象的方法是相同的,你需要Arquillian Cube1.4.0來運行它以及容器對象。基于這一特點,你可以運行任何程度的平行測試,因為Arquillian Cube可以照顧到命名和端口綁定問題。請注意,在容器之間鏈接的情況下,你依然需要運行Star運算器,它將在運行時解決某些問題。了解更多Star運算器請點擊這里。
原文作者:Alex Soto
原文標題:Running Parallel Tests in Docker
劉妮娜譯
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】