This post belongs to the How to create Lean Test Automation Architecture for Web using Java series. If you didn’t see the previous posts, please check them out!
A good practice when we are creating an automated test framework using Java is the creation of properties files to add any configuration that can be changed either manually in the file or when you are running the tests using a CI/CD tool.
It’s commonly used to change the URL, main users, timeout, or whatever data you need to change frequently as a configuration.
The main problem is to manage one or more properties files we might have in our project. This article will show you how to easily manage it with Owner Java library.
Let’s imagine we will use a property file to manage the different data and/or configuration for a web test. We have this file as an example:
There are a lot of ways we can read a property file using Java. This example is a simple one using the Singleton design pattern:
Now we can get a value from the property file as:
String url = ReadProperties.getInstance().getValue("url.base");
Owner is a library that makes easy the properties file management.
You can easily read properties values by:
You can use Owner importing its library. Please double-check the latest version.
<dependencies> <dependency> <groupId>org.aeonbits.owner</groupId> <artifactId>owner</artifactId> <version>1.0.8</version> </dependency> </dependencies>
We will model a class containing the properties as an interface and extending the Owner
Config class. We also need to use an annotation to define the configuration file.
general.propertiesfile that is placed in the classpath
Configclass (this class does most of the Owner’s magic).
Owner will do the trick automatically if you have the property’s names as the same defined in the properties file. Example: the
target() attribute in the class has the same name as the target property in the general.properties file.
If you have a composite name, as we have for
url.base you can use the
@Config.Key annotation to associate the property in the
general.properties file into the class.
Another benefit is that you can use the correct object types. The headless attribute is a
Boolean, so Owner will automatically do the type inference.
Basically, we need to create the model and use it! Easy, right?
GeneralConfigclass and attribute receiving the
ConfigFactory.create(GeneralConfig.class). This line will tell Owner to load the
general.propertiesfile and associate all the properties and values to the
generalConfigto read the properties values. Each method will return the corresponding property value.
Do you have multiple properties files to handle? No problem!
You can create one model for each property or you can merge them all in one. The first option you already know after you got here and I will explain the merge approach.
Let’s say you have, in addition to the
general.properties file, a new one named
Now how we can merge both?
@Config.LoadPolicy(Config.LoadType.MERGE)annotation to tell Owner to merge files.
So now you can have only one model do use more than one properties file.
Probably you will use a CI/CD tool to configure your application, run tests, and other magic activities. This is managed, in Java, by the System properties where we can set through the code or using command line parameters. For properties file, we use
Now we need to tell Owner to look at the System properties.
"system.properties"sources, so Owner can first look at it and set the property value
We were creating the model object to access the properties values using
GeneralConfig generalConfig = ConfigFactory.create(GeneralConfig.class);
You would add this line in every class you need to access the properties values, right? But you will end up creating multiple instances of the same object. In this case, it should be a singleton.
Owner provides a similar class as
ConfigFactory but instead of creating a new object every time we need to access the properties values, the
ConfigCache class can be used.
ConfigCache.getOrCreate Owner will create a single instance of the model. You can learn more about this approach here.
Would you like to see real examples? I have examples for Web, API, and Mobile projects.
In my selenium-java-lean-test-architecture project you can found:
In my restassured-complete-basic-example project you can found:
In my appium-parallel-execution project you can found: