# How to Use FrameworkConstants for Centralized Configuration Management in anhtester/automationframeworkselenium

> Master centralized configuration with FrameworkConstants in anhtester/automationframeworkselenium. Load properties once for a single source of truth across your Selenium framework. Learn more!

- Repository: [Anh Tester/automationframeworkselenium](https://github.com/anhtester/automationframeworkselenium)
- Tags: how-to-guide
- Published: 2026-02-24

---

**FrameworkConstants provides a single source of truth for all configuration values by loading properties from external files once at class initialization and exposing them as public static final fields across the entire Selenium automation framework.**

The anhtester/automationframeworkselenium repository implements a robust design pattern for managing test configuration through the `FrameworkConstants` class. This centralized approach eliminates hard-coded values from test scripts and ensures that environment-specific settings can be modified without changing source code. By leveraging static initialization and property file loading, the framework achieves both type safety and runtime flexibility.

## Understanding FrameworkConstants Architecture

`FrameworkConstants` acts as the **centralized configuration hub** located at [`src/main/java/com/anhtester/constants/FrameworkConstants.java`](https://github.com/anhtester/automationframeworkselenium/blob/main/src/main/java/com/anhtester/constants/FrameworkConstants.java). Rather than scattering configuration logic throughout test classes, this class consolidates every environment variable, URL, credential, and execution flag into publicly accessible static constants. The design follows the **Single Point of Truth** principle, ensuring that changing a value in one location propagates to all consuming components immediately.

## Loading Configuration at Runtime

The framework initializes constants through a lazy-loading mechanism that reads property files exactly once during class loading. This process involves two critical components working in tandem.

**PropertiesHelpers.loadAllFiles()** handles the initial I/O operations by reading `config.properties`, `data.properties`, and `crm_locators.properties` from the resources directory. This method merges all key-value pairs into a single `java.util.Properties` instance and executes within a static block in `FrameworkConstants`, guaranteeing **one-time execution** per JVM lifecycle.

Individual constants then call `PropertiesHelpers.getValue(key)` to retrieve their assigned values. For example, the browser configuration resolves through `public static final String BROWSER = PropertiesHelpers.getValue("BROWSER");`. Because these fields are `static final`, they remain immutable after initialization while remaining globally accessible to any class in the test suite.

## Practical Implementation Examples

The following patterns demonstrate how various framework components consume these centralized constants to maintain clean, maintainable code.

### Accessing URLs and Browser Settings in Tests

Test classes reference constants directly when initializing test environments, removing the need for hard-coded strings.

```java
import com.anhtester.constants.FrameworkConstants;

// Navigate to the CRM application using centralized configuration
WebUI.openWebsite(FrameworkConstants.URL_CRM);

```

This pattern allows QA engineers to switch between staging, production, or local environments by simply updating the `URL_CRM` value in `src/test/resources/config/config.properties` without touching test logic.

### Configuring Driver Factories for Remote Execution

The `TargetFactory` class at [`src/main/java/com/anhtester/driver/TargetFactory.java`](https://github.com/anhtester/automationframeworkselenium/blob/main/src/main/java/com/anhtester/driver/TargetFactory.java) uses multiple constants to determine execution strategy and browser capabilities.

```java
import com.anhtester.constants.FrameworkConstants;
import com.anhtester.driver.BrowserFactory;

public class TargetFactory {
    public static WebDriver createDriver() {
        // Resolve browser type from centralized constant
        BrowserFactory browserFactory = BrowserFactory.valueOf(FrameworkConstants.BROWSER.toUpperCase());
        
        // Check execution target (local vs remote)
        if (FrameworkConstants.TARGET.equalsIgnoreCase("remote")) {
            return new RemoteWebDriver(
                new URL(FrameworkConstants.REMOTE_URL + ":" + FrameworkConstants.REMOTE_PORT), 
                browserFactory.getOptions()
            );
        }
        return browserFactory.createDriver(); // Local execution
    }
}

```

### Integrating with Reporting Systems

Reporting utilities leverage constants for consistent configuration across Extent Reports, Allure, and optional Telegram notifications.

```java
import com.anhtester.constants.FrameworkConstants;
import com.anhtester.reports.ExtentReportManager;

// Initialize reporting with centralized title configuration
ExtentReportManager.startReport(FrameworkConstants.REPORT_TITLE);

```

Similarly, `TelegramManager` at [`src/main/java/com/anhtester/reports/TelegramManager.java`](https://github.com/anhtester/automationframeworkselenium/blob/main/src/main/java/com/anhtester/reports/TelegramManager.java) accesses webhook URLs and authentication tokens through the same constant interface, ensuring sensitive data remains out of source control while remaining accessible to the framework.

### Controlling Execution Modes

The base test class at [`src/test/java/com/anhtester/common/BaseTest.java`](https://github.com/anhtester/automationframeworkselenium/blob/main/src/test/java/com/anhtester/common/BaseTest.java) demonstrates conditional logic using boolean-like string constants.

```java
if (FrameworkConstants.HEADLESS.equalsIgnoreCase("true")) {
    ChromeOptions options = new ChromeOptions();
    options.addArguments("--headless");
    // Additional headless configuration...
}

```

This approach enables CI/CD pipelines to toggle headless mode, video recording, or report archiving through external property files rather than code changes.

## Extending the Configuration System

Adding new configuration parameters requires minimal changes across three files. First, add the key-value pair to `src/test/resources/config/config.properties`. Next, expose the value in `FrameworkConstants` by declaring a new static field: `public static final String MY_NEW_SETTING = PropertiesHelpers.getValue("MY_NEW_SETTING");`. Finally, reference `FrameworkConstants.MY_NEW_SETTING` throughout the codebase. Because the `PropertiesHelpers` cache loads during initial class access, new constants become immediately available without modifying loading logic.

## Summary

- **FrameworkConstants** at [`src/main/java/com/anhtester/constants/FrameworkConstants.java`](https://github.com/anhtester/automationframeworkselenium/blob/main/src/main/java/com/anhtester/constants/FrameworkConstants.java) provides immutable, globally accessible configuration values as `public static final` fields.
- **PropertiesHelpers** loads `config.properties`, `data.properties`, and locator files exactly once during static initialization, eliminating repetitive I/O operations.
- Driver factories, reporting managers, and test classes reference these constants directly, keeping implementation code free of hard-coded environment details.
- The architecture supports seamless environment switching and feature toggling through external property files without requiring code recompilation.
- Extending the system involves adding keys to property files and corresponding static fields in `FrameworkConstants`.

## Frequently Asked Questions

### Where does FrameworkConstants load its values from?

`FrameworkConstants` loads values from three property files located in `src/test/resources/config/`: `config.properties` for environment settings, `data.properties` for test data, and `crm_locators.properties` for element locators. The `PropertiesHelpers.loadAllFiles()` method merges these into a single Properties object during class initialization.

### Can I modify configuration values during test execution?

No, constants are declared as `public static final`, making them immutable after the static initialization block completes. If you need dynamic configuration changes during runtime, you must interact with `PropertiesHelpers` directly rather than using the constant fields, though this pattern is discouraged as it breaks the centralized design.

### How do I add a new configuration parameter to the framework?

Add your key-value pair to `src/test/resources/config/config.properties`, then declare a corresponding field in `FrameworkConstants` using `PropertiesHelpers.getValue("YOUR_KEY")`. The new constant becomes available immediately to all classes importing `FrameworkConstants` without requiring changes to the loading mechanism.

### Why use static final fields instead of direct Properties access?

Static final fields provide **compile-time type safety**, **IDE autocomplete support**, and **refactoring capabilities** that raw Properties objects lack. Additionally, this pattern prevents typos in property keys and ensures that configuration is read exactly once, improving performance by avoiding repeated file system access during test execution.