运行测试
预计阅读时间:7分钟
先决条件
完成“使用容器进行开发”中的步骤来构建映像并将其作为容器化应用程序运行。
介绍
测试是现代软件开发的重要组成部分。对于不同的开发团队来说,测试可能意味着很多事情。有单元测试,集成测试和端到端测试。在本指南中,我们将介绍如何在Docker中运行您的单元测试。
重构Dockerfile以运行测试
在春季宠物诊所的源代码已经测试在测试目录中定义src/test/java/org/springframework/samples/petclinic
。您只需更新您的JaCoCo版本,pom.xml
以确保您的测试可通过结合在JDK v15或更高版本上使用<jacoco.version>0.8.6</jacoco.version>
,因此我们可以使用以下Docker命令来启动容器并运行测试:
$ docker run -it --rm --name springboot-test java-docker ./mvnw test
...
[INFO] Results:
[INFO]
[WARNING] Tests run: 40, Failures: 0, Errors: 0, Skipped: 1
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:49 min
用于测试的多阶段Dockerfile
让我们看一下将测试命令拖入我们的Dockerfile中。下面是一个多阶段Dockerfile,我们将使用它来构建生产映像和测试映像。将突出显示的行添加到您的Dockerfile中
# syntax=docker/dockerfile:1
FROM openjdk:16-alpine3.13 as base
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
FROM base as test
CMD ["./mvnw", "test"]
FROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]
FROM base as build
RUN ./mvnw package
FROM openjdk:11-jre-slim as production
EXPOSE 8080
COPY --from=build /app/target/spring-petclinic-*.jar /spring-petclinic.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/spring-petclinic.jar"]
我们首先在FROM openjdk:16-alpine3.13
语句中添加标签。这使我们可以在其他构建阶段中引用此构建阶段。接下来,我们添加了一个名为的新构建阶段test
。我们将使用此阶段来运行我们的测试。
现在,让我们重建图像并运行测试。我们将docker build
如上所述运行命令,但是这次我们将添加--target test
标志,以便我们专门运行测试构建阶段。
$ docker build -t java-docker --target test .
[+] Building 0.7s (6/6) FINISHED
...
=> => writing image sha256:967ac80cb7799a5d12a4bdfc67c37b5a6533c6e418c903907d3e86b7d4ebf89a
=> => naming to docker.io/library/java-docker
现在我们的测试映像已构建,我们可以将其作为容器运行,并查看我们的测试是否通过。
$ docker run -it --rm --name springboot-test java-docker
[INFO] Scanning for projects...
[INFO]
[INFO] ------------< org.springframework.samples:spring-petclinic >------------
[INFO] Building petclinic 2.4.2
...
[INFO] Results:
[INFO]
[WARNING] Tests run: 40, Failures: 0, Errors: 0, Skipped: 1
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:22 min
构建输出被截断,但是您可以看到Maven测试运行程序成功完成并且我们所有的测试都通过了。
这很棒。但是,我们必须运行两个Docker命令来构建和运行我们的测试。我们可以通过使用RUN
语句而不是CMD
测试阶段中的语句来稍微改进一下。该CMD
语句在构建映像期间不会执行,但是在容器中运行该映像时会执行。使用该RUN
语句时,我们的测试将在构建映像时运行,并在它们失败时停止构建。
用下面突出显示的行更新您的Dockerfile。
# syntax=docker/dockerfile:1
FROM openjdk:16-alpine3.13 as base
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
FROM base as test
RUN ["./mvnw", "test"]
FROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]
FROM base as build
RUN ./mvnw package
FROM openjdk:11-jre-slim as production
EXPOSE 8080
COPY --from=build /app/target/spring-petclinic-*.jar /spring-petclinic.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/spring-petclinic.jar"]
现在,要运行测试,我们只需要运行上述docker build
命令即可。
$ docker build -t java-docker --target test .
[+] Building 27.6s (11/12)
=> CACHED [base 3/6] COPY .mvn/ .mvn
=> CACHED [base 4/6] COPY mvnw pom.xml ./
=> CACHED [base 5/6] RUN ./mvnw dependency:go-offline
=> CACHED [base 6/6] COPY src ./src
=> [test 1/1] RUN ["./mvnw", "test", "-Dspring-boot.run.profiles=mysql"]
=> exporting to image
=> => exporting layers
=> => writing image sha256:10cb585a7f289a04539e95d583ae97bcf8725959a6bd32c2f5632d0e7c1d16a0
=> => naming to docker.io/library/java-docker
为了简化起见,构建输出被截断了,但是您可以看到我们的测试成功运行并通过了。让我们中断其中一项测试,并在测试失败时观察输出。
打开src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java
文件并将第57行更改为以下内容。
55 ConstraintViolation<Person> violation = constraintViolations.iterator().next();
57 assertThat(violation.getPropertyPath().toString()).isEqualTo("firstName");
57 assertThat(violation.getMessage()).isEqualTo("must be empty");
58 }
现在,docker build
从上方运行命令,观察构建失败,并将失败的测试信息打印到控制台。
$ docker build -t java-docker --target test .
=> [base 6/6] COPY src ./src
=> ERROR [test 1/1] RUN ["./mvnw", "test", "-Dspring-boot.run.profiles=mysql"]
...
------
executor failed running [./mvnw test]: exit code: 1
多阶段Dockerfile进行开发
新版本的Dockerfile会生成一个最终的图像,该图像已准备好用于生产,但是您会注意到,您还有一个专门的步骤来生产开发容器。
FROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]
现在,我们可以更新docker-compose.dev.yml
该更新,以使用此特定目标来构建petclinic
服务并删除command
定义,如下所示:
services:
petclinic:
build:
context: .
target: development
ports:
- 8000:8000
- 8080:8080
environment:
- SERVER_PORT=8080
- MYSQL_URL=jdbc:mysql://mysqlserver/petclinic
volumes:
- ./:/app
现在,让我们运行Compose应用程序。现在,您应该看到该应用程序的行为与以前相同,并且您仍然可以对其进行调试。
$ docker-compose -f docker-compose.dev.yml up --build
下一步
在本模块中,我们将运行测试作为Docker映像构建过程的一部分进行了介绍。
在下一个模块中,我们将看一下如何使用GitHub Actions建立CI / CD管道。看:
反馈
通过提供您的反馈帮助我们改善此主题。通过在Docker Docs GitHub存储库中创建问题,让我们知道您的想法。或者,创建PR以建议更新。