Home | RU | EN

Configurations

There are several robust strategies for storing and selecting configurations - from "custom layer" (like here) to ready-made libraries. The example below doesn't use third-party libraries and is simple enough to understand.

package common.configs;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class Config {
    private static final Config INSTANCE = new Config();
    
    private final Properties properties = new Properties();

    private Config() {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("config.properties")) {
            if (inputStream == null) {
                throw new RuntimeException("config.properties is not found in resources");
            }
            properties.load(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("Fail to load config.properties", e);
        }
    }

    public static String getProperty(String key) {
        String systemValue = System.getProperty(key);
        if (systemValue != null) return systemValue;

        String envKey = key.toUpperCase().replace(".", "_")The line String envKey = key.toUpperCase().replace(".", "_"); is needed to convert a key from config.properties (e.g., admin.password) to the format accepted for environment variables in OS (e.g., ADMIN_PASSWORD).

Why this is done:

In config.properties keys are usually written in "Java-style" with dots:
admin.password=1234
db.url=jdbc:postgresql://localhost:5432/test

In environment variables in Unix/Windows they usually use uppercase and _ instead of dots:
ADMIN_PASSWORD=1234
DB_URL=jdbc:postgresql://localhost:5432/test

Therefore the method performs transformation:
key.toUpperCase() → admin.password → ADMIN.PASSWORD
.replace(".", "_") → ADMIN_PASSWORD

Thus you get unified logic for value lookup:
first we get from System.getProperty("admin.password") (e.g., if you passed -Dadmin.password=1234 when running Java),
if not found - try from System.getenv("ADMIN_PASSWORD"),
if not there either - get from config.properties.;
        String envValue = System.getenv(envKey);
        if (envValue != null) return envValue;

        return INSTANCE.properties.getProperty(key);
    }
}

Code Explanation

The Config class implements the Singleton pattern for centralized application configuration management. Key features:

Configuration Priority System

The getProperty() method implements a priority system (highest to lowest):

  1. Java System Properties (System.getProperty) - passed via -D parameters when starting JVM. This is convenient for running tests or jar directly when you want to quickly override a value (for example, to a different URL).
  2. Environment Variables (System.getenv) - set in OS, container or CI/CD pipeline
  3. config.properties file - standard method for local development

Configuration Priority Usage Examples

1. System Properties

mvn clean test -DapiBaseUrl=http://localhost

2. Environment Variables

For Docker:

services:
  backend:
    image: nobugsme/nbank:with_database
    environment:
      - APIBASEURL=http://localhost:4111
      - UIBASEURL=http://localhost:80
      - ADMIN_USERNAME=admin
      - ADMIN_PASSWORD=admin123

For CI/CD Pipeline:

- name: Run tests
  run: ./mvnw clean test -q
  env:
     UIREMOTE: http://localhost:4444/wd/hub
     APIBASEURL: http://194.87.199.75:4111
     UIBASEURL: http://194.87.199.75:80

For OS:

# Windows (PowerShell)
$env:APIBASEURL="http://localhost:3000"
$env:ADMIN_USERNAME="admin"
$env:ADMIN_PASSWORD="admin123"

# Linux/macOS (Bash)
export APIBASEURL=http://localhost:3000
export ADMIN_USERNAME=admin
export ADMIN_PASSWORD=admin123

3. config.properties file

apiBaseUrl=http://localhost:3000
admin.username=admin
admin.password=admin123

Implementation Steps:

  1. Create package common/configs in framework structure
  2. Create class Config.java in it with content from the example
  3. Create file config.properties in src/main/resources folder (example provided)
  4. Add Config.getProperty() method to tests where you need to get variables from config.properties file (example provided)

Example config.properties:

# API Configuration
apiBaseUrl=http://localhost:4111
uiBaseUrl=http://localhost
apiVersion=/api/v1

# Browser Configuration
browser=chrome
browserSize=1920x1080

# Admin Credentials
admin.username=admin
admin.password=admin

# Selenoid Configuration
uiRemote=http://localhost:4444/wd/hub

# Database Configuration
db.url=jdbc:postgresql://localhost:5433/nbank
db.username=postgres
db.password=postgres
db.driver=org.postgresql.Driver
db.table.customers=customers

Example usage in tests:

public class BaseUiTest extends BaseApiTest {
    @BeforeAll
    static void globalSelenideSetup() {
        Configuration.remote = Config.getProperty("uiRemote");
        Configuration.baseUrl = Config.getProperty("uiBaseUrl");
        Configuration.browser = Config.getProperty("browser");
        Configuration.browserSize = Config.getProperty("browserSize");
        // and so on...
    }
}