diff --git a/java/.mvn/jvm.config b/java/.mvn/jvm.config
new file mode 100644
index 0000000..32599ce
--- /dev/null
+++ b/java/.mvn/jvm.config
@@ -0,0 +1,10 @@
+--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
diff --git a/java/pom.xml b/java/pom.xml
index 50486b9..360a706 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -5,11 +5,11 @@
io.cucumber
cucumber-parent
- 4.5.0
+ 5.0.0-SNAPSHOT
testng-xml-formatter
- 0.7.1-SNAPSHOT
+ 0.8.0-SNAPSHOT
jar
TestNG XML Formatter
Renders Cucumber Messages as TestNG XML
@@ -59,12 +59,12 @@
io.cucumber
messages
- [29.0.1,31.0.0)
+ [32.0.0-SNAPSHOT,33.0.0)
io.cucumber
query
- [14.0.1,15.0.0)
+ [15.0.0-SNAPSHOT,16.0.0)
@@ -85,13 +85,6 @@
test
-
- org.hamcrest
- hamcrest
- 3.0
- test
-
-
org.assertj
assertj-core
@@ -111,4 +104,22 @@
test
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+ validate
+ validate
+
+ check
+
+
+
+
+
+
diff --git a/java/src/main/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriter.java b/java/src/main/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriter.java
index 25f0443..5acf46e 100644
--- a/java/src/main/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriter.java
+++ b/java/src/main/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriter.java
@@ -20,6 +20,7 @@ public void close() throws XMLStreamException {
writer.close();
}
+ @SuppressWarnings("SameParameterValue")
void writeStartDocument(String encoding, String version) throws XMLStreamException {
writer.writeStartDocument(encoding, version);
}
@@ -56,7 +57,7 @@ void writeAttribute(String localName, String value) throws XMLStreamException {
void writeCData(String data) throws XMLStreamException {
// https://stackoverflow.com/questions/223652/is-there-a-way-to-escape-a-cdata-end-token-in-xml
- for (String part : CDATA_TERMINATOR_SPLIT.split(data)) {
+ for (String part : CDATA_TERMINATOR_SPLIT.split(data, -1)) {
// see https://www.w3.org/TR/xml/#dt-cdsection
writer.writeCData(escapeIllegalChars(part));
}
@@ -88,6 +89,7 @@ private static String escapeIllegalChars(String value) {
return escaped.toString();
}
+ @SuppressWarnings("UnnecessaryParentheses")
private static boolean isLegal(int codePoint) {
// see https://www.w3.org/TR/xml/#charsets
return codePoint == 0x9
diff --git a/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportData.java b/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportData.java
index c9c880b..005ca8e 100644
--- a/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportData.java
+++ b/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportData.java
@@ -41,7 +41,7 @@
class XmlReportData {
private static final io.cucumber.messages.types.Duration ZERO_DURATION =
- new io.cucumber.messages.types.Duration(0L, 0L);
+ new io.cucumber.messages.types.Duration(0L, 0);
// By definition, but see https://github.com/cucumber/gherkin/issues/11
private static final TestStepResult SCENARIO_WITH_NO_STEPS = new TestStepResult(ZERO_DURATION, null, PASSED, null);
private final Repository repository = Repository.builder()
diff --git a/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportWriter.java b/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportWriter.java
index 478e05c..1044127 100644
--- a/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportWriter.java
+++ b/java/src/main/java/io/cucumber/testngxmlformatter/XmlReportWriter.java
@@ -50,8 +50,8 @@ private void writeTestngResultsAttributes(EscapingXmlStreamWriter writer) throws
Map counts = data.getTestCaseStatusCounts();
writer.writeAttribute("failed", String.valueOf(countFailures(counts)));
- writer.writeAttribute("passed", counts.get(PASSED).toString());
- writer.writeAttribute("skipped", counts.get(SKIPPED).toString());
+ writer.writeAttribute("passed", String.valueOf(counts.get(PASSED)));
+ writer.writeAttribute("skipped", String.valueOf(counts.get(SKIPPED)));
writer.writeAttribute("total", String.valueOf(data.getTestCaseCount()));
}
@@ -142,14 +142,11 @@ private void writeTestMethodAttributes(EscapingXmlStreamWriter writer, TestCaseS
}
private String writeStatus(TestStepResult status) {
- switch (status.getStatus()) {
- case PASSED:
- return "PASS";
- case SKIPPED:
- return "SKIP";
- default:
- return "FAIL";
- }
+ return switch (status.getStatus()) {
+ case PASSED -> "PASS";
+ case SKIPPED -> "SKIP";
+ default -> "FAIL";
+ };
}
private void writeException(EscapingXmlStreamWriter writer, TestCaseStarted testCaseStarted, TestStepResult result) throws XMLStreamException {
@@ -216,9 +213,7 @@ private String createStepResultList(List> results) {
String status = r.getValue();
sb.append(stepText);
sb.append(".");
- for (int i = 75 - stepText.length(); i > 0; i--) {
- sb.append(".");
- }
+ sb.append(".".repeat(Math.max(0, 75 - stepText.length())));
sb.append(status);
sb.append("\n");
});
diff --git a/java/src/main/java/io/cucumber/testngxmlformatter/package-info.java b/java/src/main/java/io/cucumber/testngxmlformatter/package-info.java
new file mode 100644
index 0000000..1dba1b9
--- /dev/null
+++ b/java/src/main/java/io/cucumber/testngxmlformatter/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.testngxmlformatter;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/java/src/test/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriterTest.java b/java/src/test/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriterTest.java
index 57537a8..9e4084e 100644
--- a/java/src/test/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriterTest.java
+++ b/java/src/test/java/io/cucumber/testngxmlformatter/EscapingXmlStreamWriterTest.java
@@ -64,7 +64,7 @@ void shouldEscapeCDataElement() throws XMLStreamException {
}
private static String asString(ByteArrayOutputStream out) {
- String s = new String(out.toByteArray(), UTF_8);
+ String s = out.toString(UTF_8);
return removeXmlHeader(s);
}
diff --git a/java/src/test/java/io/cucumber/testngxmlformatter/Jackson.java b/java/src/test/java/io/cucumber/testngxmlformatter/Jackson.java
index cdf2430..34593f9 100644
--- a/java/src/test/java/io/cucumber/testngxmlformatter/Jackson.java
+++ b/java/src/test/java/io/cucumber/testngxmlformatter/Jackson.java
@@ -1,7 +1,6 @@
package io.cucumber.testngxmlformatter;
import com.fasterxml.jackson.annotation.JsonCreator.Mode;
-import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -11,11 +10,14 @@
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT;
+import static com.fasterxml.jackson.annotation.JsonInclude.Value.construct;
+
final class Jackson {
public static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder()
.addModule(new Jdk8Module())
.addModule(new ParameterNamesModule(Mode.PROPERTIES))
- .serializationInclusion(Include.NON_ABSENT)
+ .defaultPropertyInclusion(construct(NON_ABSENT, NON_ABSENT))
.constructorDetector(ConstructorDetector.USE_PROPERTIES_BASED)
.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
diff --git a/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterAcceptanceTest.java b/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterAcceptanceTest.java
index 347f0bf..d004b55 100644
--- a/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterAcceptanceTest.java
+++ b/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterAcceptanceTest.java
@@ -22,10 +22,11 @@
import java.util.stream.Stream;
import static io.cucumber.testngxmlformatter.Jackson.OBJECT_MAPPER;
+import static java.util.Objects.requireNonNull;
import static org.xmlunit.assertj.XmlAssert.assertThat;
class MessagesToTestngXmlWriterAcceptanceTest {
- private static final NdjsonToMessageIterable.Deserializer deserializer = (json) -> OBJECT_MAPPER.readValue(json, Envelope.class);
+ private static final NdjsonToMessageIterable.Deserializer deserializer = json -> OBJECT_MAPPER.readValue(json, Envelope.class);
static List acceptance() throws IOException {
try (Stream paths = Files.list(Paths.get("../testdata/src"))) {
@@ -68,17 +69,16 @@ private static T writeTestngXmlReport(TestCase testCase
return out;
}
- static class TestCase {
+ private static final class TestCase {
private final Path source;
private final Path expected;
-
private final String name;
TestCase(Path source) {
this.source = source;
String fileName = source.getFileName().toString();
this.name = fileName.substring(0, fileName.lastIndexOf(".ndjson"));
- this.expected = source.getParent().resolve(name + ".xml");
+ this.expected = requireNonNull(source.getParent()).resolve(name + ".xml");
}
@Override
@@ -88,15 +88,13 @@ public String toString() {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- TestCase testCase = (TestCase) o;
- return source.equals(testCase.source);
+ if (!(o instanceof TestCase testCase)) return false;
+ return Objects.equals(source, testCase.source) && Objects.equals(expected, testCase.expected) && Objects.equals(name, testCase.name);
}
@Override
public int hashCode() {
- return Objects.hash(source);
+ return Objects.hash(source, expected, name);
}
}
diff --git a/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterTest.java b/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterTest.java
index cd34bd0..72bd2ae 100644
--- a/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterTest.java
+++ b/java/src/test/java/io/cucumber/testngxmlformatter/MessagesToTestngXmlWriterTest.java
@@ -3,6 +3,7 @@
import io.cucumber.messages.types.Envelope;
import io.cucumber.messages.types.TestRunFinished;
import io.cucumber.messages.types.TestRunStarted;
+import io.cucumber.messages.types.Timestamp;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
@@ -26,28 +27,30 @@ void it_writes_two_messages_to_xml() throws IOException {
Envelope.of(new TestRunStarted(toMessage(started), null)),
Envelope.of(new TestRunFinished(null, true, toMessage(finished), null, null)));
- assertThat(html).isEqualTo("" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n"
+ assertThat(html).isEqualTo("""
+
+
+
+
+
+
+
+ """
);
}
@Test
void it_writes_no_message_to_xml() throws IOException {
String html = renderAsJunitXml();
- assertThat(html).isEqualTo("" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n"
+ assertThat(html).isEqualTo("""
+
+
+
+
+
+
+
+ """
);
}
@@ -56,7 +59,9 @@ void it_throws_when_writing_after_close() throws IOException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
MessagesToTestngXmlWriter messagesToHtmlWriter = new MessagesToTestngXmlWriter(bytes);
messagesToHtmlWriter.close();
- assertThrows(IOException.class, () -> messagesToHtmlWriter.write(null));
+ assertThrows(IOException.class, () -> messagesToHtmlWriter.write(
+ Envelope.of(new TestRunStarted(new Timestamp(0L, 0), ""))
+ ));
}
@Test
@@ -92,6 +97,6 @@ private static String renderAsJunitXml(Envelope... messages) throws IOException
}
}
- return new String(bytes.toByteArray(), UTF_8);
+ return bytes.toString(UTF_8);
}
}