Skip to content

Commit c291139

Browse files
committed
Polish System Properties extension support and documentation
1 parent 2c64850 commit c291139

File tree

10 files changed

+211
-142
lines changed

10 files changed

+211
-142
lines changed

documentation/modules/ROOT/pages/writing-tests/built-in-extensions.adoc

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -296,23 +296,24 @@ respective annotations.
296296
Tests annotated with one of the above annotations will never execute in parallel with
297297
tests annotated with `@DefaultLocale` or `@DefaultTimeZone`.
298298

299-
[[SystemProperties]]
300-
== The System Property Extensions
299+
[[system-properties]]
300+
== The System Properties Extension
301301

302-
The system property extensions provide a set of annotations that work together to clear,
303-
set, and restore system properties.
302+
The system properties extension supports a set of annotations that work together to clear,
303+
set, and restore JVM system properties.
304304

305-
[[SystemProperties-clear-and-set]]
305+
[[system-properties-clear-and-set]]
306306
=== @ClearSystemProperty and @SetSystemProperty
307307

308-
The `{ClearSystemProperty}` and `{SetSystemProperty}` annotations can be used to clear
309-
and set, respectively, the values of system properties for test execution. Both
308+
The `{ClearSystemProperty}` and `{SetSystemProperty}` annotations can be used to clear and
309+
set, respectively, the values of JVM system properties for test execution. Both
310310
annotations work on the test method and class level and are repeatable, combinable, and
311311
inherited from higher-level containers. After the annotated method has been executed, the
312312
properties configured in the annotation will be restored to their original value or the
313313
value of the higher-level container, or will be cleared if they did not previously have a
314-
value. Other system properties that are changed during the test are _not_ restored
315-
(unless <<SystemProperties-restore, explicitly enabled>> via `{RestoreSystemProperties}`).
314+
value. Other system properties that are changed during the test are _not_ restored (unless
315+
restoration is <<system-properties-restore, explicitly enabled>> via
316+
`{RestoreSystemProperties}`).
316317

317318
For example, clearing a system property for test execution can be done as follows.
318319

@@ -354,7 +355,7 @@ With class-level configuration, the specified system properties are cleared or s
354355
and reset after each individual test in the annotated class.
355356
====
356357

357-
[[SystemProperties-restore]]
358+
[[system-properties-restore]]
358359
=== @RestoreSystemProperties
359360

360361
The `{RestoreSystemProperties}` annotation can be used to restore changes to system
@@ -400,7 +401,7 @@ property changes made within the annotated class are completely restored after t
400401
lifecycle, ensuring that changes are not visible to `SomeOtherTestClass`. Note that
401402
`SomeOtherTestClass` uses the `@ReadsSystemProperty` annotation, which ensures that JUnit
402403
does not schedule the class to run during any test known to modify system properties (see
403-
<<SystemProperties-thread-safety>>).
404+
<<system-properties-thread-safety>>).
404405

405406
[source,java,indent=0]
406407
----
@@ -414,7 +415,7 @@ Some other test class, running later:
414415
include::example$java/example/SystemPropertyExtensionDemo.java[tag=systemproperty_class_restore_isolated_class]
415416
----
416417

417-
[[SystemProperties-combined-usage]]
418+
[[system-properties-combined-usage]]
418419
=== Combining @ClearSystemProperty, @SetSystemProperty, and @RestoreSystemProperties
419420

420421
The three system property annotations can be combined, which can be useful when some
@@ -436,7 +437,7 @@ the referenced properties. `@RestoreSystemProperties` is only needed if system p
436437
are modified during a test in some way _other than_ via the `Clear` and `Set` annotations.
437438
====
438439

439-
[[SystemProperties-thread-safety]]
440+
[[system-properties-thread-safety]]
440441
=== Thread Safety
441442

442443
Since system properties are global state, reading and writing them during

junit-jupiter-api/src/main/java/org/junit/jupiter/api/util/ClearSystemProperty.java

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,45 +23,53 @@
2323
import org.junit.jupiter.api.extension.ExtendWith;
2424

2525
/**
26-
* {@code @ClearSystemProperty} is a JUnit Jupiter extension to clear the value
27-
* of a system property for a test execution.
26+
* {@code @ClearSystemProperty} is an annotation that is used to clear the value
27+
* of a JVM system property for test execution.
2828
*
29-
* <p>The key of the system property to be cleared must be specified via {@link #key()}.
30-
* After the annotated element has been executed, the original value or the value of the
31-
* higher-level container is restored.</p>
29+
* <p>The key of the system property must be specified via the {@link #key() key}
30+
* attribute.
3231
*
3332
* <p>{@code @ClearSystemProperty} can be used on the method and on the class level.
34-
* It is repeatable and inherited from higher-level containers. If a class is
35-
* annotated, the configured property will be cleared before every test inside that
36-
* class.</p>
33+
* It is {@linkplain Repeatable repeatable} and {@link Inherited @Inherited} from
34+
* higher-level containers. If a class is annotated, the configured property will
35+
* be cleared before every test inside that class. After a test has completed,
36+
* the original value of the system property will be restored.
3737
*
38-
* <p>During
39-
* <a href="https://docs.junit.org/current/writing-tests/parallel-execution.html">parallel test execution</a>,
40-
* all tests annotated with {@link ClearSystemProperty}, {@link SetSystemProperty}, {@link ReadsSystemProperty}, and {@link WritesSystemProperty}
41-
* are scheduled in a way that guarantees correctness under mutation of shared global state.</p>
38+
* <p>During <a href="https://docs.junit.org/current/writing-tests/parallel-execution.html">
39+
* parallel test execution</a>, all tests annotated with
40+
* {@link SetSystemProperty @SetSystemProperty},
41+
* {@link ClearSystemProperty @ClearSystemProperty},
42+
* {@link ReadsSystemProperty @ReadsSystemProperty}, and
43+
* {@link WritesSystemProperty @WritesSystemProperty} are scheduled in a way that
44+
* guarantees correctness under mutation of shared global state.
4245
*
43-
* <p>For more details and examples, see
44-
* <a href="https://docs.junit.org/current/writing-tests/built-in-extensions.html#SystemProperty">the documentation on <code>@ClearSystemProperty and @SetSystemProperty</code></a>.</p>
46+
* <p>For further details and examples, see the documentation on all JVM system
47+
* property annotations in the
48+
* <a href="https://docs.junit.org/current/writing-tests/built-in-extensions.html#system-properties">
49+
* User Guide</a>.
4550
*
4651
* @since 6.1
52+
* @see SetSystemProperty @SetSystemProperty
53+
* @see RestoreSystemProperties @RestoreSystemProperties
4754
*/
4855
@Retention(RetentionPolicy.RUNTIME)
4956
@Target({ ElementType.METHOD, ElementType.TYPE })
5057
@Inherited
5158
@Repeatable(ClearSystemProperty.ClearSystemProperties.class)
5259
@WritesSystemProperty
53-
@ExtendWith(SystemPropertyExtension.class)
60+
@ExtendWith(SystemPropertiesExtension.class)
5461
@API(status = EXPERIMENTAL, since = "6.1")
5562
@SuppressWarnings("exports")
5663
public @interface ClearSystemProperty {
5764

5865
/**
59-
* The key of the system property to be cleared.
66+
* The key of the system property to clear.
6067
*/
6168
String key();
6269

6370
/**
64-
* Containing annotation of repeatable {@code @ClearSystemProperty}.
71+
* {@code @ClearSystemProperties} is a container for one or more
72+
* {@code ClearSystemProperty} declarations.
6573
*/
6674
@Retention(RetentionPolicy.RUNTIME)
6775
@Target({ ElementType.METHOD, ElementType.TYPE })
@@ -70,6 +78,10 @@
7078
@API(status = EXPERIMENTAL, since = "6.1")
7179
@interface ClearSystemProperties {
7280

81+
/**
82+
* An array of one or more {@link ClearSystemProperty @ClearSystemProperty}
83+
* declarations.
84+
*/
7385
ClearSystemProperty[] value();
7486

7587
}

junit-jupiter-api/src/main/java/org/junit/jupiter/api/util/JupiterPropertyUtils.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,12 @@ private static void throwIfHasObservableDefaults(ExtensionContext context, Prope
3838
.filter(propertyName -> !keySet.contains(propertyName)) //
3939
.toList();
4040
if (!defaultPropertyNames.isEmpty()) {
41-
throw new ExtensionConfigurationException(
42-
("SystemPropertyExtension was configured to restore the system properties by [%s]. " //
43-
+ "It was not possible to create an accurate snapshot of the system properties using Properties::clone because default properties [%s] were present." //
44-
).formatted( //
45-
context.getElement().orElseThrow(), //
46-
String.join(", ", defaultPropertyNames) //
47-
));
41+
throw new ExtensionConfigurationException("""
42+
SystemPropertiesExtension was configured to restore the system properties by [%s]. \
43+
However, it was not possible to create an accurate snapshot of the system properties \
44+
using Properties::clone, because default properties were present: %s""" //
45+
.formatted(context.getElement().orElseThrow(), defaultPropertyNames));
4846
}
4947
}
48+
5049
}

junit-jupiter-api/src/main/java/org/junit/jupiter/api/util/ReadsSystemProperty.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,24 @@
2424
import org.junit.jupiter.api.parallel.Resources;
2525

2626
/**
27-
* Marks tests that read system properties but don't use the system property extension themselves.
27+
* {@code @ReadsSystemProperty} marks tests that read system properties but do
28+
* not use the JVM system properties extensions themselves.
2829
*
29-
* <p>During
30-
* <a href="https://docs.junit.org/current/writing-tests/parallel-execution.html">parallel test execution</a>,
31-
* all tests annotated with {@link ClearSystemProperty}, {@link SetSystemProperty}, {@link ReadsSystemProperty}, and {@link WritesSystemProperty}
32-
* are scheduled in a way that guarantees correctness under mutation of shared global state.</p>
30+
* <p>During <a href="https://docs.junit.org/current/writing-tests/parallel-execution.html">
31+
* parallel test execution</a>, all tests annotated with
32+
* {@link SetSystemProperty @SetSystemProperty},
33+
* {@link ClearSystemProperty @ClearSystemProperty},
34+
* {@link ReadsSystemProperty @ReadsSystemProperty}, and
35+
* {@link WritesSystemProperty @WritesSystemProperty} are scheduled in a way that
36+
* guarantees correctness under mutation of shared global state.
3337
*
34-
* <p>For more details and examples, see
35-
* <a href="https://docs.junit.org/current/writing-tests/built-in-extensions.html#SystemProperty">the documentation on <code>@ClearSystemProperty</code> and <code>@SetSystemProperty</code></a>.</p>
38+
* <p>For further details and examples, see the documentation on all JVM system
39+
* property annotations in the
40+
* <a href="https://docs.junit.org/current/writing-tests/built-in-extensions.html#system-properties">
41+
* User Guide</a>.
3642
*
3743
* @since 6.1
44+
* @see WritesSystemProperty @WritesSystemProperty
3845
*/
3946
@Retention(RetentionPolicy.RUNTIME)
4047
@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PACKAGE, ElementType.TYPE })

junit-jupiter-api/src/main/java/org/junit/jupiter/api/util/RestoreSystemProperties.java

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,52 +23,64 @@
2323
import org.junit.jupiter.api.extension.ExtendWith;
2424

2525
/**
26-
* {@code @RestoreSystemProperties} is a JUnit Jupiter extension to restore the entire set of
27-
* system properties to the original value, or the value of the higher-level container, after the
28-
* annotated element is complete.
26+
* {@code @RestoreSystemProperties} is an annotation that is used to restore the
27+
* entire set of JVM system properties to its original state, or the state of the
28+
* higher-level container, after execution of the annotated element has completed.
2929
*
30-
* <p>Use this annotation when there is a need programmatically modify system properties in a test
31-
* method or in {@code @BeforeAll} / {@code @BeforeEach} blocks.
32-
* To set or clear a system property, consider {@link SetSystemProperty @SetSystemProperty} or
30+
* <p>Use this annotation when there is a need to programmatically modify system
31+
* properties in a test method or in {@code @BeforeAll} / {@code @BeforeEach}
32+
* lifecycle methods. To set or clear a system property, consider
33+
* {@link SetSystemProperty @SetSystemProperty} or
3334
* {@link ClearSystemProperty @ClearSystemProperty} instead.
3435
*
35-
* <p>{@code @RestoreSystemProperties} can be used on the method and on the class level.
36-
* When placed on a test method, a snapshot of system properties is stored prior to that test.
37-
* The snapshot is created before any {@code @BeforeEach} blocks in scope and before any
38-
* {@link SetSystemProperty @SetSystemProperty} or {@link ClearSystemProperty @ClearSystemProperty}
39-
* annotations on that method. After the test, system properties are restored from the
40-
* snapshot after any {@code @AfterEach} have completed.
36+
* <p>{@code @RestoreSystemProperties} can be used on the method and on the class
37+
* level.
4138
*
42-
* <p>When placed on a test class, a snapshot of system properties is stored prior to any
43-
* {@code @BeforeAll} blocks in scope and before any {@link SetSystemProperty @SetSystemProperty}
44-
* or {@link ClearSystemProperty @ClearSystemProperty} annotations on that class.
45-
* After the test class completes, system properties are restored from the snapshot after any
46-
* {@code @AfterAll} blocks have completed.
47-
* In addition, a class level annotation is inherited by each test method just as if each one was
39+
* <p>When declared on a test method, a snapshot of all JVM system properties is
40+
* stored prior to that test. The snapshot is created before any {@code @BeforeEach}
41+
* lifecycle methods in scope and before any {@link SetSystemProperty @SetSystemProperty}
42+
* or {@link ClearSystemProperty @ClearSystemProperty} annotations on that method.
43+
* After the test, system properties are restored from the snapshot after all
44+
* {@code @AfterEach} lifecycle methods have completed.
45+
*
46+
* <p>When placed on a test class, a snapshot of all JVM system properties is stored
47+
* prior to any {@code @BeforeAll} lifecycle methods in scope and before any
48+
* {@link SetSystemProperty @SetSystemProperty} or
49+
* {@link ClearSystemProperty @ClearSystemProperty} annotations on that class.
50+
* After the test class completes, system properties are restored from the snapshot
51+
* after any {@code @AfterAll} lifecycle methods have completed. In addition, a
52+
* class-level annotation is inherited by each test method just as if each one were
4853
* annotated with {@code RestoreSystemProperties}.
4954
*
50-
* <p>During
51-
* <a href="https://docs.junit.org/current/writing-tests/parallel-execution.html">parallel test execution</a>,
52-
* all tests annotated with {@link RestoreSystemProperties}, {@link SetSystemProperty},
53-
* {@link ReadsSystemProperty}, and {@link WritesSystemProperty}
54-
* are scheduled in a way that guarantees correctness under mutation of shared global state.
55+
* <p>During <a href="https://docs.junit.org/current/writing-tests/parallel-execution.html">
56+
* parallel test execution</a>, all tests annotated with
57+
* {@link SetSystemProperty @SetSystemProperty},
58+
* {@link ClearSystemProperty @ClearSystemProperty},
59+
* {@link ReadsSystemProperty @ReadsSystemProperty}, and
60+
* {@link WritesSystemProperty @WritesSystemProperty} are scheduled in a way that
61+
* guarantees correctness under mutation of shared global state.
5562
*
56-
* <p>For more details and examples, see
57-
* <a href="https://docs.junit.org/current/writing-tests/built-in-extensions.html#SystemProperty">the documentation on
58-
* <code>@ClearSystemProperty</code>, <code>@SetSystemProperty</code>, and <code>@RestoreSystemProperties</code></a>.</p>
63+
* <p>For further details and examples, see the documentation on all JVM system
64+
* property annotations in the
65+
* <a href="https://docs.junit.org/current/writing-tests/built-in-extensions.html#system-properties">
66+
* User Guide</a>.
5967
*
60-
* <p><em>Note:</em> The snapshot of the properties object is created using {@link Properties#clone()}.
61-
* This cloned value will not include any default values. This extension will make a best effort
62-
* attempt to detect default values and fail if any are detected. For classes that extend
63-
* {@code Properties}, it is assumed that {@code clone()} is implemented with sufficient fidelity.
68+
* <p><em>Note:</em> The snapshot of the properties object is created using
69+
* {@link Properties#clone()}. However, this cloned properties object will not
70+
* include any default values from the original properties object. Consequently,
71+
* this extension will make a best effort attempt to detect default values and
72+
* fail if any are detected. For classes that extend {@code Properties}, it is
73+
* assumed that {@code clone()} is implemented with sufficient fidelity.
6474
*
6575
* @since 6.1
76+
* @see ClearSystemProperty @ClearSystemProperty
77+
* @see SetSystemProperty @SetSystemProperty
6678
*/
6779
@Retention(RetentionPolicy.RUNTIME)
6880
@Target({ ElementType.METHOD, ElementType.TYPE })
6981
@Inherited
7082
@WritesSystemProperty
71-
@ExtendWith(SystemPropertyExtension.class)
83+
@ExtendWith(SystemPropertiesExtension.class)
7284
@API(status = EXPERIMENTAL, since = "6.1")
7385
@SuppressWarnings("exports")
7486
public @interface RestoreSystemProperties {

0 commit comments

Comments
 (0)