or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdconditional-execution.mdcore-testing.mddynamic-tests.mdextensions.mdindex.mdparallel-execution.mdparameterized-tests.md

parallel-execution.mddocs/

0

# Parallel Execution and Resource Management

1

2

Configuration for parallel test execution, resource locking, and temporary file management. JUnit Jupiter provides fine-grained control over test concurrency and resource access.

3

4

## Imports

5

6

```java

7

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

8

import org.junit.jupiter.api.io.TempDir;

9

import java.nio.file.Path;

10

import static org.junit.jupiter.api.Assertions.*;

11

```

12

13

## Capabilities

14

15

### Parallel Execution Configuration

16

17

Control concurrent execution of tests and test classes.

18

19

```java { .api }

20

/**

21

* Configure parallel execution mode for tests

22

*/

23

@Target({ElementType.TYPE, ElementType.METHOD})

24

@Retention(RetentionPolicy.RUNTIME)

25

@interface Execution {

26

/**

27

* Execution mode for this test or test class

28

*/

29

ExecutionMode value();

30

}

31

32

/**

33

* Execution mode enumeration

34

*/

35

enum ExecutionMode {

36

/**

37

* Execute in same thread as parent

38

*/

39

SAME_THREAD,

40

41

/**

42

* Execute concurrently with other tests (if parallel execution enabled)

43

*/

44

CONCURRENT

45

}

46

```

47

48

**Usage Examples:**

49

50

```java

51

// Enable concurrent execution for entire test class

52

@Execution(ExecutionMode.CONCURRENT)

53

class ParallelTest {

54

55

@Test

56

void test1() {

57

// Runs concurrently with other tests

58

performIndependentOperation();

59

}

60

61

@Test

62

void test2() {

63

// Runs concurrently with other tests

64

performAnotherIndependentOperation();

65

}

66

67

@Test

68

@Execution(ExecutionMode.SAME_THREAD)

69

void sequentialTest() {

70

// Runs sequentially despite class-level concurrent setting

71

performSequentialOperation();

72

}

73

}

74

75

// Mixed execution modes

76

class MixedExecutionTest {

77

78

@Test

79

@Execution(ExecutionMode.CONCURRENT)

80

void concurrentTest1() {

81

// Runs concurrently

82

}

83

84

@Test

85

@Execution(ExecutionMode.CONCURRENT)

86

void concurrentTest2() {

87

// Runs concurrently

88

}

89

90

@Test

91

void defaultTest() {

92

// Uses default execution mode

93

}

94

}

95

```

96

97

### Test Isolation

98

99

Force sequential execution for tests that require isolation.

100

101

```java { .api }

102

/**

103

* Force sequential execution in separate classloader

104

*/

105

@Target({ElementType.TYPE, ElementType.METHOD})

106

@Retention(RetentionPolicy.RUNTIME)

107

@interface Isolated {

108

}

109

```

110

111

**Usage Example:**

112

113

```java

114

@Isolated

115

class IsolatedTest {

116

117

@Test

118

void testThatModifiesGlobalState() {

119

System.setProperty("test.mode", "isolated");

120

// Test runs in isolation

121

}

122

123

@Test

124

void anotherIsolatedTest() {

125

// Also runs in isolation

126

}

127

}

128

129

class RegularTest {

130

131

@Test

132

@Isolated

133

void isolatedMethod() {

134

// Only this method runs in isolation

135

}

136

137

@Test

138

void regularMethod() {

139

// Regular execution

140

}

141

}

142

```

143

144

### Resource Locking

145

146

Coordinate access to shared resources across concurrent tests.

147

148

```java { .api }

149

/**

150

* Lock access to a shared resource

151

*/

152

@Target({ElementType.TYPE, ElementType.METHOD})

153

@Retention(RetentionPolicy.RUNTIME)

154

@Repeatable(ResourceLocks.class)

155

@interface ResourceLock {

156

/**

157

* Resource identifier

158

*/

159

String value();

160

161

/**

162

* Access mode for the resource

163

*/

164

ResourceAccessMode mode() default ResourceAccessMode.READ_WRITE;

165

166

/**

167

* Target level for the lock

168

*/

169

ResourceLockTarget target() default ResourceLockTarget.METHOD;

170

}

171

172

/**

173

* Container for multiple resource locks

174

*/

175

@Target({ElementType.TYPE, ElementType.METHOD})

176

@Retention(RetentionPolicy.RUNTIME)

177

@interface ResourceLocks {

178

ResourceLock[] value();

179

}

180

181

/**

182

* Resource access mode

183

*/

184

enum ResourceAccessMode {

185

/**

186

* Exclusive read-write access

187

*/

188

READ_WRITE,

189

190

/**

191

* Shared read-only access

192

*/

193

READ

194

}

195

196

/**

197

* Resource lock target level

198

*/

199

enum ResourceLockTarget {

200

/**

201

* Lock applies to individual method

202

*/

203

METHOD,

204

205

/**

206

* Lock applies to entire class

207

*/

208

CLASS

209

}

210

```

211

212

**Usage Examples:**

213

214

```java

215

class ResourceLockTest {

216

217

@Test

218

@ResourceLock("database")

219

void testDatabaseWrite() {

220

// Exclusive access to database resource

221

database.insert("test data");

222

}

223

224

@Test

225

@ResourceLock(value = "database", mode = ResourceAccessMode.READ)

226

void testDatabaseRead1() {

227

// Shared read access - can run concurrently with other read tests

228

String data = database.select("test data");

229

assertNotNull(data);

230

}

231

232

@Test

233

@ResourceLock(value = "database", mode = ResourceAccessMode.READ)

234

void testDatabaseRead2() {

235

// Shared read access - can run concurrently with testDatabaseRead1

236

int count = database.count();

237

assertTrue(count >= 0);

238

}

239

240

@Test

241

@ResourceLocks({

242

@ResourceLock("database"),

243

@ResourceLock("filesystem")

244

})

245

void testMultipleResources() {

246

// Requires exclusive access to both database and filesystem

247

database.backup("/tmp/backup");

248

}

249

}

250

251

@ResourceLock(value = "system-properties", target = ResourceLockTarget.CLASS)

252

class SystemPropertiesTest {

253

254

@Test

255

void testSystemProperty1() {

256

System.setProperty("test.prop", "value1");

257

// Entire class has exclusive access to system properties

258

}

259

260

@Test

261

void testSystemProperty2() {

262

System.setProperty("test.prop", "value2");

263

// Sequential execution guaranteed

264

}

265

}

266

```

267

268

### Standard Resources

269

270

Pre-defined resource identifiers for common shared resources.

271

272

```java { .api }

273

/**

274

* Standard resource constants

275

*/

276

class Resources {

277

/**

278

* Global resource lock

279

*/

280

public static final String GLOBAL = "GLOBAL";

281

282

/**

283

* Java system properties

284

*/

285

public static final String SYSTEM_PROPERTIES = "SYSTEM_PROPERTIES";

286

287

/**

288

* Java system environment

289

*/

290

public static final String SYSTEM_ENVIRONMENT = "SYSTEM_ENVIRONMENT";

291

292

/**

293

* Standard input/output streams

294

*/

295

public static final String SYSTEM_OUT = "SYSTEM_OUT";

296

public static final String SYSTEM_ERR = "SYSTEM_ERR";

297

public static final String SYSTEM_IN = "SYSTEM_IN";

298

299

/**

300

* Java locale settings

301

*/

302

public static final String LOCALE = "LOCALE";

303

304

/**

305

* Java time zone settings

306

*/

307

public static final String TIME_ZONE = "TIME_ZONE";

308

}

309

```

310

311

**Usage Examples:**

312

313

```java

314

class StandardResourcesTest {

315

316

@Test

317

@ResourceLock(Resources.SYSTEM_PROPERTIES)

318

void testWithSystemProperties() {

319

String original = System.getProperty("user.dir");

320

System.setProperty("user.dir", "/tmp");

321

322

// Test with modified system property

323

assertEquals("/tmp", System.getProperty("user.dir"));

324

325

// Restore

326

System.setProperty("user.dir", original);

327

}

328

329

@Test

330

@ResourceLock(Resources.SYSTEM_OUT)

331

void testWithSystemOut() {

332

PrintStream originalOut = System.out;

333

ByteArrayOutputStream capturedOut = new ByteArrayOutputStream();

334

System.setOut(new PrintStream(capturedOut));

335

336

System.out.println("Test output");

337

assertEquals("Test output\n", capturedOut.toString());

338

339

System.setOut(originalOut);

340

}

341

342

@Test

343

@ResourceLock(Resources.LOCALE)

344

void testWithLocale() {

345

Locale original = Locale.getDefault();

346

Locale.setDefault(Locale.FRENCH);

347

348

// Test with French locale

349

assertEquals(Locale.FRENCH, Locale.getDefault());

350

351

Locale.setDefault(original);

352

}

353

}

354

```

355

356

### Custom Resource Locks Provider

357

358

Programmatically provide resource locks based on test context.

359

360

```java { .api }

361

/**

362

* Provides resource locks programmatically

363

*/

364

interface ResourceLocksProvider {

365

/**

366

* Provide resource locks for the given extension context

367

*/

368

Set<Lock> provideForClass(ExtensionContext context);

369

Set<Lock> provideForNestedClass(ExtensionContext context);

370

Set<Lock> provideForMethod(ExtensionContext context);

371

372

/**

373

* Resource lock representation

374

*/

375

interface Lock {

376

String getKey();

377

ResourceAccessMode getAccessMode();

378

}

379

}

380

```

381

382

### Temporary Directory Support

383

384

Automatic temporary directory creation and cleanup for tests.

385

386

```java { .api }

387

/**

388

* Inject temporary directory into test method or field

389

*/

390

@Target({ElementType.FIELD, ElementType.PARAMETER})

391

@Retention(RetentionPolicy.RUNTIME)

392

@interface TempDir {

393

/**

394

* Cleanup mode for temporary directory

395

*/

396

CleanupMode cleanup() default CleanupMode.DEFAULT;

397

398

/**

399

* Factory for creating temporary directories

400

*/

401

Class<? extends TempDirFactory> factory() default TempDirFactory.Standard.class;

402

}

403

404

/**

405

* Cleanup mode for temporary directories

406

*/

407

enum CleanupMode {

408

/**

409

* Use default cleanup behavior

410

*/

411

DEFAULT,

412

413

/**

414

* Never clean up temporary directories

415

*/

416

NEVER,

417

418

/**

419

* Always clean up temporary directories

420

*/

421

ALWAYS,

422

423

/**

424

* Clean up on success, keep on failure

425

*/

426

ON_SUCCESS

427

}

428

429

/**

430

* Factory for creating temporary directories

431

*/

432

interface TempDirFactory {

433

/**

434

* Create temporary directory

435

*/

436

Path createTempDirectory(AnnotatedElement annotatedElement, ExtensionContext extensionContext) throws IOException;

437

438

/**

439

* Standard temporary directory factory

440

*/

441

class Standard implements TempDirFactory {

442

@Override

443

public Path createTempDirectory(AnnotatedElement annotatedElement, ExtensionContext extensionContext) throws IOException {

444

return Files.createTempDirectory("junit");

445

}

446

}

447

}

448

```

449

450

**Usage Examples:**

451

452

```java

453

class TempDirTest {

454

455

@TempDir

456

Path sharedTempDir;

457

458

@Test

459

void testWithSharedTempDir() throws IOException {

460

Path file = sharedTempDir.resolve("test.txt");

461

Files.write(file, "test content".getBytes());

462

463

assertTrue(Files.exists(file));

464

assertEquals("test content", Files.readString(file));

465

}

466

467

@Test

468

void testWithMethodTempDir(@TempDir Path tempDir) throws IOException {

469

// Each test method gets its own temp directory

470

assertNotEquals(sharedTempDir, tempDir);

471

472

Path file = tempDir.resolve("method-test.txt");

473

Files.createFile(file);

474

assertTrue(Files.exists(file));

475

}

476

477

@Test

478

void testWithCustomCleanup(@TempDir(cleanup = CleanupMode.NEVER) Path persistentDir) throws IOException {

479

// This directory won't be cleaned up automatically

480

Path file = persistentDir.resolve("persistent.txt");

481

Files.write(file, "This file will persist".getBytes());

482

483

System.out.println("Persistent dir: " + persistentDir);

484

}

485

486

@Test

487

void testWithCustomFactory(@TempDir(factory = CustomTempDirFactory.class) Path customDir) {

488

// Directory created by custom factory

489

assertTrue(customDir.toString().contains("custom"));

490

}

491

}

492

493

class CustomTempDirFactory implements TempDirFactory {

494

@Override

495

public Path createTempDirectory(AnnotatedElement annotatedElement, ExtensionContext extensionContext) throws IOException {

496

return Files.createTempDirectory("custom-junit-" + extensionContext.getDisplayName());

497

}

498

}

499

```

500

501

### Configuration Properties

502

503

Configure parallel execution behavior through system properties or configuration files.

504

505

**Key Configuration Properties:**

506

507

```properties

508

# Enable parallel execution

509

junit.jupiter.execution.parallel.enabled=true

510

511

# Default execution mode

512

junit.jupiter.execution.parallel.mode.default=concurrent

513

514

# Class-level execution mode

515

junit.jupiter.execution.parallel.mode.classes.default=concurrent

516

517

# Parallelism strategy

518

junit.jupiter.execution.parallel.config.strategy=dynamic

519

# or fixed with custom thread count

520

junit.jupiter.execution.parallel.config.strategy=fixed

521

junit.jupiter.execution.parallel.config.fixed.parallelism=4

522

523

# Dynamic parallelism factor

524

junit.jupiter.execution.parallel.config.dynamic.factor=2.0

525

```

526

527

**Usage in junit-platform.properties:**

528

529

```properties

530

junit.jupiter.execution.parallel.enabled=true

531

junit.jupiter.execution.parallel.mode.default=concurrent

532

junit.jupiter.execution.parallel.mode.classes.default=same_thread

533

junit.jupiter.execution.parallel.config.strategy=dynamic

534

junit.jupiter.execution.parallel.config.dynamic.factor=1.5

535

```