From d6d79857e71d575120a6c5151dcda5091cbed71b Mon Sep 17 00:00:00 2001 From: Guilhem Bonnefille Date: Fri, 13 Feb 2026 14:32:08 +0100 Subject: [PATCH 1/3] feat: support files containing testsuites --- .../java/junit/xml/merger/JunitXmlParser.java | 42 +++++++++++++++---- .../junit/xml/merger/JunitXmlParserTest.java | 8 ++++ .../xml/merger/model/TestSuitesTest.java | 4 +- src/test/resources/testsuites.xml | 13 ++++++ 4 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 src/test/resources/testsuites.xml diff --git a/src/main/java/io/codeclou/java/junit/xml/merger/JunitXmlParser.java b/src/main/java/io/codeclou/java/junit/xml/merger/JunitXmlParser.java index 614fca1..e7b32bb 100644 --- a/src/main/java/io/codeclou/java/junit/xml/merger/JunitXmlParser.java +++ b/src/main/java/io/codeclou/java/junit/xml/merger/JunitXmlParser.java @@ -43,6 +43,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Collection; public class JunitXmlParser { @@ -51,22 +52,47 @@ public class JunitXmlParser { private Boolean hasCmdLineParameterErrors = false; private Boolean hasFileNotFoundErrors = false; - protected TestSuite parseTestSuite(File filename) throws ParserConfigurationException, SAXException, IOException { + protected Collection parseTestSuites(File filename) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(filename); return transform(document.getFirstChild()); } - public TestSuite transform(Node testSuite) { + public Collection transform(Node testSuite) { + System.out.println(); + Collection testSuites = new java.util.ArrayList<>(); + if (testSuite.getNodeName().equals("testsuites")) { + // Already a collection + for (int i = 0; i < testSuite.getChildNodes().getLength(); i++) { + Node child = testSuite.getChildNodes().item(i); + if (child.getNodeName().equals("testsuite")) { + testSuites.add(transformTestSuite(child)); + } + } + } else { + TestSuite t = transformTestSuite(testSuite); + testSuites.add(t); + } + return testSuites; + } + + protected TestSuite parseTestSuite(File filename) throws ParserConfigurationException, SAXException, IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(filename); + return transformTestSuite(document.getFirstChild()); + } + + public TestSuite transformTestSuite(Node testSuite) { TestSuite t = new TestSuite(); NamedNodeMap attrs = testSuite.getAttributes(); t.setTests(attrs.getNamedItem("tests") != null ? Long.valueOf(attrs.getNamedItem("tests").getNodeValue()) : 0L); - t.setErrors(attrs.getNamedItem("errors") != null ? Long.valueOf(testSuite.getAttributes().getNamedItem("errors").getNodeValue()) : 0L); - t.setFailures(attrs.getNamedItem("failures") != null ? Long.valueOf(testSuite.getAttributes().getNamedItem("failures").getNodeValue()) : 0L); - t.setSkipped(attrs.getNamedItem("skipped") != null ? Long.valueOf(testSuite.getAttributes().getNamedItem("skipped").getNodeValue()) : 0L); - t.setName(testSuite.getAttributes().getNamedItem("name").getNodeValue()); - t.setTime(attrs.getNamedItem("time") != null ? Double.valueOf(testSuite.getAttributes().getNamedItem("time").getNodeValue()) : 0.0); + t.setErrors(attrs.getNamedItem("errors") != null ? Long.valueOf(attrs.getNamedItem("errors").getNodeValue()) : 0L); + t.setFailures(attrs.getNamedItem("failures") != null ? Long.valueOf(attrs.getNamedItem("failures").getNodeValue()) : 0L); + t.setSkipped(attrs.getNamedItem("skipped") != null ? Long.valueOf(attrs.getNamedItem("skipped").getNodeValue()) : 0L); + t.setName(attrs.getNamedItem("name").getNodeValue()); + t.setTime(attrs.getNamedItem("time") != null ? Double.valueOf(attrs.getNamedItem("time").getNodeValue()) : 0.0); t.setXml(testSuite); return t; } @@ -118,7 +144,7 @@ protected void run(String[] args) throws Exception { if (f.getAbsoluteFile().toString().endsWith(".xml")) { System.out.println("\033[32;1;2mInfo >> adding " + f.getName() + " to TestSuites\033[0m"); try { - suites.getTestSuites().add(parseTestSuite(f)); + suites.getTestSuites().addAll(parseTestSuites(f)); } catch (Exception e) { System.out.println("\033[31;1mError >> the file " + f.getName() + " cannot be read: ignored\033[0m"); e.printStackTrace(); diff --git a/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java b/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java index 51127ab..b2d05a0 100644 --- a/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java +++ b/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java @@ -28,6 +28,7 @@ import org.mockito.internal.util.reflection.Whitebox; import java.io.File; +import java.util.Collection; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.*; @@ -39,6 +40,13 @@ private File getTestFile(String filename) { return new File(classLoader.getResource(filename).getFile()); } + @Test + public void testParseSuites() throws Exception { + JunitXmlParser parser = new JunitXmlParser(); + Collection c = parser.parseTestSuites(getTestFile("testsuites.xml")); + assertFalse(c.isEmpty()); + } + @Test public void testParse() throws Exception { JunitXmlParser parser = new JunitXmlParser(); diff --git a/src/test/java/io/codeclou/java/junit/xml/merger/model/TestSuitesTest.java b/src/test/java/io/codeclou/java/junit/xml/merger/model/TestSuitesTest.java index 0535000..b2362ad 100644 --- a/src/test/java/io/codeclou/java/junit/xml/merger/model/TestSuitesTest.java +++ b/src/test/java/io/codeclou/java/junit/xml/merger/model/TestSuitesTest.java @@ -39,8 +39,8 @@ public void testPojoGetterSetter() { @Test public void testToXml() throws Exception { JunitXmlParser jxml = new JunitXmlParser(); - TestSuite suite1 = jxml.transform(XmlHelper.xmlFromString("".replaceAll("'", "\""))); - TestSuite suite2 = jxml.transform(XmlHelper.xmlFromString("".replaceAll("'", "\""))); + TestSuite suite1 = jxml.transformTestSuite(XmlHelper.xmlFromString("".replaceAll("'", "\""))); + TestSuite suite2 = jxml.transformTestSuite(XmlHelper.xmlFromString("".replaceAll("'", "\""))); TestSuites suites = new TestSuites(); suites.setName("foobar23"); suites.getTestSuites().add(suite1); diff --git a/src/test/resources/testsuites.xml b/src/test/resources/testsuites.xml new file mode 100644 index 0000000..e701ca4 --- /dev/null +++ b/src/test/resources/testsuites.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 7aeffb76549d6117889aba85e5865c9ea198ff5c Mon Sep 17 00:00:00 2001 From: Guilhem Bonnefille Date: Mon, 16 Feb 2026 18:13:15 +0100 Subject: [PATCH 2/3] fix(test): improve assertions --- .../java/junit/xml/merger/JunitXmlParserTest.java | 9 +++++++++ src/test/resources/testsuites.xml | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java b/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java index b2d05a0..5ed077a 100644 --- a/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java +++ b/src/test/java/io/codeclou/java/junit/xml/merger/JunitXmlParserTest.java @@ -28,7 +28,9 @@ import org.mockito.internal.util.reflection.Whitebox; import java.io.File; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.*; @@ -42,9 +44,16 @@ private File getTestFile(String filename) { @Test public void testParseSuites() throws Exception { + // GIVEN JunitXmlParser parser = new JunitXmlParser(); + // WHEN Collection c = parser.parseTestSuites(getTestFile("testsuites.xml")); + List l = new ArrayList<>(c); + // THEN assertFalse(c.isEmpty()); + assertEquals(2, c.size()); + assertEquals(l.get(0).getName(), "ut.io.codeclou.customfield.editor.model.rest.SortModelTestOne"); + assertEquals(l.get(1). getName(), "ut.io.codeclou.customfield.editor.model.rest.SortModelTestTwo"); } @Test diff --git a/src/test/resources/testsuites.xml b/src/test/resources/testsuites.xml index e701ca4..8afac44 100644 --- a/src/test/resources/testsuites.xml +++ b/src/test/resources/testsuites.xml @@ -1,11 +1,11 @@ - + - + From e2ab3095b99c0aca6a27e607351c21a304110a01 Mon Sep 17 00:00:00 2001 From: Guilhem Bonnefille Date: Mon, 16 Feb 2026 18:18:37 +0100 Subject: [PATCH 3/3] chore: release 1.2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index db3b295..302c511 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.codeclou java-junit-xml-merger - 1.1.0 + 1.2.0 codeclou.io http://codeclou.io/