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:
@@ -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-<version>.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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user