mirror of https://github.com/docker/docs.git
179 lines
6.5 KiB
Markdown
179 lines
6.5 KiB
Markdown
---
|
||
title: "Run your tests"
|
||
keywords: Java, build, test
|
||
description: How to build and run your Tests
|
||
---
|
||
|
||
{% include_relative nav.html selected="4" %}
|
||
|
||
## Prerequisites
|
||
|
||
Work through the steps to build an image and run it as a containerized application in [Use your container for development](develop.md).
|
||
|
||
## Introduction
|
||
|
||
Testing is an essential part of modern software development. Testing can mean a lot of things to different development teams. There are unit tests, integration tests and end-to-end testing. In this guide we take a look at running your unit tests in Docker.
|
||
|
||
## Refactor Dockerfile to run tests
|
||
|
||
The **Spring Pet Clinic** source code has already tests defined in the test directory `src/test/java/org/springframework/samples/petclinic`. We can use the following Docker command to start the container and run tests:
|
||
|
||
```console
|
||
$ 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
|
||
```
|
||
|
||
### Multi-stage Dockerfile for testing
|
||
|
||
Let’s take a look at pulling the testing commands into our Dockerfile. Below is our updated multi-stage Dockerfile that we will use to build our test image. Replace the contents of your Dockerfile with the following.
|
||
|
||
```dockerfile
|
||
# syntax=docker/dockerfile:1
|
||
|
||
FROM eclipse-temurin:17-jdk-jammy as base
|
||
WORKDIR /app
|
||
COPY .mvn/ .mvn
|
||
COPY mvnw pom.xml ./
|
||
RUN ./mvnw dependency:resolve
|
||
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 eclipse-temurin:17-jre-jammy 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"]
|
||
```
|
||
|
||
We added a new build stage labeled `test`. We'll use this stage for running our tests.
|
||
|
||
Now let’s rebuild our image and run our tests. We will run the `docker build` command as above, but this time we will add the `--target test` flag so that we specifically run the test build stage.
|
||
|
||
```console
|
||
$ docker build -t java-docker --target test .
|
||
[+] Building 0.7s (6/6) FINISHED
|
||
...
|
||
=> => writing image sha256:967ac80cb7799a5d12a4bdfc67c37b5a6533c6e418c903907d3e86b7d4ebf89a
|
||
=> => naming to docker.io/library/java-docker
|
||
```
|
||
|
||
Now that our test image is built, we can run it as a container and see if our tests pass.
|
||
|
||
```console
|
||
$ 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
|
||
```
|
||
|
||
The build output is truncated, but you can see that the Maven test runner was successful and all our tests passed.
|
||
|
||
This is great. However, we'll have to run two Docker commands to build and run our tests. We can improve this slightly by using a `RUN` statement instead of the `CMD` statement in the test stage. The `CMD` statement is not executed during the building of the image, but is executed when you run the image in a container. When using the `RUN` statement, our tests run when building the image, and stop the build when they fail.
|
||
|
||
Update your Dockerfile with the following.
|
||
|
||
```dockerfile
|
||
# syntax=docker/dockerfile:1
|
||
|
||
FROM eclipse-temurin:17-jdk-jammy as base
|
||
WORKDIR /app
|
||
COPY .mvn/ .mvn
|
||
COPY mvnw pom.xml ./
|
||
RUN ./mvnw dependency:resolve
|
||
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 eclipse-temurin:17-jre-jammy 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"]
|
||
```
|
||
|
||
Now, to run our tests, we just need to run the `docker build` command as above.
|
||
|
||
```console
|
||
$ 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:resolve
|
||
=> CACHED [base 6/6] COPY src ./src
|
||
=> [test 1/1] RUN ["./mvnw", "test"]
|
||
=> exporting to image
|
||
=> => exporting layers
|
||
=> => writing image sha256:10cb585a7f289a04539e95d583ae97bcf8725959a6bd32c2f5632d0e7c1d16a0
|
||
=> => naming to docker.io/library/java-docker
|
||
```
|
||
|
||
The build output is truncated for simplicity, but you can see that our tests ran succesfully and passed. Let’s break one of the tests and observe the output when our tests fail.
|
||
|
||
Open the `src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java` file and change the assertion
|
||
|
||
```java
|
||
assertThat(violation.getMessage()).isEqualTo("must not be empty");
|
||
```
|
||
|
||
with the following.
|
||
|
||
```java
|
||
assertThat(violation.getMessage()).isEqualTo("must be empty");
|
||
```
|
||
|
||
Now, run the `docker build` command from above and observe that the build fails and the failing testing information is printed to the console.
|
||
|
||
```console
|
||
$ docker build -t java-docker --target test .
|
||
=> [base 6/6] COPY src ./src
|
||
=> ERROR [test 1/1] RUN ["./mvnw", "test"]
|
||
...
|
||
------
|
||
executor failed running [./mvnw test]: exit code: 1
|
||
```
|
||
|
||
## Next steps
|
||
|
||
In this module, we took a look at running tests as part of our Docker image build process.
|
||
|
||
In the next module, we’ll take a look at how to set up a CI/CD pipeline using GitHub Actions. See:
|
||
|
||
[Configure CI/CD](configure-ci-cd.md){: .button .primary-btn}
|
||
|
||
## Feedback
|
||
|
||
Help us improve this topic by providing your feedback. Let us know what you think by creating an issue in the [Docker Docs]({{ site.repo }}/issues/new?title=[Java%20docs%20feedback]){:target="_blank" rel="noopener" class="_"} GitHub repository. Alternatively, [create a PR]({{ site.repo }}/pulls){:target="_blank" rel="noopener" class="_"} to suggest updates.
|