We use properties files all over for our development to store configurable data of our applications and the same is true when it comes to test automation. We store config params in properties files.
Properties files store data as key-value pairs similar to a Java map data structure. Below is an example of a properties file.
server.host.name=testing.com
parallel=true
maxThreads=100
· Need to maintain a separate code to read/write values to properties file
· Keys can get duplicated and hence values may differ
· Type conversion has to be managed
Good news!
<dependency>
<groupId>org.aeonbits.owner</groupId>
<artifactId>owner</artifactId>
<version>1.0.8</version>
</dependency>
In this article, let’s use the above example and develop our code leveraging owners library.
Next is to generate the interface to load the properties in the file.
import
org.aeonbits.owner.Config;public interface ServerConfig extends Config {
boolean parallel(); @Key("server.host.name")
String hostname(); @DefaultValue("5")
int maxThreads();
}
Moreover, if you look closely at the maxThreads, you can specify the default value as a safety net.
Now the question is how do you map the two files, the properties file, and the java interface.
Rule 1
If both the files are in the same package, with the same name, then the owners will find and read the value of the properties file.
Rule 2
In most cases, we want to store the properties file in a separate directory and hence you need to specify the file path using @sources annotation as below.
My file is residing inside the resources folder under the test package.
@org.aeonbits.owner.Config.Sources({
"file:./src/test/resources/config.properties"})
public interface ServerConfig extends Config {
boolean parallel(); @Key("server.host.name")
String hostname(); @DefaultValue("5")
int maxThreads();
}
With all these, next is to use the values from the properties files inside our application.
We are initiating the ServerConfig via the ConfigFactory provided by the owners.
ServerConfig
cfg = ConfigFactory.create(ServerConfig .class);
cfg.hostname;
cfg.maxThreads;
Final Thoughts
· The owners library helps to remove the boilerplate code used for reading properties files.
· Owners takes care of type conversion and load strategies
· Owners library is an annotation-based library easy to maintain.