ConfNG
Configuration Management for TestNG Projects
Built for TestNG with extensible support for other Java applications. Simplify loading and resolving configuration values from multiple sources with precedence-based resolution, type safety, and automatic TestNG parameter injection.
// Define configuration keys
public enum TestConfig implements ConfNGKey {
BROWSER("browser"),
BASE_URL("base.url"),
TIMEOUT("timeout");
// Implementation...
}
// Built for TestNG projects with extensible Java support
// TestNG parameters automatically injected via service loader
// Load configuration sources
ConfNG.loadProperties("test.properties");
ConfNG.loadJson("config.json");
// TestNG projects: testng.xml parameters are automatically available:
// <parameter name="browser" value="firefox"/>
// <parameter name="base.url" value="https://staging.example.com"/>
// Use in TestNG tests or other Java applications
@Test
public void testConfiguration() {
String browser = ConfNG.get(TestConfig.BROWSER); // From testng.xml or other sources
Integer timeout = ConfNG.getInt(TestConfig.TIMEOUT); // Type-safe conversion
// Your test logic...
}
Why Choose ConfNG?
Multiple Sources
Environment variables, system properties, properties files, JSON files, custom sources, and automatic TestNG parameter injection with configurable precedence.
Type Safety
Enum-based configuration keys with compile-time checking and automatic type conversion for integers and booleans.
High Performance
Eager resolution of configuration values during initialization saves resources and improves runtime performance.
Auto-discovery
Automatic scanning for configuration keys using reflection with support for custom package filtering.
Secret Management
Built-in support for secret managers like AWS Secrets Manager and HashiCorp Vault with caching and error handling.
Extensible
Easy to add custom configuration sources and integrate with existing systems through clean interfaces.
TestNG-First Design
Built specifically for TestNG projects with zero-configuration parameter injection that automatically captures and injects all parameters from testng.xml, with extensible support for other Java applications.
Quick Start
Add Dependency
dependencies {
implementation 'org.confng:confng:1.0.1'
}
<dependency>
<groupId>org.confng</groupId>
<artifactId>confng</artifactId>
<version>1.0.1</version>
</dependency>
Define Configuration Keys
import org.confng.api.ConfNGKey;
public enum TestConfig implements ConfNGKey {
BROWSER("browser", "chrome"),
BASE_URL("base.url", "http://localhost:8080"),
TIMEOUT("timeout", "30"),
HEADLESS("headless", "false");
private final String key;
private final String defaultValue;
TestConfig(String key, String defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
}
@Override
public String getKey() {
return key;
}
@Override
public String getDefaultValue() {
return defaultValue;
}
}
Load Configuration Sources
import org.confng.ConfNG;
public class TestConfig {
static {
// Built for TestNG projects, extensible for other Java applications
// TestNG parameters are automatically injected when TestNG is present
// Load configuration files (optional - skipped if not found)
ConfNG.loadProperties("test.properties");
ConfNG.loadJson("config.json");
// Add custom sources if needed
ConfNG.registerSource(new CustomConfigSource());
}
}
Use in TestNG Tests
// Primary use case: TestNG test projects
@Test
public void testWebApplication() {
// TestNG parameters from testng.xml are automatically available!
// No listener registration or manual setup required
// Get configuration values with type safety
String browser = ConfNG.get(TestConfig.BROWSER); // From testng.xml or other sources
String baseUrl = ConfNG.get(TestConfig.BASE_URL); // From testng.xml or other sources
Integer timeout = ConfNG.getInt(TestConfig.TIMEOUT); // From testng.xml or other sources
Boolean headless = ConfNG.getBoolean(TestConfig.HEADLESS);
// Use configuration in your tests
WebDriver driver = createDriver(browser, headless);
driver.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
driver.get(baseUrl);
}
// Also works in other Java applications
public class DatabaseService {
public void connect() {
String dbUrl = ConfNG.get(AppConfig.DATABASE_URL);
String apiKey = ConfNG.get(AppConfig.API_KEY);
// Your application logic...
}
}
TestNG-First with Extensible Support
ConfNG is built for TestNG projects with extensible support for other Java applications:
- โ TestNG-First: Designed specifically for TestNG test projects
- โ Automatic Detection: Detects TestNG on classpath and activates features
- โ Zero Configuration: Registers parameter injection listener via service loader
- โ Parameter Capture: Captures all testng.xml parameters (suite, test, method levels)
- โ Smart Precedence: Handles parameter precedence (method > test > suite)
- โ Thread-Safe: Concurrent test execution support
- โ Extensible: Can be used in other Java applications when needed
Built for TestNG, extensible for more!
Documentation
๐ User Guide
Complete guide covering all features, configuration sources, and advanced usage patterns.
Read Guide๐ง API Reference
Detailed API documentation with all classes, methods, and configuration options.
View APIExamples
Basic Configuration Usage
// Configuration files
// test.properties
browser=chrome
base.url=https://staging.example.com
timeout=30
// config.json
{
"browser": "firefox",
"base.url": "https://prod.example.com",
"timeout": 45
}
// Java code - primarily for TestNG projects
public enum TestConfig implements ConfNGKey {
BROWSER("browser", "chrome"),
BASE_URL("base.url", "http://localhost"),
TIMEOUT("timeout", "30");
// Constructor and methods...
}
// In TestNG tests
@BeforeClass
public void setup() {
ConfNG.loadProperties("test.properties");
ConfNG.loadJson("config.json");
}
@Test
public void testApplication() {
String browser = ConfNG.get(TestConfig.BROWSER);
String url = ConfNG.get(TestConfig.BASE_URL);
Integer timeout = ConfNG.getInt(TestConfig.TIMEOUT);
// Precedence: Env > System Props > TestNG Params > Properties > JSON
// If BROWSER env var is set, it overrides file values
WebDriver driver = createDriver(browser);
driver.get(url);
}
// Also works in other Java applications
public class ConfigService {
public void loadConfig() {
ConfNG.loadProperties("app.properties");
String value = ConfNG.get(AppConfig.SOME_VALUE);
// Use configuration...
}
}
Secret Manager Integration
// Custom AWS Secrets Manager integration
public class AWSSecretsSource extends SecretManagerSource {
private final SecretsManagerClient client;
public AWSSecretsSource() {
super(300000); // 5 minute cache timeout
this.client = SecretsManagerClient.builder()
.region(Region.US_EAST_1)
.build();
}
@Override
public String getName() {
return "AWSSecretsManager";
}
@Override
protected String fetchSecret(String secretId) throws Exception {
GetSecretValueRequest request = GetSecretValueRequest.builder()
.secretId(secretId)
.build();
GetSecretValueResponse response = client.getSecretValue(request);
return response.secretString();
}
}
// Usage
AWSSecretsSource secretSource = new AWSSecretsSource();
secretSource.addKeyMapping("db.password", "prod/database/password");
secretSource.addKeyMapping("api.key", "prod/external-api/key");
ConfNG.loadSecretSource(secretSource);
// In tests
String dbPassword = ConfNG.get(DatabaseConfig.PASSWORD);
String apiKey = ConfNG.get(ApiConfig.KEY);
Custom Configuration Sources
// Custom database configuration source
public class DatabaseConfigSource implements ConfigSource {
private final Map<String, String> configCache = new HashMap<>();
private final DataSource dataSource;
public DatabaseConfigSource(DataSource dataSource) {
this.dataSource = dataSource;
loadConfigurations();
}
@Override
public String getName() {
return "DatabaseConfig";
}
@Override
public Optional<String> get(String key) {
return Optional.ofNullable(configCache.get(key));
}
private void loadConfigurations() {
try (Connection conn = dataSource.getConnection()) {
PreparedStatement stmt = conn.prepareStatement(
"SELECT config_key, config_value FROM app_config WHERE active = true"
);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
configCache.put(rs.getString("config_key"), rs.getString("config_value"));
}
} catch (SQLException e) {
throw new RuntimeException("Failed to load database configuration", e);
}
}
}
// Register the custom source
ConfNG.registerSource(new DatabaseConfigSource(dataSource));
TestNG Integration Features
// ConfNG is built for TestNG projects!
// When TestNG is detected on classpath, automatic features activate
// testng.xml example:
// <suite name="Test-Suite">
// <parameter name="browser" value="chrome"/>
// <parameter name="base.url" value="https://staging.example.com"/>
// <test name="Smoke-Tests">
// <parameter name="browser" value="firefox"/> <!-- Overrides suite level -->
// <parameter name="timeout" value="45"/>
// <classes><class name="com.example.SmokeTest"/></classes>
// </test>
// <test name="Regression-Tests">
// <parameter name="browser" value="edge"/>
// <classes><class name="com.example.RegressionTest"/></classes>
// </test>
// </suite>
// Configuration enum
public enum TestConfig implements ConfNGKey {
BROWSER("browser", "chrome"),
BASE_URL("base.url", "http://localhost:8080"),
TIMEOUT("timeout", "30");
// Standard implementation...
}
// TestNG test class - automatic parameter injection!
public class SmokeTest {
@Test
public void testAutomaticParameterInjection() {
// โจ TestNG feature: parameters automatically injected!
// Zero configuration - ConfNG detects TestNG and activates listener
String browser = ConfNG.get(TestConfig.BROWSER); // "firefox" (from test level)
String baseUrl = ConfNG.get(TestConfig.BASE_URL); // "https://staging.example.com" (from suite)
Integer timeout = ConfNG.getInt(TestConfig.TIMEOUT); // 45 (from test level)
System.out.println("Browser: " + browser); // firefox
System.out.println("Base URL: " + baseUrl); // https://staging.example.com
System.out.println("Timeout: " + timeout); // 45
// TestNG precedence: Method > Test > Suite > Other sources
}
@Test
public void testMixedSources() {
// TestNG parameters work alongside other sources
ConfNG.loadProperties("test.properties");
// TestNG parameters have high precedence (priority 80)
// They override properties files but not env vars or system props
String browser = ConfNG.get(TestConfig.BROWSER);
// Use in Selenium tests, API tests, etc.
WebDriver driver = WebDriverFactory.create(browser);
// Test implementation...
}
}
// Extensible: works in other Java applications too
public class DatabaseService {
public void connect() {
// Same ConfNG API, no TestNG features (since TestNG not present)
ConfNG.loadProperties("app.properties");
String dbUrl = ConfNG.get(AppConfig.DATABASE_URL);
// Your application logic...
}
}