or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-framework.mdfiltering.mdindex.mdlifecycle.mdselection.md

configuration.mddocs/

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

}