Repository navigation
Execute each JUnit 5 test template invocation once in its own JVM - #288
Merged
jeanbisutti merged 1 commit intoOct 18, 2026
Merged
jeanbisutti merged 1 commit into
jeanbisutti merged 1 commit into
Conversation
With an annotation that needs a specific JVM (@heapsize, @JvmOptions, @MeasureHeapAllocation, @ExpectMaxHeapAllocation...), the forked JVM selected the test by class and method name. A @RepeatedTest or a @ParameterizedClass then ran all its invocations in each forked JVM (N x N executions, with measures and failures reported for the wrong invocation), and a test method having parameters (@ParameterizedTest, TestInfo, @tempdir...) could not be found and failed with a JvmError. The test JVM now saves the JUnit unique id of the invocation in the working folder, and the forked JVM executes the test having this id, without the segments of a @suite. The forked JVM fails the test with an explicit message when JUnit does not start exactly one test there, and reports a test aborted there as aborted. Template invocations use the allocation offset of the other tests. @ParameterizedClass and @BeforeSuite are tested in a new test module on JUnit 5.14.4, junit5-14-4-jvm-test, because the other JUnit 5 modules use JUnit 5.6.2.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With an annotation that needs a specific JVM (
@HeapSize,@Xmx,@JvmOptions,@MeasureHeapAllocation,@ExpectMaxHeapAllocation,@ProfileJvm...), QuickPerf executes the JUnit 5 test in a new JVM. The new JVM only got the class name and the method name, and selected the test withselectMethod(testClass, methodName). As a consequence:@RepeatedTest(N)or a@ParameterizedClassran all its invocations in each new JVM: N x N executions. Each invocation reported the measure of the last execution in its JVM, and the failures of the other executions in its JVM.@ParameterizedTest,RepetitionInfo,TestInfo,TestReporter,@TempDir, a parameter resolved by an extension) could not be found in the new JVM: the test failed with aJvmError, without executing the test method.UnexpectedQuickPerfExceptionwhen the assumption failed in a@BeforeEachor@BeforeAllmethod of a test having an allocation annotation.This PR:
ExtensionContext.getUniqueId()) in the working folder before forking (junit5-test-to-execute.ser). The new JVM executes the test having this unique id, withselectUniqueId. The unique id of a test template invocation contains its index, for example[test-template-invocation:#2]. For a test executed through a@Suite, the new JVM removes the segments of the suite engine: as before, it executes the test with the Jupiter engine only, without the@BeforeSuiteand@AfterSuitemethods.@BeforeEachor@BeforeAllmethod, or in an arguments source): no performance record is evaluated;@AfterEachmethod): the performance records are evaluated, as when the test executes in the test JVM;InvocationTargetException, as JUnit does, so that JUnit and the other extensions handle it as usual.OutOfMemoryError. The new JVM then still ends withSystem.exit, even if the test left non-daemon threads.Every JUnit 5 test executed in a new JVM now goes through the unique id selection and the check, not only the test template invocations. The main code changes are in
junit5-extensiononly, with three new package-private classes: no change tocore, to JUnit 4, to TestNG, or to a public API.Behavior changes for users
@RepeatedTest,@ParameterizedTest,@ParameterizedClassand test methods having parameters now work with the annotations that need a specific JVM.[test-template-invocation:#2], it calls the arguments source (@MethodSource...) again and executes the test with the second arguments it returns. So the arguments source has to return the same arguments, in the same order, in every JVM. WithSet.of(...), whose iteration order changes from one JVM to another, with aHashSetof objects that do not overridehashCode(), or with random values, the new JVM can execute the test with other arguments than the invocation that JUnit reports, without any warning. When the arguments source returns fewer arguments in the new JVM, the test fails with an explicit message.@RetryingTestcannot retry a test executed in a new JVM: only the first attempt exists there. A test failing its first attempt fails, with an explicit message.@JvmOptions("-Dname=value"), because the new JVM does not get the system properties of the test JVM.