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
```