0
# Configuration Management
1
2
Configuration parameter management with support for inline parameters, properties files, and inheritance control from parent discovery requests.
3
4
## Capabilities
5
6
### @ConfigurationParameter Annotation
7
8
Specifies individual configuration key-value pairs to be added to the discovery request.
9
10
```java { .api }
11
/**
12
* Specifies a configuration key and value pair to be added to the discovery request.
13
* Repeatable annotation for multiple configuration parameters.
14
*/
15
@Retention(RetentionPolicy.RUNTIME)
16
@Target(ElementType.TYPE)
17
@Inherited
18
@Documented
19
@API(status = STABLE, since = "1.10")
20
@Repeatable(ConfigurationParameters.class)
21
public @interface ConfigurationParameter {
22
/**
23
* The configuration parameter key; never null or blank.
24
* @return configuration parameter key
25
*/
26
String key();
27
28
/**
29
* The value to add to the discovery request for the specified key.
30
* @return configuration parameter value
31
*/
32
String value();
33
}
34
35
/**
36
* Container for multiple @ConfigurationParameter declarations.
37
*/
38
@Retention(RetentionPolicy.RUNTIME)
39
@Target(ElementType.TYPE)
40
@Inherited
41
@Documented
42
@API(status = STABLE, since = "1.10")
43
public @interface ConfigurationParameters {
44
/**
45
* Array of @ConfigurationParameter declarations.
46
* @return array of configuration parameters
47
*/
48
ConfigurationParameter[] value();
49
}
50
```
51
52
**Usage Examples:**
53
54
```java
55
// Single configuration parameter
56
@Suite
57
@SelectPackages("com.example")
58
@ConfigurationParameter(
59
key = "junit.jupiter.displayname.generator.default",
60
value = "org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores"
61
)
62
public class CustomDisplayNameTestSuite {
63
}
64
65
// Multiple configuration parameters
66
@Suite
67
@SelectPackages("com.example")
68
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "true")
69
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.mode.default", value = "concurrent")
70
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.config.strategy", value = "dynamic")
71
public class ParallelExecutionTestSuite {
72
}
73
74
// Database configuration
75
@Suite
76
@SelectTags("database")
77
@ConfigurationParameter(key = "database.url", value = "jdbc:h2:mem:testdb")
78
@ConfigurationParameter(key = "database.username", value = "sa")
79
@ConfigurationParameter(key = "database.password", value = "")
80
@ConfigurationParameter(key = "database.pool.size", value = "5")
81
public class DatabaseTestSuite {
82
}
83
```
84
85
### @ConfigurationParametersResource Annotation
86
87
Specifies configuration files in Java properties format to be loaded from the classpath.
88
89
```java { .api }
90
/**
91
* Specifies a configuration file in Java's properties format on the classpath
92
* to be added to the discovery request.
93
* Repeatable annotation for multiple properties files.
94
*/
95
@Retention(RetentionPolicy.RUNTIME)
96
@Target(ElementType.TYPE)
97
@Inherited
98
@Documented
99
@API(status = EXPERIMENTAL, since = "1.11")
100
@Repeatable(ConfigurationParametersResources.class)
101
public @interface ConfigurationParametersResource {
102
/**
103
* The classpath location for the desired properties file; never null or blank.
104
* @return classpath resource path
105
*/
106
String value();
107
}
108
109
/**
110
* Container for multiple @ConfigurationParametersResource declarations.
111
*/
112
@Retention(RetentionPolicy.RUNTIME)
113
@Target(ElementType.TYPE)
114
@Inherited
115
@Documented
116
@API(status = EXPERIMENTAL, since = "1.11")
117
public @interface ConfigurationParametersResources {
118
/**
119
* Array of @ConfigurationParametersResource declarations.
120
* @return array of configuration parameter resources
121
*/
122
ConfigurationParametersResource[] value();
123
}
124
```
125
126
**Usage Examples:**
127
128
```java
129
// Single properties file
130
@Suite
131
@SelectPackages("com.example.integration")
132
@ConfigurationParametersResource("/test-config/integration.properties")
133
public class IntegrationTestSuite {
134
}
135
136
// Multiple properties files
137
@Suite
138
@SelectPackages("com.example")
139
@ConfigurationParametersResource("/test-config/database.properties")
140
@ConfigurationParametersResource("/test-config/security.properties")
141
@ConfigurationParametersResource("/test-config/logging.properties")
142
public class MultiConfigTestSuite {
143
}
144
145
// Environment-specific configuration
146
@Suite
147
@SelectTags("performance")
148
@ConfigurationParametersResource("/test-config/performance-${test.env:local}.properties")
149
public class PerformanceTestSuite {
150
}
151
```
152
153
**Example properties file (`/test-config/integration.properties`):**
154
```properties
155
# Database configuration
156
database.url=jdbc:h2:mem:integration_test
157
database.username=test_user
158
database.password=test_pass
159
160
# JUnit Jupiter configuration
161
junit.jupiter.execution.timeout.default=30s
162
junit.jupiter.execution.parallel.enabled=true
163
junit.jupiter.execution.parallel.mode.default=concurrent
164
165
# Custom application configuration
166
app.feature.flags.enabled=true
167
app.mock.external.services=true
168
app.log.level=DEBUG
169
```
170
171
### @DisableParentConfigurationParameters Annotation
172
173
Disables inheritance of configuration parameters from parent discovery requests.
174
175
```java { .api }
176
/**
177
* Disable parent configuration parameters.
178
*
179
* By default, a suite discovers tests using both explicit configuration parameters
180
* and configuration parameters from the discovery request that discovered the suite.
181
* This annotation disables the latter source so that only explicit configuration
182
* parameters are taken into account.
183
*/
184
@Retention(RetentionPolicy.RUNTIME)
185
@Target(ElementType.TYPE)
186
@Inherited
187
@Documented
188
@API(status = STABLE, since = "1.10")
189
public @interface DisableParentConfigurationParameters {
190
}
191
```
192
193
**Usage Examples:**
194
195
```java
196
// Isolated test suite with only explicit configuration
197
@Suite
198
@SelectPackages("com.example.isolated")
199
@DisableParentConfigurationParameters
200
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "false")
201
@ConfigurationParameter(key = "app.test.mode", value = "isolated")
202
public class IsolatedTestSuite {
203
}
204
205
// Suite that ignores global CI configuration
206
@Suite
207
@SelectTags("local-only")
208
@DisableParentConfigurationParameters
209
@ConfigurationParametersResource("/test-config/local-development.properties")
210
public class LocalDevelopmentTestSuite {
211
}
212
```
213
214
## Configuration Best Practices
215
216
### Configuration Hierarchy
217
218
Configuration parameters are applied in the following order (highest to lowest precedence):
219
220
1. **Explicit @ConfigurationParameter annotations** (highest precedence)
221
2. **@ConfigurationParametersResource files** (in declaration order)
222
3. **Parent discovery request parameters** (unless disabled)
223
4. **Default JUnit configuration** (lowest precedence)
224
225
```java
226
@Suite
227
@SelectPackages("com.example")
228
// These have highest precedence
229
@ConfigurationParameter(key = "parallel.enabled", value = "true")
230
@ConfigurationParameter(key = "timeout.default", value = "60s")
231
// These have medium precedence
232
@ConfigurationParametersResource("/config/base.properties")
233
@ConfigurationParametersResource("/config/override.properties")
234
// Parent parameters have lowest precedence (unless disabled)
235
public class ConfigurationHierarchyTestSuite {
236
}
237
```
238
239
### Common Configuration Patterns
240
241
**Parallel execution configuration:**
242
```java
243
@Suite
244
@SelectPackages("com.example.unit")
245
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "true")
246
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.mode.default", value = "concurrent")
247
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.config.strategy", value = "dynamic")
248
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.config.dynamic.factor", value = "0.8")
249
public class ParallelTestSuite {
250
}
251
```
252
253
**Timeout configuration:**
254
```java
255
@Suite
256
@SelectTags("integration")
257
@ConfigurationParameter(key = "junit.jupiter.execution.timeout.default", value = "5m")
258
@ConfigurationParameter(key = "junit.jupiter.execution.timeout.testable.method.default", value = "2m")
259
@ConfigurationParameter(key = "junit.jupiter.execution.timeout.testtemplate.method.default", value = "3m")
260
public class TimeoutConfiguredTestSuite {
261
}
262
```
263
264
**Display name configuration:**
265
```java
266
@Suite
267
@SelectPackages("com.example")
268
@ConfigurationParameter(
269
key = "junit.jupiter.displayname.generator.default",
270
value = "org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores"
271
)
272
public class ReadableDisplayNameTestSuite {
273
}
274
```
275
276
### Environment-Specific Configuration
277
278
**Development environment:**
279
```java
280
@Suite
281
@SelectPackages("com.example")
282
@ConfigurationParametersResource("/config/development.properties")
283
@ConfigurationParameter(key = "app.debug.enabled", value = "true")
284
@ConfigurationParameter(key = "app.mock.external", value = "true")
285
public class DevelopmentTestSuite {
286
}
287
```
288
289
**CI/CD environment:**
290
```java
291
@Suite
292
@SelectPackages("com.example")
293
@DisableParentConfigurationParameters // Ignore local dev config
294
@ConfigurationParametersResource("/config/ci.properties")
295
@ConfigurationParameter(key = "junit.jupiter.execution.parallel.enabled", value = "true")
296
@ConfigurationParameter(key = "app.strict.validation", value = "true")
297
public class CiTestSuite {
298
}
299
```
300
301
**Production-like environment:**
302
```java
303
@Suite
304
@SelectTags("production-ready")
305
@ConfigurationParametersResource("/config/production-test.properties")
306
@ConfigurationParameter(key = "app.mock.external", value = "false")
307
@ConfigurationParameter(key = "app.security.strict", value = "true")
308
@ConfigurationParameter(key = "database.pool.size", value = "20")
309
public class ProductionTestSuite {
310
}
311
```
312
313
### Configuration File Organization
314
315
**Recommended file structure:**
316
```
317
src/test/resources/
318
├── test-config/
319
│ ├── base.properties # Common configuration
320
│ ├── development.properties # Development overrides
321
│ ├── ci.properties # CI/CD specific
322
│ ├── integration.properties # Integration test config
323
│ ├── performance.properties # Performance test config
324
│ └── security.properties # Security test config
325
```
326
327
**Base configuration file (`base.properties`):**
328
```properties
329
# Common JUnit configuration
330
junit.jupiter.execution.timeout.default=30s
331
junit.jupiter.displayname.generator.default=org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores
332
333
# Common application configuration
334
app.log.level=INFO
335
app.test.data.cleanup=true
336
```
337
338
**Integration configuration file (`integration.properties`):**
339
```properties
340
# Include base configuration (manually or via tooling)
341
342
# Database configuration
343
database.url=jdbc:h2:mem:integration_test
344
database.username=integration_user
345
database.pool.size=10
346
347
# External services
348
app.mock.external.services=true
349
app.external.api.timeout=10s
350
351
# Parallel execution for integration tests
352
junit.jupiter.execution.parallel.enabled=true
353
junit.jupiter.execution.parallel.mode.default=same_thread
354
junit.jupiter.execution.parallel.mode.classes.default=concurrent
355
```
356
357
### Dynamic Configuration
358
359
**System property substitution:**
360
```java
361
@Suite
362
@SelectPackages("com.example")
363
@ConfigurationParameter(key = "database.url", value = "${test.db.url:jdbc:h2:mem:testdb}")
364
@ConfigurationParameter(key = "app.profile", value = "${test.profile:test}")
365
public class DynamicConfigTestSuite {
366
}
367
```
368
369
**Conditional configuration:**
370
```java
371
// Different suites for different environments
372
@Suite
373
@SelectPackages("com.example")
374
@ConfigurationParametersResource("/config/${test.env:local}.properties")
375
public class EnvironmentAwareTestSuite {
376
}
377
```
378
379
### Configuration Validation
380
381
**Validating configuration in suite setup:**
382
```java
383
@Suite
384
@SelectPackages("com.example.database")
385
@ConfigurationParametersResource("/config/database.properties")
386
public class DatabaseTestSuite {
387
388
@BeforeSuite
389
static void validateConfiguration() {
390
String dbUrl = System.getProperty("database.url");
391
if (dbUrl == null || dbUrl.trim().isEmpty()) {
392
throw new IllegalStateException("Database URL must be configured");
393
}
394
395
String poolSize = System.getProperty("database.pool.size", "5");
396
try {
397
int size = Integer.parseInt(poolSize);
398
if (size < 1 || size > 50) {
399
throw new IllegalStateException("Database pool size must be between 1 and 50");
400
}
401
} catch (NumberFormatException e) {
402
throw new IllegalStateException("Invalid database pool size: " + poolSize);
403
}
404
}
405
}