In my scrum team, there are 3 separate test repositories for 3 different services (let's say A, B, and C). The problem is through time, there are a lot of code duplications accumulated between them, which makes it hard to keep the maintainability well. For example if there’s an update to the waitUtil() function in C, we will have to make that change in other 2 repositories (A and B) as well, which is painful.
1. Solution
We centralize code that can be shared in one place, then package it as a jar file (dependency/library). Any repository that includes that jar file can access the common functions. If there’s a new version of the library rolled out, just update the library's version in pom.xml (Maven is our main build tool and dependency manager) where you want to download it, new dependency will be automatically downloaded and applied.
The solution sounds promising, but it also yields some new problems:
- How to maintain the jar file’s version?
- How can we download the jar file easily? We don’t want to include the file manually in each project every time there’s a new version available. That would be more painful.
That’s why we want to put our jar file onto a dependency platform (similar to Maven Repository) so anyone who wants to include our jar file in their project, they just need to put the corresponding dependency tag in their pom.xml. But, since our code is quite sensitive and internal, we definitely don’t want to put our jar file on a public repository, and that’s how Nexus Repository came into the picture.
Nexus Repository OSS is an open source repository that supports many artifact formats, including Docker, Java™, and npm. With Nexus, we can build and host our own dependency platform without publishing our sensitive libraries to the outside world.
However, in case you still want to include the file manually (for testing the availability), put scope and systemPath in your custom dependency tag to point to the jar file. That jar file, of course, should be included in your test project. Take a look at below screenshot to have an idea.
2. Let's build the jar file
Let's say I put all resources into A repository, I would like B and C to be able to access to these resources.Basically, we want to utilize everything under resources directory. For now, I package the whole test project, I will package only resources folder later in the future. |
2.1 Contribute distribution management
This is where we define the repository that we will upload the file to. We assume that you've already had internal Nexus Repository set up. It would usually be done by your DevOps team.
<distributionManagement>
<snapshotRepository>
<id>api-tests</id>
<name>Internal development</name>
<url>https://nexus.abc.com/repository/awesome_repo/</url>
</snapshotRepository>
</distributionManagement>
2.2 Configure Nexus credentials on Local Machine
In order to connect to Nexus to upload/download dependencies, we would need to put the Nexus credentials where Maven can pick up. By default, Maven will look into .m2 directory and look for settings.xml file. Or you can also specify a particular settings file when running test with Maven: mvn clean test -Dtest=TestRunner -s settings.xml -Dkarate.env=uat.
<?xml version="1.0" encoding="UTF-8"?>
<settings
xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>api-tests</id>
<username>{nexus_username}</username>
<password>{nexus_password}</password>
</server>
</servers>
</settings>
2.3 Upload the jar file
Make sure to configure the jar file's version in pom.xml |
Now when you run mvn clean deploy -DskipTests, the jar file will be packaged and automatically uploaded to Nexus repostiory:
If you look into your .m2 directory at /repository/com/api/automation/service-test/1.0.46-SNAPSHOT, you can find the jar file there as well.
3. Let's utilize the jar file
Now let’s say from B repository, I want to download and utilize that jar I have built. What should I do? I'll go to B repository, in pom.xml, I need to specify that dependency and the Nexus repository I want to connect to.
<dependency>
<groupId>com.api.automation</groupId>
<artifactId>service-test</artifactId>
<version>1.0.46-SNAPSHOT</version>
<classifier>tests</classifier>
</dependency>
<repositories>
<repository>
<id>api-tests</id>
<name>Internal development</name>
<url>https://nexus.abc.com/repository/awesome_repo/</url>
</repository>
</repositories>
You can right click on pom.xml select “Reload Projects” to apply the new library. If it doesn’t work, execute this command: mvn dependency:resolve
To make sure the jar file has been downloaded properly, in vscode, you can go to Java Projects, look for that file and check out if all the resources that you’ve built are there.
Now everything is ready, let’s try calling waitUntil function from resources/utils/common.feature file:
Feature: Test shared utils
Scenario: Test waitUntil() util
* def common = call read('classpath:../resources/utils/common.feature')
* def aService = call read('classpath:../resources/services/a.feature')
* common.waitUntil(() => aService.getUserById('123456') != null)
4. Conclusion
That’s it! Thank you for reading this article. I hope that it has brought you an idea on how to build and share a jar file, and how to utilize it between in other places. If there’s any questions, please feel free to drop me a comment or message. I would love to hear out and discuss with you. Have a great day!