or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

conditional-execution.mdcore-testing.mdextension-framework.mdindex.mdparallel-io.md

conditional-execution.mddocs/

0

# Conditional Test Execution

1

2

Runtime environment-based test control for platform-specific, JRE-specific, and custom conditional testing scenarios. These annotations allow tests to be enabled or disabled based on operating system, Java version, system properties, environment variables, or custom conditions.

3

4

## Capabilities

5

6

### Operating System Conditions

7

8

Enable or disable tests based on the current operating system and architecture.

9

10

```java { .api }

11

/**

12

* Enable test only on specified operating systems

13

*/

14

@EnabledOnOs(OS value)

15

@EnabledOnOs(OS[] value)

16

@EnabledOnOs(value = OS.LINUX, architectures = "aarch64")

17

@EnabledOnOs(value = {OS.LINUX, OS.MAC}, disabledReason = "Not supported on Windows")

18

19

/**

20

* Disable test on specified operating systems

21

*/

22

@DisabledOnOs(OS value)

23

@DisabledOnOs(OS[] value)

24

@DisabledOnOs(value = OS.WINDOWS, architectures = {"x86_64", "amd64"})

25

26

/**

27

* Operating system enumeration

28

*/

29

enum OS {

30

AIX, FREEBSD, LINUX, MAC, OPENBSD, SOLARIS, WINDOWS, OTHER;

31

32

/**

33

* Get the current operating system

34

*/

35

static OS current();

36

37

/**

38

* Check if this OS matches the current system

39

*/

40

boolean isCurrentOs();

41

}

42

```

43

44

**Usage Examples:**

45

46

```java

47

import org.junit.jupiter.api.condition.*;

48

49

class PlatformSpecificTest {

50

51

@Test

52

@EnabledOnOs(OS.LINUX)

53

void linuxOnlyTest() {

54

// This test only runs on Linux

55

assertTrue(System.getProperty("os.name").toLowerCase().contains("linux"));

56

}

57

58

@Test

59

@DisabledOnOs({OS.WINDOWS, OS.MAC})

60

void notOnWindowsOrMac() {

61

// Runs on all systems except Windows and Mac

62

ProcessBuilder pb = new ProcessBuilder("ps", "-ef");

63

assertDoesNotThrow(() -> pb.start());

64

}

65

66

@Test

67

@EnabledOnOs(value = OS.LINUX, architectures = "aarch64")

68

void linuxArm64Only() {

69

// Only runs on ARM64 Linux systems

70

assertEquals("aarch64", System.getProperty("os.arch"));

71

}

72

73

@Test

74

@DisabledOnOs(value = OS.WINDOWS, disabledReason = "File permissions work differently on Windows")

75

void unixFilePermissions() {

76

// Test Unix-specific file permission behavior

77

Path file = Files.createFile(tempDir.resolve("test.txt"));

78

Files.setPosixFilePermissions(file, PosixFilePermissions.fromString("rwxr--r--"));

79

}

80

}

81

```

82

83

### Java Runtime Environment Conditions

84

85

Enable or disable tests based on JRE version.

86

87

```java { .api }

88

/**

89

* Enable test only on specified JRE versions

90

*/

91

@EnabledOnJre(JRE value)

92

@EnabledOnJre(JRE[] value)

93

94

/**

95

* Disable test on specified JRE versions

96

*/

97

@DisabledOnJre(JRE value)

98

@DisabledOnJre(JRE[] value)

99

100

/**

101

* Enable test for a range of JRE versions

102

*/

103

@EnabledForJreRange(JRE min = JRE.JAVA_8, JRE max = JRE.JAVA_17)

104

105

/**

106

* Disable test for a range of JRE versions

107

*/

108

@DisabledForJreRange(JRE min = JRE.JAVA_8, JRE max = JRE.JAVA_11)

109

110

/**

111

* Java Runtime Environment version enumeration

112

*/

113

enum JRE {

114

JAVA_8, JAVA_9, JAVA_10, JAVA_11, JAVA_12, JAVA_13, JAVA_14,

115

JAVA_15, JAVA_16, JAVA_17, JAVA_18, JAVA_19, JAVA_20, JAVA_21, OTHER;

116

117

/**

118

* Get the current JRE version

119

*/

120

static JRE current();

121

122

/**

123

* Check if this JRE version matches the current runtime

124

*/

125

boolean isCurrentVersion();

126

}

127

```

128

129

**Usage Examples:**

130

131

```java

132

class JreSpecificTest {

133

134

@Test

135

@EnabledOnJre(JRE.JAVA_11)

136

void java11OnlyFeature() {

137

// Test features specific to Java 11

138

String result = "hello world".repeat(3);

139

assertEquals("hello worldhello worldhello world", result);

140

}

141

142

@Test

143

@DisabledOnJre({JRE.JAVA_8, JRE.JAVA_9})

144

void modernJavaFeatures() {

145

// Uses features not available in Java 8/9

146

var list = List.of("item1", "item2", "item3");

147

assertTrue(list.size() > 0);

148

}

149

150

@Test

151

@EnabledForJreRange(min = JRE.JAVA_11, max = JRE.JAVA_17)

152

void supportedJavaVersions() {

153

// Test runs on Java 11 through 17

154

assertDoesNotThrow(() -> {

155

// Use features available in this range

156

String text = """

157

Multi-line

158

string literal

159

""";

160

assertFalse(text.isEmpty());

161

});

162

}

163

164

@Test

165

@DisabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_10, disabledReason = "Module system required")

166

void moduleSystemFeatures() {

167

// Test module system features not available before Java 11

168

Module module = getClass().getModule();

169

assertNotNull(module);

170

}

171

}

172

```

173

174

### System Property Conditions

175

176

Enable or disable tests based on system properties.

177

178

```java { .api }

179

/**

180

* Enable test if system property matches condition

181

*/

182

@EnabledIfSystemProperty(named = "property.name", matches = "regex")

183

184

/**

185

* Disable test if system property matches condition

186

*/

187

@DisabledIfSystemProperty(named = "property.name", matches = "regex")

188

189

/**

190

* Multiple system property conditions (all must be true)

191

*/

192

@EnabledIfSystemProperties({

193

@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*"),

194

@EnabledIfSystemProperty(named = "java.vendor", matches = ".*OpenJDK.*")

195

})

196

197

@DisabledIfSystemProperties({

198

@DisabledIfSystemProperty(named = "env.type", matches = "production"),

199

@DisabledIfSystemProperty(named = "skip.integration", matches = "true")

200

})

201

```

202

203

**Usage Examples:**

204

205

```java

206

class SystemPropertyTest {

207

208

@Test

209

@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")

210

void on64BitArchitecture() {

211

// Only runs on 64-bit architectures

212

String arch = System.getProperty("os.arch");

213

assertTrue(arch.contains("64"));

214

}

215

216

@Test

217

@DisabledIfSystemProperty(named = "headless", matches = "true")

218

void guiTest() {

219

// Skipped in headless environments

220

assertFalse(GraphicsEnvironment.isHeadless());

221

// GUI testing code here

222

}

223

224

@Test

225

@EnabledIfSystemProperties({

226

@EnabledIfSystemProperty(named = "test.environment", matches = "integration"),

227

@EnabledIfSystemProperty(named = "database.url", matches = ".*localhost.*")

228

})

229

void integrationTestWithLocalDatabase() {

230

// Only runs if both conditions are met

231

assertEquals("integration", System.getProperty("test.environment"));

232

assertTrue(System.getProperty("database.url").contains("localhost"));

233

}

234

235

@Test

236

@DisabledIfSystemProperty(named = "skip.slow.tests", matches = "true", disabledReason = "Slow tests disabled")

237

void slowIntegrationTest() {

238

// Skip when -Dskip.slow.tests=true is set

239

Thread.sleep(5000); // Simulate slow test

240

}

241

}

242

```

243

244

### Environment Variable Conditions

245

246

Enable or disable tests based on environment variables.

247

248

```java { .api }

249

/**

250

* Enable test if environment variable matches condition

251

*/

252

@EnabledIfEnvironmentVariable(named = "ENV_VAR", matches = "regex")

253

254

/**

255

* Disable test if environment variable matches condition

256

*/

257

@DisabledIfEnvironmentVariable(named = "ENV_VAR", matches = "regex")

258

259

/**

260

* Multiple environment variable conditions (all must be true)

261

*/

262

@EnabledIfEnvironmentVariables({

263

@EnabledIfEnvironmentVariable(named = "CI", matches = "true"),

264

@EnabledIfEnvironmentVariable(named = "BUILD_ENV", matches = "staging|production")

265

})

266

267

@DisabledIfEnvironmentVariables({

268

@DisabledIfEnvironmentVariable(named = "SKIP_TESTS", matches = ".*integration.*"),

269

@DisabledIfEnvironmentVariable(named = "LIGHTWEIGHT_BUILD", matches = "true")

270

})

271

```

272

273

**Usage Examples:**

274

275

```java

276

class EnvironmentVariableTest {

277

278

@Test

279

@EnabledIfEnvironmentVariable(named = "CI", matches = "true")

280

void continuousIntegrationTest() {

281

// Only runs in CI environments

282

assertEquals("true", System.getenv("CI"));

283

// CI-specific test logic

284

}

285

286

@Test

287

@DisabledIfEnvironmentVariable(named = "SKIP_DOCKER_TESTS", matches = "true")

288

void dockerContainerTest() {

289

// Skipped when SKIP_DOCKER_TESTS=true

290

// Docker-based integration test

291

DockerClient client = DockerClient.getInstance();

292

assertNotNull(client);

293

}

294

295

@Test

296

@EnabledIfEnvironmentVariables({

297

@EnabledIfEnvironmentVariable(named = "AWS_REGION", matches = "us-.*"),

298

@EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".+")

299

})

300

void awsIntegrationTest() {

301

// Only runs with proper AWS configuration in US regions

302

String region = System.getenv("AWS_REGION");

303

assertTrue(region.startsWith("us-"));

304

assertNotNull(System.getenv("AWS_ACCESS_KEY_ID"));

305

}

306

307

@Test

308

@DisabledIfEnvironmentVariable(named = "BUILD_ENV", matches = "production", disabledReason = "Not safe in production")

309

void destructiveTest() {

310

// Never runs in production environment

311

// Potentially destructive test operations

312

}

313

}

314

```

315

316

### Custom Method Conditions

317

318

Enable or disable tests based on custom condition methods.

319

320

```java { .api }

321

/**

322

* Enable test if method returns true

323

*/

324

@EnabledIf("methodName")

325

@EnabledIf(value = "methodName", disabledReason = "Custom condition not met")

326

327

/**

328

* Disable test if method returns true

329

*/

330

@DisabledIf("methodName")

331

@DisabledIf(value = "methodName", disabledReason = "Custom condition prevents execution")

332

```

333

334

**Usage Examples:**

335

336

```java

337

class CustomConditionTest {

338

339

@Test

340

@EnabledIf("isDatabaseAvailable")

341

void databaseTest() {

342

// Only runs if database is available

343

assertTrue(isDatabaseAvailable());

344

// Database test logic

345

}

346

347

@Test

348

@DisabledIf("isProductionEnvironment")

349

void developmentOnlyTest() {

350

// Skipped in production

351

assertFalse(isProductionEnvironment());

352

// Development/testing specific code

353

}

354

355

@Test

356

@EnabledIf(value = "hasRequiredFeature", disabledReason = "Required feature not available")

357

void featureSpecificTest() {

358

// Only runs if specific feature is available

359

assertTrue(hasRequiredFeature());

360

// Feature-specific test logic

361

}

362

363

// Condition methods must be static and return boolean

364

static boolean isDatabaseAvailable() {

365

try {

366

java.sql.Connection conn = java.sql.DriverManager.getConnection("jdbc:h2:mem:test");

367

conn.close();

368

return true;

369

} catch (java.sql.SQLException e) {

370

return false;

371

}

372

}

373

374

static boolean isProductionEnvironment() {

375

return "production".equals(System.getenv("ENV"));

376

}

377

378

static boolean hasRequiredFeature() {

379

return System.getProperty("features", "").contains("advanced");

380

}

381

}

382

```

383

384

### Native Image Conditions

385

386

Enable or disable tests when running in GraalVM native image.

387

388

```java { .api }

389

/**

390

* Enable test only when running in a native image

391

*/

392

@EnabledInNativeImage

393

394

/**

395

* Disable test when running in a native image

396

*/

397

@DisabledInNativeImage

398

```

399

400

**Usage Examples:**

401

402

```java

403

class NativeImageTest {

404

405

@Test

406

@EnabledInNativeImage

407

void nativeImageOnlyTest() {

408

// Only runs in GraalVM native image

409

// Test native image specific behavior

410

assertTrue(isNativeImage());

411

}

412

413

@Test

414

@DisabledInNativeImage

415

void jvmOnlyTest() {

416

// Skipped in native image, uses reflection heavily

417

Class<?> clazz = SomeClass.class;

418

Method[] methods = clazz.getDeclaredMethods();

419

assertTrue(methods.length > 0);

420

}

421

422

private boolean isNativeImage() {

423

return System.getProperty("org.graalvm.nativeimage.imagecode") != null;

424

}

425

}

426

```

427

428

### Combining Conditions

429

430

Multiple conditional annotations can be combined on the same test method.

431

432

**Usage Examples:**

433

434

```java

435

class CombinedConditionsTest {

436

437

@Test

438

@EnabledOnOs(OS.LINUX)

439

@EnabledForJreRange(min = JRE.JAVA_11)

440

@EnabledIfEnvironmentVariable(named = "CI", matches = "true")

441

void linuxJava11CiTest() {

442

// Only runs on Linux, Java 11+, in CI environment

443

// All conditions must be satisfied

444

}

445

446

@Test

447

@DisabledOnOs(OS.WINDOWS)

448

@DisabledIfSystemProperty(named = "headless", matches = "true")

449

@DisabledIf("isResourceConstrained")

450

void resourceIntensiveTest() {

451

// Skipped if ANY condition is met:

452

// - Running on Windows, OR

453

// - In headless mode, OR

454

// - System is resource constrained

455

}

456

457

static boolean isResourceConstrained() {

458

Runtime runtime = Runtime.getRuntime();

459

return runtime.maxMemory() < 1024 * 1024 * 1024; // Less than 1GB

460

}

461

}

462

```

463

464

## Error Handling

465

466

When conditional annotations are misconfigured or condition methods throw exceptions, JUnit will report the error and typically disable the affected test.

467

468

```java

469

@Test

470

@EnabledIf("nonExistentMethod") // Error: method not found

471

void misconfiguredTest() {

472

// This test will be disabled due to configuration error

473

}

474

475

@Test

476

@EnabledIf("throwingConditionMethod")

477

void testWithThrowingCondition() {

478

// This test will be disabled if condition method throws exception

479

}

480

481

static boolean throwingConditionMethod() {

482

throw new RuntimeException("Condition evaluation failed");

483

}

484

```

485

486

## Types

487

488

### Condition Evaluation Result

489

490

```java { .api }

491

/**

492

* Result of evaluating an execution condition

493

*/

494

class ConditionEvaluationResult {

495

static ConditionEvaluationResult enabled(String reason);

496

static ConditionEvaluationResult disabled(String reason);

497

498

boolean isDisabled();

499

Optional<String> getReason();

500

}

501

```