This article explains how to setup integration test in jenkins using dokcerized database. It is important that we should execute the integration test in CI pipeline so that we get hold of any error in the CI itself. Since integration test depends on database and other services, we need to have those installed in CI. If your application has lot of dependencies , installing those particular versions is going to be tedious. But going with docker it simplifies those dependent thing. This article explains how to do it with dockerized database.
This uses a plain script based way to run the integration test in jenkins. This uses the spring project and junit 5 testcase for demonstration purposes. Since it mostly deals with testcase and coverage, there is no controller or API as such.
Also, this article mostly concentrates on setting up integration test and dockerized database setup along with coverage feedback. I am planning to add an article explaining how to write integration testcases.
Now, we will jump to the pre-setup part. I have taken a spring boot based project. It is a simple employee CRUD application. It has data access layer and service layer. It contains certain validation such as the following:
- Employee email should be in the correct format.
- While updating employee, it should get the existing employee id.
- While updating, it cannot use an existing email of another employee.
- Non-existent employee id can't be deleted.
All those test cases are written using new JUnit 5. I have already explained about certain important features of jUnit 5 here. I have written the integration test by covering the above cases. Here is the link to the source code.
Docker can be installed using docker image or standalone installer. Here we are picking standalone installer, as we are planning to run the dependent services on docker. As it might be problematic to setup docker inside docker, I have not taken jenkins as docker image.
Jenkins can be downloaded from here - https://jenkins.io/download/ .
After installing jenkins, create a new job with name "java-int-test" and choose freestyle project. Here is how it looks like.
Jenkins job has different sections such as SCM, Build frequency, Build Commands, Post-Build setup. I will explain those in details.
SCM: It is expected to give path to the source code. Since we are going to build and run testcase, it is expected to have some source code to start with. As we are using github, I have chosed git. If it is private repo, you have to give credential, so that it can fetch the source code. Here is how the setting looks like.
Build Frequency: Here we can specify when we should build the project. I have chosen to build it hourly. We can also set it up to run on every commit to the repo. Here is my setting
Build Commands: This is the crucial step, where we specify what are the commands to execute against the source code we taken. Here is how my setting looks like.
Since we are running dockerized db, we need to install docker in the system where jenkins is running. Also we are using mariadb (mysql variant) as db for integration test, so we need to have mysql client installed in the same machine as well, becasue we need to apply db scripts before the test runs.
Here are those lines.
docker stop testdb || true
docker rm testdb || true
docker run --name testdb -p 4306:3306 -e MYSQL_ROOT_PASSWORD=root -d mariadb/server:10.3
mysql --host=127.0.0.1 --port=4306 --user="root" -proot --execute="CREATE SCHEMA IF NOT EXISTS demo_test;"
mysql --host=127.0.0.1 --port=4306 --user="root" -proot demo_test < src/main/resources/migration/V1.1__create_employee_table.sql
mysql --host=127.0.0.1 --port=4306 --user="root" -proot demo_test < src/main/resources/migration/V1.2__seed_employees.sql
mysql --host=127.0.0.1 --port=4306 --user="root" -proot -e "select * from demo_test.Employee"
./gradlew clean build test
I will explain above commands below.
- For now ignore first 2 lines, will explain them later.
- 3rd line, here we are pulling mariadb server with version as 10.3 with port mapping of 4306 of host and mysql root password being set to root. This creates a container with name as testdb.
- Since the container initialize will take some time, we have to wait till it comes up, so I put a sleep of 30s.
- Now our db is up and running, in 4 -7 th line, we are connecting to DB for various activity, i.e. create blank schema , apply db scripts and verify if everything is up and running. If you notice, to connect to docker container DB, we are using mysql --host=127.0.0.1 --port=4306 --user="root" -proot , here we are utilizing the port and credential as root / root, which we setup in 3rd line.
- In the last line, we are build our project and runing the tests.
- The first 2 lines, actually does the clean up of container. So that our test is repetable, for every run we will get a clean container with clean DB.
In test application properties, it points to the test database. Here is the setting file.
# = DATA SOURCE
# Set here configurations for the database connection
# Keep the connection alive if idle for a long time (needed in production)
I have used
gradle plugin to get the coverage report.
To publish coverage report in jenkins, I have used plugins - "JUnit Realtime Test Reporter Plugin" , "JaCoCo Plugin". To install it, Go to "Manage Jenkins" --> "Manage Plugins" --> Click on "Available" tab --> Search for above 2. Then select those and install. This requires jenkins restart, please proceed with that.
Next step is to configure those plugins to read our test report and nicely publish them to jenkins.
Here is the setting for Junit test xml. Since our test XMLs are created under `build/test-results/test/` , I have given that path there.
Here is the setting for Jacoco. I have not made any change there, it is the default one.
After setting all these up, navigate to the job we created and click on "build now" on left side. After that, you see a build number like following.
Click on the recent build number, then click on "Console output". There you can see all those commands running. If everything is succeful, then it should show in blue like above screenshot.
After successful run , here is how coverage report looks like. It will give you all type of coverages like class, line, method etc..
And here is unit test report.
You can browse through all the testcase execution from here. And you can see what all remaining lines are there to cover etc.
Points of Interest
There are a lot of things that can be done for coverage and integration test. I am listing those. You can add a lot more dependency to the jenkins build process if your application depends on those. E.g., database, cache, solr, queueing service, etc. In terms of coverage, gradle provides lot of options like mark the build as failure if certain % of coverage is not met and there can be a lot more to it.
This is my initial published content. I will keep the list of revisions here.
Revision 1: Initial publish
Revision 2: Added jenkins and dockerized db setup