Add junit-6-migration module: JUnit 5.14.4 vs 6.1.3, API diff and behaviour probes

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YPgGH6aMbSLANL3E2HHmS6
This commit is contained in:
2026-10-25 18:46:52 +00:00
co-authored by Claude Sonnet 5.5
parent 8fc8bc934f
commit 820318be7d
22 changed files with 1018 additions and 0 deletions
@@ -0,0 +1,86 @@
package com.ankurm.junitmigration;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
/**
* Runs the same probe classes on whichever JUnit is on the class path and writes what happened to
* output/NN-name-&lt;version&gt;.txt. The two versions are meant to give different answers in places, so this
* test records them instead of asserting them. It does assert that the probes ran at all.
*/
class BehaviourTest {
private static final String VERSION = System.getProperty("junit.version", "unknown");
@Test
void csvBehaviour() throws IOException {
List<String> lines = run(CsvProbe.class);
write("03-csv-behaviour", lines);
assertTrue(lines.size() > 10, "probe produced results");
}
@Test
void vintageStillRunsJUnit4() throws IOException {
List<String> lines = run(LegacyJUnit4Test.class);
write("04-vintage-junit4", lines);
assertTrue(lines.stream().anyMatch(l -> l.contains("stillRuns") && l.contains("SUCCESSFUL")), "junit 4 test ran");
}
private static List<String> run(Class<?> probe) {
List<String> lines = new ArrayList<>();
var request = LauncherDiscoveryRequestBuilder.request().selectors(selectClass(probe)).build();
var launcher = LauncherFactory.create();
launcher.execute(request, new TestExecutionListener() {
@Override
public void executionSkipped(TestIdentifier id, String reason) {
lines.add(String.format("%-11s %s -> %s", "SKIPPED", id.getDisplayName(), reason));
}
@Override
public void executionFinished(TestIdentifier id, TestExecutionResult result) {
// a parameterized method is a container: report it too when it fails as a whole
if (!id.isTest() && result.getStatus() == TestExecutionResult.Status.SUCCESSFUL) {
return;
}
if (!id.isTest() && id.getParentId().isEmpty()) {
return;
}
String outcome = result.getStatus().name();
String message = result.getThrowable().map(t -> " -> " + t.getClass().getSimpleName() + ": "
+ firstLine(t.getMessage())).orElse("");
lines.add(String.format("%-11s %s%s%s", outcome, id.isTest() ? "" : "[method] ", id.getDisplayName(), message));
}
});
return lines;
}
private static String firstLine(String s) {
if (s == null) {
return "";
}
String one = s.lines().findFirst().orElse("");
return one.length() > 110 ? one.substring(0, 110) + "..." : one;
}
private static void write(String name, List<String> lines) throws IOException {
Path dir = Path.of("output");
Files.createDirectories(dir);
List<String> out = new ArrayList<>();
out.add("JUnit " + VERSION);
out.addAll(lines);
Files.write(dir.resolve(name + "-" + VERSION + ".txt"), out);
}
}
@@ -0,0 +1,56 @@
package com.ankurm.junitmigration;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
/**
* Not run by Surefire (the name does not end in Test). {@link BehaviourTest} launches it through the
* JUnit Platform Launcher and records what each invocation was called and whether it passed, on whichever
* JUnit version is on the class path.
*/
class CsvProbe {
@ParameterizedTest
@CsvSource({
"apple, 1",
"'a,b', 2",
" padded , 3",
"'', 4",
", 5",
"NIL, 6",
"'it''s', 7",
"\"dq\", 8"
})
void basicRows(String name, int n) {
}
@ParameterizedTest
@CsvSource(value = {"x;1", "y;2"}, delimiter = ';', useHeadersInDisplayName = false)
void customDelimiter(String name, int n) {
}
@ParameterizedTest
@CsvSource(textBlock = """
name, qty
widget, 4
'multi word', 5
""", useHeadersInDisplayName = true)
void textBlockWithHeader(String name, int qty) {
}
@ParameterizedTest
@CsvSource(value = {"a,b,c"})
void tooManyColumnsForParameters(String first) {
}
@ParameterizedTest
@CsvSource(value = {"1234567890,1"}, maxCharsPerColumn = 5)
void columnLongerThanLimit(String value, int n) {
}
@ParameterizedTest
@CsvFileSource(resources = "/probe.csv", numLinesToSkip = 1)
void fileRows(String name, int n) {
}
}
@@ -0,0 +1,14 @@
package com.ankurm.junitmigration;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/** A JUnit 4 test. It is discovered by the Vintage engine, not by Jupiter. */
public class LegacyJUnit4Test {
@Test
public void stillRuns() {
assertEquals(4, 2 + 2);
}
}