diff --git a/pom.xml b/pom.xml index 18cea2f..474e5da 100644 --- a/pom.xml +++ b/pom.xml @@ -77,6 +77,11 @@ commons-codec + + jakarta.xml.bind + jakarta.xml.bind-api + + org.springframework.boot -- 2.51.2 From 1851f0b5d8a4f79db9fa6973e32909f2d9149e23 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Thu, 24 Aug 2023 15:27:57 +0200 Subject: [PATCH 02/22] =?UTF-8?q?=E2=9C=A8=20:=20add=20surefire-test-repor?= =?UTF-8?q?t.xsd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit taken from https://github.com/apache/maven-surefire/blob/master/maven-surefire-plugin/src/site/resources/xsd/surefire-test-report.xsd this file was used to generate the JAXB bindings for the surefire test reports --- src/main/resources/surefire-test-report.xsd | 132 ++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/main/resources/surefire-test-report.xsd diff --git a/src/main/resources/surefire-test-report.xsd b/src/main/resources/surefire-test-report.xsd new file mode 100644 index 0000000..e19d637 --- /dev/null +++ b/src/main/resources/surefire-test-report.xsd @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.51.2 From 7a7d889f81e6e15526361637db034d9575d3bb2f Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Thu, 24 Aug 2023 15:29:39 +0200 Subject: [PATCH 03/22] =?UTF-8?q?=E2=9C=A8=20:=20generate=20JAXB=20binding?= =?UTF-8?q?s=20for=20surefire-test-report.xsd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../testReports/ObjectFactory.java | 150 ++ .../assignments/testReports/TestSuite.java | 2023 +++++++++++++++++ 2 files changed, 2173 insertions(+) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/ObjectFactory.java create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuite.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/ObjectFactory.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/ObjectFactory.java new file mode 100644 index 0000000..eead971 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/ObjectFactory.java @@ -0,0 +1,150 @@ +package fr.univ_lille.gitlab.classrooms.assignments.testReports; + +import jakarta.xml.bind.JAXBElement; +import jakarta.xml.bind.annotation.XmlElementDecl; +import jakarta.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the generated package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _TestSuiteTestcaseSkipped_QNAME = new QName("", "skipped"); + private final static QName _TestSuiteTestcaseError_QNAME = new QName("", "error"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: generated + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link TestSuite } + * + */ + public TestSuite createTestSuite() { + return new TestSuite(); + } + + /** + * Create an instance of {@link TestSuite.Testcase } + * + */ + public TestSuite.Testcase createTestSuiteTestcase() { + return new TestSuite.Testcase(); + } + + /** + * Create an instance of {@link TestSuite.Properties } + * + */ + public TestSuite.Properties createTestSuiteProperties() { + return new TestSuite.Properties(); + } + + /** + * Create an instance of {@link TestSuite.Testcase.Failure } + * + */ + public TestSuite.Testcase.Failure createTestSuiteTestcaseFailure() { + return new TestSuite.Testcase.Failure(); + } + + /** + * Create an instance of {@link TestSuite.Testcase.RerunFailure } + * + */ + public TestSuite.Testcase.RerunFailure createTestSuiteTestcaseRerunFailure() { + return new TestSuite.Testcase.RerunFailure(); + } + + /** + * Create an instance of {@link TestSuite.Testcase.FlakyFailure } + * + */ + public TestSuite.Testcase.FlakyFailure createTestSuiteTestcaseFlakyFailure() { + return new TestSuite.Testcase.FlakyFailure(); + } + + /** + * Create an instance of {@link TestSuite.Testcase.Skipped } + * + */ + public TestSuite.Testcase.Skipped createTestSuiteTestcaseSkipped() { + return new TestSuite.Testcase.Skipped(); + } + + /** + * Create an instance of {@link TestSuite.Testcase.Error } + * + */ + public TestSuite.Testcase.Error createTestSuiteTestcaseError() { + return new TestSuite.Testcase.Error(); + } + + /** + * Create an instance of {@link TestSuite.Testcase.RerunError } + * + */ + public TestSuite.Testcase.RerunError createTestSuiteTestcaseRerunError() { + return new TestSuite.Testcase.RerunError(); + } + + /** + * Create an instance of {@link TestSuite.Testcase.FlakyError } + * + */ + public TestSuite.Testcase.FlakyError createTestSuiteTestcaseFlakyError() { + return new TestSuite.Testcase.FlakyError(); + } + + /** + * Create an instance of {@link TestSuite.Properties.Property } + * + */ + public TestSuite.Properties.Property createTestSuitePropertiesProperty() { + return new TestSuite.Properties.Property(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Skipped }{@code >} + * + * @param value + * Java instance representing xml element's value. + * @return + * the new instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Skipped }{@code >} + */ + @XmlElementDecl(namespace = "", name = "skipped", scope = TestSuite.Testcase.class) + public JAXBElement createTestSuiteTestcaseSkipped(TestSuite.Testcase.Skipped value) { + return new JAXBElement(_TestSuiteTestcaseSkipped_QNAME, TestSuite.Testcase.Skipped.class, TestSuite.Testcase.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Error }{@code >} + * + * @param value + * Java instance representing xml element's value. + * @return + * the new instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Error }{@code >} + */ + @XmlElementDecl(namespace = "", name = "error", scope = TestSuite.Testcase.class) + public JAXBElement createTestSuiteTestcaseError(TestSuite.Testcase.Error value) { + return new JAXBElement(_TestSuiteTestcaseError_QNAME, TestSuite.Testcase.Error.class, TestSuite.Testcase.class, value); + } + +} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuite.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuite.java new file mode 100644 index 0000000..c61b99a --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuite.java @@ -0,0 +1,2023 @@ +package fr.univ_lille.gitlab.classrooms.assignments.testReports; + +import java.util.ArrayList; +import java.util.List; +import jakarta.xml.bind.JAXBElement; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementRef; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.XmlValue; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="properties" maxOccurs="unbounded" minOccurs="0">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="property" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <element name="testcase" maxOccurs="unbounded" minOccurs="0">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="failure" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <simpleContent>
+ *                         <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </extension>
+ *                       </simpleContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="rerunFailure" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                           </sequence>
+ *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="flakyFailure" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                           </sequence>
+ *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="skipped" minOccurs="0">
+ *                     <complexType>
+ *                       <simpleContent>
+ *                         <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </extension>
+ *                       </simpleContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="error" minOccurs="0">
+ *                     <complexType>
+ *                       <simpleContent>
+ *                         <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </extension>
+ *                       </simpleContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="rerunError" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                           </sequence>
+ *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="flakyError" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                           </sequence>
+ *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                 </sequence>
+ *                 <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                 <attribute name="classname" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                 <attribute name="group" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                 <attribute name="time" use="required" type="{http://www.w3.org/2001/XMLSchema}float" />
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *       </sequence>
+ *       <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="time" type="{http://www.w3.org/2001/XMLSchema}float" />
+ *       <attribute name="tests" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="errors" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="skipped" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="failures" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="group" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "properties", + "testcase" +}) +@XmlRootElement(name = "testsuite") +public class TestSuite { + + protected List properties; + protected List testcase; + @XmlAttribute(name = "version") + protected String version; + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "time") + protected Float time; + @XmlAttribute(name = "tests", required = true) + protected String tests; + @XmlAttribute(name = "errors", required = true) + protected String errors; + @XmlAttribute(name = "skipped", required = true) + protected String skipped; + @XmlAttribute(name = "failures", required = true) + protected String failures; + @XmlAttribute(name = "group") + protected String group; + + /** + * Gets the value of the properties property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the properties property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getProperties().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Properties } + * + * + */ + public List getProperties() { + if (properties == null) { + properties = new ArrayList(); + } + return this.properties; + } + + /** + * Gets the value of the testcase property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the testcase property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getTestcase().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Testcase } + * + * + */ + public List getTestcase() { + if (testcase == null) { + testcase = new ArrayList(); + } + return this.testcase; + } + + /** + * Gets the value of the version property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVersion() { + return version; + } + + /** + * Sets the value of the version property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVersion(String value) { + this.version = value; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the time property. + * + * @return + * possible object is + * {@link Float } + * + */ + public Float getTime() { + return time; + } + + /** + * Sets the value of the time property. + * + * @param value + * allowed object is + * {@link Float } + * + */ + public void setTime(Float value) { + this.time = value; + } + + /** + * Gets the value of the tests property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getTests() { + return tests; + } + + /** + * Sets the value of the tests property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setTests(String value) { + this.tests = value; + } + + /** + * Gets the value of the errors property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getErrors() { + return errors; + } + + /** + * Sets the value of the errors property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setErrors(String value) { + this.errors = value; + } + + /** + * Gets the value of the skipped property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSkipped() { + return skipped; + } + + /** + * Sets the value of the skipped property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSkipped(String value) { + this.skipped = value; + } + + /** + * Gets the value of the failures property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFailures() { + return failures; + } + + /** + * Sets the value of the failures property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFailures(String value) { + this.failures = value; + } + + /** + * Gets the value of the group property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getGroup() { + return group; + } + + /** + * Sets the value of the group property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setGroup(String value) { + this.group = value; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence>
+     *         <element name="property" maxOccurs="unbounded" minOccurs="0">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "property" + }) + public static class Properties { + + protected List property; + + /** + * Gets the value of the property property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the property property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getProperty().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Property } + * + * + */ + public List getProperty() { + if (property == null) { + property = new ArrayList(); + } + return this.property; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Property { + + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "value", required = true) + protected String value; + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence>
+     *         <element name="failure" maxOccurs="unbounded" minOccurs="0">
+     *           <complexType>
+     *             <simpleContent>
+     *               <extension base="<http://www.w3.org/2001/XMLSchema>string">
+     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </extension>
+     *             </simpleContent>
+     *           </complexType>
+     *         </element>
+     *         <element name="rerunFailure" maxOccurs="unbounded" minOccurs="0">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <sequence>
+     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                 </sequence>
+     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *         <element name="flakyFailure" maxOccurs="unbounded" minOccurs="0">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <sequence>
+     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                 </sequence>
+     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *         <element name="skipped" minOccurs="0">
+     *           <complexType>
+     *             <simpleContent>
+     *               <extension base="<http://www.w3.org/2001/XMLSchema>string">
+     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </extension>
+     *             </simpleContent>
+     *           </complexType>
+     *         </element>
+     *         <element name="error" minOccurs="0">
+     *           <complexType>
+     *             <simpleContent>
+     *               <extension base="<http://www.w3.org/2001/XMLSchema>string">
+     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </extension>
+     *             </simpleContent>
+     *           </complexType>
+     *         </element>
+     *         <element name="rerunError" maxOccurs="unbounded" minOccurs="0">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <sequence>
+     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                 </sequence>
+     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *         <element name="flakyError" maxOccurs="unbounded" minOccurs="0">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <sequence>
+     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *                 </sequence>
+     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+     *       </sequence>
+     *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       <attribute name="classname" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       <attribute name="group" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       <attribute name="time" use="required" type="{http://www.w3.org/2001/XMLSchema}float" />
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "failure", + "rerunFailure", + "flakyFailure", + "skipped", + "error", + "rerunError", + "flakyError", + "systemOut", + "systemErr" + }) + public static class Testcase { + + @XmlElement(nillable = true) + protected List failure; + protected List rerunFailure; + protected List flakyFailure; + @XmlElementRef(name = "skipped", type = JAXBElement.class, required = false) + protected JAXBElement skipped; + @XmlElementRef(name = "error", type = JAXBElement.class, required = false) + protected JAXBElement error; + protected List rerunError; + protected List flakyError; + @XmlElement(name = "system-out") + protected String systemOut; + @XmlElement(name = "system-err") + protected String systemErr; + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "classname") + protected String classname; + @XmlAttribute(name = "group") + protected String group; + @XmlAttribute(name = "time", required = true) + protected float time; + + /** + * Gets the value of the failure property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the failure property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getFailure().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Failure } + * + * + */ + public List getFailure() { + if (failure == null) { + failure = new ArrayList(); + } + return this.failure; + } + + /** + * Gets the value of the rerunFailure property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the rerunFailure property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getRerunFailure().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link RerunFailure } + * + * + */ + public List getRerunFailure() { + if (rerunFailure == null) { + rerunFailure = new ArrayList(); + } + return this.rerunFailure; + } + + /** + * Gets the value of the flakyFailure property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the flakyFailure property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getFlakyFailure().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link FlakyFailure } + * + * + */ + public List getFlakyFailure() { + if (flakyFailure == null) { + flakyFailure = new ArrayList(); + } + return this.flakyFailure; + } + + /** + * Gets the value of the skipped property. + * + * @return + * possible object is + * {@link JAXBElement }{@code <}{@link Skipped }{@code >} + * + */ + public JAXBElement getSkipped() { + return skipped; + } + + /** + * Sets the value of the skipped property. + * + * @param value + * allowed object is + * {@link JAXBElement }{@code <}{@link Skipped }{@code >} + * + */ + public void setSkipped(JAXBElement value) { + this.skipped = value; + } + + /** + * Gets the value of the error property. + * + * @return + * possible object is + * {@link JAXBElement }{@code <}{@link Error }{@code >} + * + */ + public JAXBElement getError() { + return error; + } + + /** + * Sets the value of the error property. + * + * @param value + * allowed object is + * {@link JAXBElement }{@code <}{@link Error }{@code >} + * + */ + public void setError(JAXBElement value) { + this.error = value; + } + + /** + * Gets the value of the rerunError property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the rerunError property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getRerunError().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link RerunError } + * + * + */ + public List getRerunError() { + if (rerunError == null) { + rerunError = new ArrayList(); + } + return this.rerunError; + } + + /** + * Gets the value of the flakyError property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the flakyError property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getFlakyError().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link FlakyError } + * + * + */ + public List getFlakyError() { + if (flakyError == null) { + flakyError = new ArrayList(); + } + return this.flakyError; + } + + /** + * Gets the value of the systemOut property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemOut() { + return systemOut; + } + + /** + * Sets the value of the systemOut property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemOut(String value) { + this.systemOut = value; + } + + /** + * Gets the value of the systemErr property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemErr() { + return systemErr; + } + + /** + * Sets the value of the systemErr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemErr(String value) { + this.systemErr = value; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the classname property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getClassname() { + return classname; + } + + /** + * Sets the value of the classname property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setClassname(String value) { + this.classname = value; + } + + /** + * Gets the value of the group property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getGroup() { + return group; + } + + /** + * Sets the value of the group property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setGroup(String value) { + this.group = value; + } + + /** + * Gets the value of the time property. + * + */ + public float getTime() { + return time; + } + + /** + * Sets the value of the time property. + * + */ + public void setTime(float value) { + this.time = value; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <simpleContent>
+         *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </extension>
+         *   </simpleContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "value" + }) + public static class Error { + + @XmlValue + protected String value; + @XmlAttribute(name = "message") + protected String message; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the value of the message property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMessage(String value) { + this.message = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <simpleContent>
+         *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </extension>
+         *   </simpleContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "value" + }) + public static class Failure { + + @XmlValue + protected String value; + @XmlAttribute(name = "message") + protected String message; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the value of the message property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMessage(String value) { + this.message = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <sequence>
+         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *       </sequence>
+         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "stackTrace", + "systemOut", + "systemErr" + }) + public static class FlakyError { + + @XmlElement(required = true) + protected String stackTrace; + @XmlElement(name = "system-out") + protected String systemOut; + @XmlElement(name = "system-err") + protected String systemErr; + @XmlAttribute(name = "message") + protected String message; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Gets the value of the stackTrace property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getStackTrace() { + return stackTrace; + } + + /** + * Sets the value of the stackTrace property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setStackTrace(String value) { + this.stackTrace = value; + } + + /** + * Gets the value of the systemOut property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemOut() { + return systemOut; + } + + /** + * Sets the value of the systemOut property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemOut(String value) { + this.systemOut = value; + } + + /** + * Gets the value of the systemErr property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemErr() { + return systemErr; + } + + /** + * Sets the value of the systemErr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemErr(String value) { + this.systemErr = value; + } + + /** + * Gets the value of the message property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMessage(String value) { + this.message = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <sequence>
+         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *       </sequence>
+         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "stackTrace", + "systemOut", + "systemErr" + }) + public static class FlakyFailure { + + @XmlElement(required = true) + protected String stackTrace; + @XmlElement(name = "system-out") + protected String systemOut; + @XmlElement(name = "system-err") + protected String systemErr; + @XmlAttribute(name = "message") + protected String message; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Gets the value of the stackTrace property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getStackTrace() { + return stackTrace; + } + + /** + * Sets the value of the stackTrace property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setStackTrace(String value) { + this.stackTrace = value; + } + + /** + * Gets the value of the systemOut property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemOut() { + return systemOut; + } + + /** + * Sets the value of the systemOut property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemOut(String value) { + this.systemOut = value; + } + + /** + * Gets the value of the systemErr property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemErr() { + return systemErr; + } + + /** + * Sets the value of the systemErr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemErr(String value) { + this.systemErr = value; + } + + /** + * Gets the value of the message property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMessage(String value) { + this.message = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <sequence>
+         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *       </sequence>
+         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "stackTrace", + "systemOut", + "systemErr" + }) + public static class RerunError { + + @XmlElement(required = true) + protected String stackTrace; + @XmlElement(name = "system-out") + protected String systemOut; + @XmlElement(name = "system-err") + protected String systemErr; + @XmlAttribute(name = "message") + protected String message; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Gets the value of the stackTrace property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getStackTrace() { + return stackTrace; + } + + /** + * Sets the value of the stackTrace property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setStackTrace(String value) { + this.stackTrace = value; + } + + /** + * Gets the value of the systemOut property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemOut() { + return systemOut; + } + + /** + * Sets the value of the systemOut property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemOut(String value) { + this.systemOut = value; + } + + /** + * Gets the value of the systemErr property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemErr() { + return systemErr; + } + + /** + * Sets the value of the systemErr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemErr(String value) { + this.systemErr = value; + } + + /** + * Gets the value of the message property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMessage(String value) { + this.message = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <sequence>
+         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+         *       </sequence>
+         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "stackTrace", + "systemOut", + "systemErr" + }) + public static class RerunFailure { + + @XmlElement(required = true) + protected String stackTrace; + @XmlElement(name = "system-out") + protected String systemOut; + @XmlElement(name = "system-err") + protected String systemErr; + @XmlAttribute(name = "message") + protected String message; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Gets the value of the stackTrace property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getStackTrace() { + return stackTrace; + } + + /** + * Sets the value of the stackTrace property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setStackTrace(String value) { + this.stackTrace = value; + } + + /** + * Gets the value of the systemOut property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemOut() { + return systemOut; + } + + /** + * Sets the value of the systemOut property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemOut(String value) { + this.systemOut = value; + } + + /** + * Gets the value of the systemErr property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemErr() { + return systemErr; + } + + /** + * Sets the value of the systemErr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemErr(String value) { + this.systemErr = value; + } + + /** + * Gets the value of the message property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMessage(String value) { + this.message = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <simpleContent>
+         *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     </extension>
+         *   </simpleContent>
+         * </complexType>
+         * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "value" + }) + public static class Skipped { + + @XmlValue + protected String value; + @XmlAttribute(name = "message") + protected String message; + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the value of the message property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMessage(String value) { + this.message = value; + } + + } + + } + +} -- 2.51.2 From e9e95ab78777f2716d824441d6eea822f2c72a83 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Thu, 24 Aug 2023 15:30:05 +0200 Subject: [PATCH 04/22] =?UTF-8?q?=E2=9C=85=20:=20test=20the=20JAXB=20bindi?= =?UTF-8?q?ng=20with=20a=20real-world=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../testReports/TestSuiteTest.java | 46 +++++++++++++++++++ src/test/resources/cucumber-junit-output.xml | 30 ++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteTest.java create mode 100644 src/test/resources/cucumber-junit-output.xml diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteTest.java new file mode 100644 index 0000000..ad63598 --- /dev/null +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteTest.java @@ -0,0 +1,46 @@ +package fr.univ_lille.gitlab.classrooms.assignments.testReports; + +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import org.junit.jupiter.api.Test; +import org.springframework.core.io.ClassPathResource; + +import javax.xml.transform.stream.StreamSource; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.*; + +class TestSuiteTest { + + @Test + void testReadXmlJaxb() throws IOException, JAXBException { + var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); + + var file = new ClassPathResource("/cucumber-junit-output.xml"); + + var root = unmarshaller.unmarshal(new StreamSource(file.getInputStream()), TestSuite.class); + var testSuite = root.getValue(); + + assertThat(testSuite.getName()).isEqualTo("Cucumber"); + assertThat(testSuite.getTime()).isEqualTo(10.772f); + assertThat(testSuite.getTests()).isEqualTo("2"); + assertThat(testSuite.getSkipped()).isEqualTo("0"); + assertThat(testSuite.getFailures()).isEqualTo("1"); + assertThat(testSuite.getErrors()).isEqualTo("0"); + + assertThat(testSuite.getTestcase()).hasSize(2); + var firstTest = testSuite.getTestcase().get(0); + assertThat(firstTest.getClassname()).isEqualTo("Premier Contrôleur Spring"); + assertThat(firstTest.getFailure()).isNullOrEmpty(); + assertThat(firstTest.getSystemOut()).contains("And La réponse a un body \"Hello World\""); + + var secondTest = testSuite.getTestcase().get(1); + assertThat(secondTest.getClassname()).isEqualTo("Premier Contrôleur Spring"); + assertThat(secondTest.getFailure()).hasSize(1); + assertThat(secondTest.getFailure().get(0).getType()).isEqualTo("java.lang.AssertionError"); + assertThat(secondTest.getFailure().get(0).getMessage()).isEqualTo("Element with name 'password_verify' not present."); + assertThat(secondTest.getFailure().get(0).getValue()).contains("java.lang.AssertionError: Element with name 'password_verify' not present"); + } + + +} diff --git a/src/test/resources/cucumber-junit-output.xml b/src/test/resources/cucumber-junit-output.xml new file mode 100644 index 0000000..f1687e6 --- /dev/null +++ b/src/test/resources/cucumber-junit-output.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + -- 2.51.2 From 7f7fa084740dff0a5920a426a6b3a01199ac909f Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Tue, 29 Aug 2023 17:18:25 +0200 Subject: [PATCH 05/22] =?UTF-8?q?=E2=9C=85=20:=20add=20a=20test=20with=20a?= =?UTF-8?q?=20surefire=20report?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...iteTest.java => TestSuiteParsingTest.java} | 31 +++++++- .../TEST-test.dao.CatalogDaoTest.xml | 71 +++++++++++++++++++ 2 files changed, 100 insertions(+), 2 deletions(-) rename src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/{TestSuiteTest.java => TestSuiteParsingTest.java} (56%) create mode 100644 src/test/resources/TEST-test.dao.CatalogDaoTest.xml diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteParsingTest.java similarity index 56% rename from src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteTest.java rename to src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteParsingTest.java index ad63598..bb7b478 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteParsingTest.java @@ -10,10 +10,10 @@ import java.io.IOException; import static org.assertj.core.api.Assertions.*; -class TestSuiteTest { +class TestSuiteParsingTest { @Test - void testReadXmlJaxb() throws IOException, JAXBException { + void testReadCucumberOuptut() throws IOException, JAXBException { var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); var file = new ClassPathResource("/cucumber-junit-output.xml"); @@ -42,5 +42,32 @@ class TestSuiteTest { assertThat(secondTest.getFailure().get(0).getValue()).contains("java.lang.AssertionError: Element with name 'password_verify' not present"); } + @Test + void testReadSurefireOutput() throws IOException, JAXBException { + var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); + + var file = new ClassPathResource("/TEST-test.dao.CatalogDaoTest.xml"); + + var root = unmarshaller.unmarshal(new StreamSource(file.getInputStream()), TestSuite.class); + var testSuite = root.getValue(); + + assertThat(testSuite.getName()).isEqualTo("test.dao.CatalogDaoTest"); + assertThat(testSuite.getTime()).isEqualTo(0.274f); + assertThat(testSuite.getTests()).isEqualTo("10"); + assertThat(testSuite.getSkipped()).isEqualTo("0"); + assertThat(testSuite.getFailures()).isEqualTo("0"); + assertThat(testSuite.getErrors()).isEqualTo("0"); + assertThat(testSuite.getTestcase()).hasSize(10); + var firstTest = testSuite.getTestcase().get(0); + assertThat(firstTest.getClassname()).isEqualTo("test.dao.CatalogDaoTest"); + assertThat(firstTest.getName()).isEqualTo("test_getArticleCategories_match"); + assertThat(firstTest.getFailure()).isNullOrEmpty(); + + var secondTest = testSuite.getTestcase().get(1); + assertThat(secondTest.getClassname()).isEqualTo("test.dao.CatalogDaoTest"); + assertThat(secondTest.getName()).isEqualTo("test_getCategories"); + assertThat(secondTest.getFailure()).isNullOrEmpty(); + } + } diff --git a/src/test/resources/TEST-test.dao.CatalogDaoTest.xml b/src/test/resources/TEST-test.dao.CatalogDaoTest.xml new file mode 100644 index 0000000..e240909 --- /dev/null +++ b/src/test/resources/TEST-test.dao.CatalogDaoTest.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- 2.51.2 From b2bca0f67e1cb595b9f1c2fb2ad6baffa54420d0 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Tue, 29 Aug 2023 17:21:41 +0200 Subject: [PATCH 06/22] =?UTF-8?q?=F0=9F=9A=9A=20:=20rename=20package=20to?= =?UTF-8?q?=20comply=20with=20java=20conventions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../junit/reports}/ObjectFactory.java | 2 +- .../junit/reports/TestReportParser.java | 19 +++++++++++++++++++ .../junit/reports}/TestSuite.java | 2 +- .../junit/reports}/TestSuiteParsingTest.java | 6 +++--- .../TEST-test.dao.CatalogDaoTest.xml | 0 5 files changed, 24 insertions(+), 5 deletions(-) rename src/main/java/fr/univ_lille/gitlab/classrooms/assignments/{testReports => grading/junit/reports}/ObjectFactory.java (98%) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java rename src/main/java/fr/univ_lille/gitlab/classrooms/assignments/{testReports => grading/junit/reports}/TestSuite.java (99%) rename src/test/java/fr/univ_lille/gitlab/classrooms/assignments/{testReports => grading/junit/reports}/TestSuiteParsingTest.java (95%) rename src/test/resources/{ => junit-reports}/TEST-test.dao.CatalogDaoTest.xml (100%) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/ObjectFactory.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java similarity index 98% rename from src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/ObjectFactory.java rename to src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java index eead971..968ad9c 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/ObjectFactory.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java @@ -1,4 +1,4 @@ -package fr.univ_lille.gitlab.classrooms.assignments.testReports; +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports; import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.annotation.XmlElementDecl; diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java new file mode 100644 index 0000000..82d5cff --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java @@ -0,0 +1,19 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports; + +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import org.springframework.stereotype.Component; + +import javax.xml.transform.stream.StreamSource; +import java.io.InputStream; + +@Component +public class TestReportParser { + + public TestSuite parseTestReport(InputStream inputStream) throws JAXBException { + var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); + var root = unmarshaller.unmarshal(new StreamSource(inputStream), TestSuite.class); + return root.getValue(); + } + +} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuite.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java similarity index 99% rename from src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuite.java rename to src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java index c61b99a..8402f6a 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuite.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java @@ -1,4 +1,4 @@ -package fr.univ_lille.gitlab.classrooms.assignments.testReports; +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports; import java.util.ArrayList; import java.util.List; diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteParsingTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuiteParsingTest.java similarity index 95% rename from src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteParsingTest.java rename to src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuiteParsingTest.java index bb7b478..de75d14 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/testReports/TestSuiteParsingTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuiteParsingTest.java @@ -1,4 +1,4 @@ -package fr.univ_lille.gitlab.classrooms.assignments.testReports; +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; @@ -46,7 +46,7 @@ class TestSuiteParsingTest { void testReadSurefireOutput() throws IOException, JAXBException { var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); - var file = new ClassPathResource("/TEST-test.dao.CatalogDaoTest.xml"); + var file = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml"); var root = unmarshaller.unmarshal(new StreamSource(file.getInputStream()), TestSuite.class); var testSuite = root.getValue(); @@ -69,5 +69,5 @@ class TestSuiteParsingTest { assertThat(secondTest.getName()).isEqualTo("test_getCategories"); assertThat(secondTest.getFailure()).isNullOrEmpty(); } - + } diff --git a/src/test/resources/TEST-test.dao.CatalogDaoTest.xml b/src/test/resources/junit-reports/TEST-test.dao.CatalogDaoTest.xml similarity index 100% rename from src/test/resources/TEST-test.dao.CatalogDaoTest.xml rename to src/test/resources/junit-reports/TEST-test.dao.CatalogDaoTest.xml -- 2.51.2 From 712499ca725e0b64f424323907a5c1931941226c Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:34:11 +0200 Subject: [PATCH 07/22] =?UTF-8?q?=F0=9F=90=9B=20:=20prevent=20a=20NPE=20if?= =?UTF-8?q?=20the=20JWT=20token=20does=20not=20contains=20the=20claim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gitlab/classrooms/users/UserControllerAdvice.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/users/UserControllerAdvice.java b/src/main/java/fr/univ_lille/gitlab/classrooms/users/UserControllerAdvice.java index 693e81e..a6ae203 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/users/UserControllerAdvice.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/users/UserControllerAdvice.java @@ -25,7 +25,7 @@ public class UserControllerAdvice { ClassroomUser classroomUser(Principal authenticationPrincipal){ try{ // if user is a JWTAuthenticationToken, (gitlab id token), load the user using the "user_login" claim - if(authenticationPrincipal instanceof JwtAuthenticationToken jwtToken){ + if(authenticationPrincipal instanceof JwtAuthenticationToken jwtToken && (jwtToken.getTokenAttributes().containsKey("user_login"))){ return this.classroomUserService.getClassroomUser(jwtToken.getTokenAttributes().get("user_login").toString()); } return this.classroomUserService.getClassroomUser(authenticationPrincipal.getName()); -- 2.51.2 From 64ae64f0d15558f683757ccd51b5f65940eeaef3 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:37:39 +0200 Subject: [PATCH 08/22] =?UTF-8?q?=E2=9C=A8=20:=20add=20assignment=20grade?= =?UTF-8?q?=20entity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudentExerciseAssignment.java | 30 +++++++++++++ .../assignments/grading/AssignmentGrade.java | 42 +++++++++++++++++++ .../grading/AssignmentGradeType.java | 5 +++ 3 files changed, 77 insertions(+) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeType.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java index 132e6bb..7bee203 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java @@ -1,7 +1,12 @@ package fr.univ_lille.gitlab.classrooms.assignments; +import fr.univ_lille.gitlab.classrooms.assignments.grading.AssignmentGrade; +import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; +import java.util.HashSet; +import java.util.Set; + @Entity public class StudentExerciseAssignment extends StudentAssignment { @@ -9,6 +14,9 @@ public class StudentExerciseAssignment extends StudentAssignment { private String gitlabProjectUrl; + @ElementCollection + private Set assignmentGrades = new HashSet<>(); + public Long getGitlabProjectId() { return gitlabProjectId; } @@ -25,4 +33,26 @@ public class StudentExerciseAssignment extends StudentAssignment { this.gitlabProjectUrl = gitlabProjectUrl; } + + public Set getAssignmentGrades() { + return assignmentGrades; + } + + public void setAssignmentGrades(Set assignmentGrades) { + this.assignmentGrades = assignmentGrades; + } + + @Override + public Long getScore() { + return this.assignmentGrades.stream() + .mapToLong(AssignmentGrade::getScore) + .sum(); + } + + @Override + public Long getMaxScore() { + return this.assignmentGrades.stream() + .mapToLong(AssignmentGrade::getMaxScore) + .sum(); + } } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java new file mode 100644 index 0000000..943cded --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java @@ -0,0 +1,42 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +import jakarta.persistence.*; + +@Embeddable +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +public abstract class AssignmentGrade { + + @Enumerated(EnumType.STRING) + private AssignmentGradeType type; + + protected AssignmentGrade() { + } + + protected AssignmentGrade(AssignmentGradeType type) { + this.type = type; + } + + public AssignmentGradeType getType() { + return type; + } + + public void setType(AssignmentGradeType type) { + this.type = type; + } + + public abstract int getScore(); + public abstract int getMaxScore(); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AssignmentGrade that)) return false; + + return type == that.type; + } + + @Override + public int hashCode() { + return type.hashCode(); + } +} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeType.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeType.java new file mode 100644 index 0000000..4082025 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeType.java @@ -0,0 +1,5 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +public enum AssignmentGradeType { + JUNIT, +} -- 2.51.2 From 263c70de8da1981275e5f974557e819ab6fbafe3 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:39:07 +0200 Subject: [PATCH 09/22] =?UTF-8?q?=E2=9C=A8=20:=20add=20JUnit=20assignment?= =?UTF-8?q?=20grade=20entity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grading/junit/JUnitAssignmentGrade.java | 42 +++++++ .../grading/junit/JUnitTestSuite.java | 107 ++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java new file mode 100644 index 0000000..ebfe58e --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java @@ -0,0 +1,42 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit; + +import fr.univ_lille.gitlab.classrooms.assignments.grading.AssignmentGrade; +import fr.univ_lille.gitlab.classrooms.assignments.grading.AssignmentGradeType; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embeddable; + +import java.util.HashSet; +import java.util.Set; + +@Embeddable +public class JUnitAssignmentGrade extends AssignmentGrade { + + public JUnitAssignmentGrade() { + super(AssignmentGradeType.JUNIT); + } + + @ElementCollection + private Set testSuites = new HashSet<>(); + + public Set getTestSuites() { + return testSuites; + } + + public void setTestSuites(Set testSuites) { + this.testSuites = testSuites; + } + + @Override + public int getScore() { + return this.testSuites.stream() + .mapToInt(JUnitTestSuite::getScore) + .sum(); + } + + @Override + public int getMaxScore() { + return this.testSuites.stream() + .mapToInt(JUnitTestSuite::getMaxScore) + .sum(); + } +} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java new file mode 100644 index 0000000..cafc800 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java @@ -0,0 +1,107 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit; + +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports.TestSuite; +import jakarta.persistence.Embeddable; + +import java.util.Objects; + +@Embeddable +public class JUnitTestSuite { + + private String name; + + private int tests; + + private int failures; + + private int errors; + + private int skipped; + + /** + * Factory method to build this entity from a TestSuite report parsed from XML + * + * @param testSuiteReport + * @return + */ + public static JUnitTestSuite fromTestSuiteReport(TestSuite testSuiteReport) { + var junitTestSuite = new JUnitTestSuite(); + junitTestSuite.name = testSuiteReport.getName(); + if (testSuiteReport.getTests() != null) { + junitTestSuite.tests = Integer.parseInt(testSuiteReport.getTests()); + } + if (testSuiteReport.getFailures() != null) { + junitTestSuite.failures = Integer.parseInt(testSuiteReport.getFailures()); + } + if (testSuiteReport.getErrors() != null) { + junitTestSuite.errors = Integer.parseInt(testSuiteReport.getErrors()); + } + if (testSuiteReport.getSkipped() != null) { + junitTestSuite.skipped = Integer.parseInt(testSuiteReport.getSkipped()); + } + return junitTestSuite; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getTests() { + return tests; + } + + public void setTests(int tests) { + this.tests = tests; + } + + public int getFailures() { + return failures; + } + + public void setFailures(int failures) { + this.failures = failures; + } + + public int getErrors() { + return errors; + } + + public void setErrors(int errors) { + this.errors = errors; + } + + public int getSkipped() { + return skipped; + } + + public void setSkipped(int skipped) { + this.skipped = skipped; + } + + public int getScore() { + return this.tests - this.failures - this.errors - this.skipped; + } + + public int getMaxScore() { + return this.tests; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + JUnitTestSuite that = (JUnitTestSuite) o; + + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } +} -- 2.51.2 From bb0b067d6d1faab58fbf65ce8604c0eb92ba4a85 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:40:36 +0200 Subject: [PATCH 10/22] =?UTF-8?q?=E2=9C=A8=20:=20grade=20assignements=20wi?= =?UTF-8?q?th=20JUnit=20reports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grading/AssignmentGradeService.java | 11 ++ .../grading/AssignmentGradeServiceImpl.java | 51 ++++++++ .../AssignmentGradeServiceImplTest.java | 109 ++++++++++++++++++ .../TEST-test.model.ModelAttributesTest.xml | 69 +++++++++++ 4 files changed, 240 insertions(+) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java create mode 100644 src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java create mode 100644 src/test/resources/junit-reports/TEST-test.model.ModelAttributesTest.xml diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java new file mode 100644 index 0000000..0ef3d69 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java @@ -0,0 +1,11 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +import fr.univ_lille.gitlab.classrooms.assignments.StudentExerciseAssignment; + +import java.io.InputStream; + +public interface AssignmentGradeService { + + void gradeAssignmentWithJUnitReport(StudentExerciseAssignment studentExerciseAssignment, InputStream inputStream); + +} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java new file mode 100644 index 0000000..d2de011 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java @@ -0,0 +1,51 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +import fr.univ_lille.gitlab.classrooms.assignments.StudentExerciseAssignment; +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.JUnitAssignmentGrade; +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.JUnitTestSuite; +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports.TestReportParser; +import jakarta.transaction.Transactional; +import jakarta.xml.bind.JAXBException; +import org.springframework.stereotype.Service; + +import java.io.InputStream; +import java.time.ZonedDateTime; + +@Service +class AssignmentGradeServiceImpl implements AssignmentGradeService { + + private static final System.Logger LOGGER = System.getLogger(AssignmentGradeServiceImpl.class.getName()); + + private final TestReportParser testReportParser; + + AssignmentGradeServiceImpl(TestReportParser testReportParser) { + this.testReportParser = testReportParser; + } + + @Override + @Transactional + public void gradeAssignmentWithJUnitReport(StudentExerciseAssignment studentExerciseAssignment, InputStream inputStream) { + // parse test suite + try { + var testSuiteReport = testReportParser.parseTestReport(inputStream); + var junitTestSuite = JUnitTestSuite.fromTestSuiteReport(testSuiteReport); + + // get junit assignment grade, or create it + var assignmentGrade = studentExerciseAssignment.getAssignmentGrades().stream() + .filter(it -> it.getType() == AssignmentGradeType.JUNIT) + .findFirst() + .orElse(new JUnitAssignmentGrade()); + + // add parsed suite to current grade + var jUnitAssignmentGrade = ((JUnitAssignmentGrade) assignmentGrade); + jUnitAssignmentGrade.getTestSuites().add(junitTestSuite); + + studentExerciseAssignment.getAssignmentGrades().add(assignmentGrade); + + // update the submission date + studentExerciseAssignment.setSubmissionDate(ZonedDateTime.now()); + } catch (JAXBException e) { + LOGGER.log(System.Logger.Level.ERROR, "Could parse JUnit Report"); + } + } +} diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java new file mode 100644 index 0000000..1e6ab10 --- /dev/null +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java @@ -0,0 +1,109 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +import fr.univ_lille.gitlab.classrooms.assignments.StudentExerciseAssignment; +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.JUnitAssignmentGrade; +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports.TestReportParser; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.io.ClassPathResource; + +import java.io.IOException; +import java.time.ZonedDateTime; + +import static org.assertj.core.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) +class AssignmentGradeServiceImplTest { + + @InjectMocks + private AssignmentGradeServiceImpl assignmentGradeService; + + @Spy + private TestReportParser testReportParser = new TestReportParser(); + + @Test + void testGradeAssignmentWithJUnitReport() throws IOException { + var studentExerciseAssignment = new StudentExerciseAssignment(); + + var reportInputStream = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml").getInputStream(); + + assignmentGradeService.gradeAssignmentWithJUnitReport(studentExerciseAssignment, reportInputStream); + + assertThat(studentExerciseAssignment.getAssignmentGrades()) + .isNotEmpty() + .hasSize(1); + + var assignmentGrade = studentExerciseAssignment.getAssignmentGrades().stream().findFirst().get(); + assertThat(assignmentGrade) + .isNotNull() + .isInstanceOf(JUnitAssignmentGrade.class); + var junitAssignmentGrade = ((JUnitAssignmentGrade) assignmentGrade); + + assertThat(junitAssignmentGrade.getTestSuites()) + .isNotEmpty() + .hasSize(1); + + var testSuite = junitAssignmentGrade.getTestSuites().stream().findFirst().get(); + assertThat(testSuite.getName()).isEqualTo("test.dao.CatalogDaoTest"); + assertThat(testSuite.getTests()).isEqualTo(10); + assertThat(testSuite.getFailures()).isZero(); + assertThat(testSuite.getErrors()).isZero(); + assertThat(testSuite.getSkipped()).isZero(); + + assertThat(studentExerciseAssignment.getSubmissionDate()).isEqualToIgnoringSeconds(ZonedDateTime.now()); + assertThat(studentExerciseAssignment.getScore()).isEqualTo(10); + assertThat(studentExerciseAssignment.getMaxScore()).isEqualTo(10); + } + + @Test + void testGradeAssignmentWithMultipleJUnitReports() throws IOException { + var studentExerciseAssignment = new StudentExerciseAssignment(); + + var firstReportInputStream = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml").getInputStream(); + var secondReportInputStream = new ClassPathResource("/junit-reports/TEST-test.model.ModelAttributesTest.xml").getInputStream(); + + assignmentGradeService.gradeAssignmentWithJUnitReport(studentExerciseAssignment, firstReportInputStream); + assignmentGradeService.gradeAssignmentWithJUnitReport(studentExerciseAssignment, secondReportInputStream); + + assertThat(studentExerciseAssignment.getSubmissionDate()).isEqualToIgnoringSeconds(ZonedDateTime.now()); + assertThat(studentExerciseAssignment.getScore()).isEqualTo(18); + assertThat(studentExerciseAssignment.getMaxScore()).isEqualTo(18); + } + + @Test + void testGradeAssignmentWithJUnitCucumberReport() throws IOException { + var studentExerciseAssignment = new StudentExerciseAssignment(); + + var reportInputStream = new ClassPathResource("/cucumber-junit-output.xml").getInputStream(); + + assignmentGradeService.gradeAssignmentWithJUnitReport(studentExerciseAssignment, reportInputStream); + + assertThat(studentExerciseAssignment.getAssignmentGrades()) + .isNotEmpty() + .hasSize(1); + + var assignmentGrade = studentExerciseAssignment.getAssignmentGrades().stream().findFirst().get(); + assertThat(assignmentGrade) + .isNotNull() + .isInstanceOf(JUnitAssignmentGrade.class); + var junitAssignmentGrade = ((JUnitAssignmentGrade) assignmentGrade); + + assertThat(junitAssignmentGrade.getTestSuites()) + .isNotEmpty() + .hasSize(1); + + var testSuite = junitAssignmentGrade.getTestSuites().stream().findFirst().get(); + assertThat(testSuite.getName()).isEqualTo("Cucumber"); + assertThat(testSuite.getTests()).isEqualTo(2); + assertThat(testSuite.getFailures()).isOne(); + assertThat(testSuite.getErrors()).isZero(); + assertThat(testSuite.getSkipped()).isZero(); + + assertThat(studentExerciseAssignment.getSubmissionDate()).isEqualToIgnoringSeconds(ZonedDateTime.now()); + assertThat(studentExerciseAssignment.getScore()).isEqualTo(1); + assertThat(studentExerciseAssignment.getMaxScore()).isEqualTo(2); + } +} diff --git a/src/test/resources/junit-reports/TEST-test.model.ModelAttributesTest.xml b/src/test/resources/junit-reports/TEST-test.model.ModelAttributesTest.xml new file mode 100644 index 0000000..3773c0c --- /dev/null +++ b/src/test/resources/junit-reports/TEST-test.model.ModelAttributesTest.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.51.2 From 99d99b10b86e683c2ff66e431f3d97a20fa0a102 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:41:25 +0200 Subject: [PATCH 11/22] =?UTF-8?q?=E2=9C=A8=20:=20load=20student=20assignme?= =?UTF-8?q?nts=20using=20gitlab=20project=20id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assignments/StudentAssignmentService.java | 16 +++++++++ .../StudentAssignmentServiceImpl.java | 25 ++++++++++++++ .../StudentExerciceAssignmentRepository.java | 11 ++++++ .../StudentAssignmentServiceImplTest.java | 34 +++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentService.java create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImpl.java create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciceAssignmentRepository.java create mode 100644 src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImplTest.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentService.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentService.java new file mode 100644 index 0000000..d5665a8 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentService.java @@ -0,0 +1,16 @@ +package fr.univ_lille.gitlab.classrooms.assignments; + +import java.util.Optional; + +public interface StudentAssignmentService { + + /** + * Gets an assignment from its Gitlab Project id + * + * @param gitlabProjectId + * @return + */ + Optional getByGitlabProjectId(long gitlabProjectId); + + void save(StudentExerciseAssignment exerciseAssignment); +} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImpl.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImpl.java new file mode 100644 index 0000000..5fcfbac --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImpl.java @@ -0,0 +1,25 @@ +package fr.univ_lille.gitlab.classrooms.assignments; + +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +class StudentAssignmentServiceImpl implements StudentAssignmentService { + + private final StudentExerciceAssignmentRepository studentExerciceAssignmentRepository; + + StudentAssignmentServiceImpl(StudentExerciceAssignmentRepository studentExerciceAssignmentRepository) { + this.studentExerciceAssignmentRepository = studentExerciceAssignmentRepository; + } + + @Override + public Optional getByGitlabProjectId(long gitlabProjectId) { + return this.studentExerciceAssignmentRepository.findByGitlabProjectId(gitlabProjectId); + } + + @Override + public void save(StudentExerciseAssignment exerciseAssignment) { + this.studentExerciceAssignmentRepository.save(exerciseAssignment); + } +} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciceAssignmentRepository.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciceAssignmentRepository.java new file mode 100644 index 0000000..ced58ff --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciceAssignmentRepository.java @@ -0,0 +1,11 @@ +package fr.univ_lille.gitlab.classrooms.assignments; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; +import java.util.UUID; + +interface StudentExerciceAssignmentRepository extends JpaRepository { + + Optional findByGitlabProjectId(Long gitlabProjectId); +} diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImplTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImplTest.java new file mode 100644 index 0000000..5714ff4 --- /dev/null +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentServiceImplTest.java @@ -0,0 +1,34 @@ +package fr.univ_lille.gitlab.classrooms.assignments; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class StudentAssignmentServiceImplTest { + + @InjectMocks + private StudentAssignmentServiceImpl studentAssignmentService; + + @Mock + private StudentExerciceAssignmentRepository studentExerciceAssignmentRepository; + + @Test + void getByGitlabProjectId() { + this.studentAssignmentService.getByGitlabProjectId(12); + + verify(this.studentExerciceAssignmentRepository).findByGitlabProjectId(12L); + } + + @Test + void save() { + var exercise = new StudentExerciseAssignment(); + this.studentAssignmentService.save(exercise); + + verify(this.studentExerciceAssignmentRepository).save(exercise); + } +} -- 2.51.2 From 5971f489f80de978d4e9df7f81b10df2ae3d6949 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:42:37 +0200 Subject: [PATCH 12/22] =?UTF-8?q?=E2=9C=A8=20:=20expose=20submit=20junit?= =?UTF-8?q?=20report=20endpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grading/AssignmentGradingController.java | 58 +++++++++ .../AssignmentGradingControllerMVCTest.java | 112 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java create mode 100644 src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingControllerMVCTest.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java new file mode 100644 index 0000000..607ee7b --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java @@ -0,0 +1,58 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +import fr.univ_lille.gitlab.classrooms.assignments.StudentAssignmentService; +import fr.univ_lille.gitlab.classrooms.users.ClassroomUser; +import org.springframework.http.HttpStatus; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ResponseStatusException; + +import java.io.IOException; +import java.security.Principal; + +@RestController +@RequestMapping("/api/assignments/") +class AssignmentGradingController { + + private final StudentAssignmentService studentAssignmentService; + + private final AssignmentGradeService assignmentGradeService; + + AssignmentGradingController(StudentAssignmentService studentAssignmentService, AssignmentGradeService assignmentGradeService) { + this.studentAssignmentService = studentAssignmentService; + this.assignmentGradeService = assignmentGradeService; + } + + /** + * Submits a JUnit report file to an assignment for grading. + * Multiple different JUnit reports can be submitted and will be added to the grade. + * @param authenticationPrincipal The principal MUST be a Gitlab ID Token, to identify the Gitlab Project ID + * @param student The student submitting its assignment, computed from the token in {@link fr.univ_lille.gitlab.classrooms.users.UserControllerAdvice} + * @param testResultsFile The XML test result file, in the JUnit format + * @throws IOException if the XML test result file cannot be read + */ + @PostMapping("/submit/junit") + void submitAssignment(Principal authenticationPrincipal, + @ModelAttribute("user") ClassroomUser student, + @RequestParam("file") MultipartFile testResultsFile) throws IOException { + // this ressource only works with gitlab id token authentication + if (!(authenticationPrincipal instanceof JwtAuthenticationToken jwtToken)) { + throw new ResponseStatusException(HttpStatus.FORBIDDEN); + } + // get the gitlab project id from the authentication token + if(! jwtToken.getTokenAttributes().containsKey("project_id")){ + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + var gitlabProjectId = Long.parseLong(jwtToken.getTokenAttributes().get("project_id").toString()); + + // find the associated exercise assignment + var exerciseAssignment = this.studentAssignmentService.getByGitlabProjectId(gitlabProjectId) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + + // grade using the test report + this.assignmentGradeService.gradeAssignmentWithJUnitReport(exerciseAssignment, testResultsFile.getInputStream()); + + this.studentAssignmentService.save(exerciseAssignment); + } +} diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingControllerMVCTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingControllerMVCTest.java new file mode 100644 index 0000000..8fff8d0 --- /dev/null +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingControllerMVCTest.java @@ -0,0 +1,112 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +import fr.univ_lille.gitlab.classrooms.assignments.ExerciseAssignment; +import fr.univ_lille.gitlab.classrooms.assignments.QuizAssignment; +import fr.univ_lille.gitlab.classrooms.assignments.StudentAssignmentService; +import fr.univ_lille.gitlab.classrooms.assignments.StudentExerciseAssignment; +import fr.univ_lille.gitlab.classrooms.classrooms.Classroom; +import fr.univ_lille.gitlab.classrooms.quiz.QuizEntity; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.core.io.ClassPathResource; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Sql("/sql/init-test-users.sql") +class AssignmentGradingControllerMVCTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private StudentAssignmentService studentAssignmentService; + + @MockBean + private AssignmentGradeService assignmentGradeService; + + @BeforeEach + void setUp() { + } + + @Test + void submitJunit_shouldReturn403_whenNoAuth() throws Exception { + mockMvc.perform(post("/api/assignments/submit/junit")) + .andExpect(status().is4xxClientError()) + .andExpect(status().is(403)); + } + + @Test + void submitJunit_shouldReturn404_whenNoProjectIdCanBeFound() throws Exception { + var reportFile = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml"); + var mockMultipartFile = new MockMultipartFile("file", reportFile.getInputStream()); + + mockMvc.perform( + multipart("/api/assignments/submit/junit") + .file(mockMultipartFile) + .with(jwt()) + ) + .andExpect(status().is4xxClientError()) + .andExpect(status().is(404)); + } + + @Test + void submitJunit_shouldReturn404_whenNoProjectCanBeFound() throws Exception { + var reportFile = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml"); + var mockMultipartFile = new MockMultipartFile("file", reportFile.getInputStream()); + + when(studentAssignmentService.getByGitlabProjectId(12)).thenReturn(Optional.empty()); + + mockMvc.perform( + multipart("/api/assignments/submit/junit") + .file(mockMultipartFile) + .with(jwt().jwt(builder -> builder.claim("project_id", 12))) + ) + .andExpect(status().is4xxClientError()) + .andExpect(status().is(404)); + } + + @Test + void submitJunit_shouldReturn200_whenProjectIsSuccessfullyGraded() throws Exception { + var reportInputStream = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml").getInputStream(); + var mockMultipartFile = new MockMultipartFile("file", reportInputStream); + + var studentExerciseAssignment = new StudentExerciseAssignment(); + + when(studentAssignmentService.getByGitlabProjectId(12)).thenReturn(Optional.of(studentExerciseAssignment)); + + mockMvc.perform( + multipart("/api/assignments/submit/junit") + .file(mockMultipartFile) + .with(jwt().jwt(builder -> builder.claim("project_id", 12))) + ) + .andExpect(status().is2xxSuccessful()) + .andExpect(status().is(200)); + + verify(assignmentGradeService).gradeAssignmentWithJUnitReport(eq(studentExerciseAssignment), any()); + verify(studentAssignmentService).save(studentExerciseAssignment); + } + +} -- 2.51.2 From b378d95b4c6b291a90a0ac5199c4ba4c45f3884f Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:49:51 +0200 Subject: [PATCH 13/22] =?UTF-8?q?=E2=99=BB=20:=20cleanup=20JAXB=20Object?= =?UTF-8?q?=20Factory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grading/junit/reports/ObjectFactory.java | 103 +----------------- 1 file changed, 4 insertions(+), 99 deletions(-) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java index 968ad9c..d65c87e 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java @@ -23,103 +23,8 @@ import javax.xml.namespace.QName; @XmlRegistry public class ObjectFactory { - private final static QName _TestSuiteTestcaseSkipped_QNAME = new QName("", "skipped"); - private final static QName _TestSuiteTestcaseError_QNAME = new QName("", "error"); - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: generated - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link TestSuite } - * - */ - public TestSuite createTestSuite() { - return new TestSuite(); - } - - /** - * Create an instance of {@link TestSuite.Testcase } - * - */ - public TestSuite.Testcase createTestSuiteTestcase() { - return new TestSuite.Testcase(); - } - - /** - * Create an instance of {@link TestSuite.Properties } - * - */ - public TestSuite.Properties createTestSuiteProperties() { - return new TestSuite.Properties(); - } - - /** - * Create an instance of {@link TestSuite.Testcase.Failure } - * - */ - public TestSuite.Testcase.Failure createTestSuiteTestcaseFailure() { - return new TestSuite.Testcase.Failure(); - } - - /** - * Create an instance of {@link TestSuite.Testcase.RerunFailure } - * - */ - public TestSuite.Testcase.RerunFailure createTestSuiteTestcaseRerunFailure() { - return new TestSuite.Testcase.RerunFailure(); - } - - /** - * Create an instance of {@link TestSuite.Testcase.FlakyFailure } - * - */ - public TestSuite.Testcase.FlakyFailure createTestSuiteTestcaseFlakyFailure() { - return new TestSuite.Testcase.FlakyFailure(); - } - - /** - * Create an instance of {@link TestSuite.Testcase.Skipped } - * - */ - public TestSuite.Testcase.Skipped createTestSuiteTestcaseSkipped() { - return new TestSuite.Testcase.Skipped(); - } - - /** - * Create an instance of {@link TestSuite.Testcase.Error } - * - */ - public TestSuite.Testcase.Error createTestSuiteTestcaseError() { - return new TestSuite.Testcase.Error(); - } - - /** - * Create an instance of {@link TestSuite.Testcase.RerunError } - * - */ - public TestSuite.Testcase.RerunError createTestSuiteTestcaseRerunError() { - return new TestSuite.Testcase.RerunError(); - } - - /** - * Create an instance of {@link TestSuite.Testcase.FlakyError } - * - */ - public TestSuite.Testcase.FlakyError createTestSuiteTestcaseFlakyError() { - return new TestSuite.Testcase.FlakyError(); - } - - /** - * Create an instance of {@link TestSuite.Properties.Property } - * - */ - public TestSuite.Properties.Property createTestSuitePropertiesProperty() { - return new TestSuite.Properties.Property(); - } + private static final QName _TestSuiteTestcaseSkipped_QNAME = new QName("", "skipped"); + private static final QName _TestSuiteTestcaseError_QNAME = new QName("", "error"); /** * Create an instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Skipped }{@code >} @@ -131,7 +36,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "", name = "skipped", scope = TestSuite.Testcase.class) public JAXBElement createTestSuiteTestcaseSkipped(TestSuite.Testcase.Skipped value) { - return new JAXBElement(_TestSuiteTestcaseSkipped_QNAME, TestSuite.Testcase.Skipped.class, TestSuite.Testcase.class, value); + return new JAXBElement<>(_TestSuiteTestcaseSkipped_QNAME, TestSuite.Testcase.Skipped.class, TestSuite.Testcase.class, value); } /** @@ -144,7 +49,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "", name = "error", scope = TestSuite.Testcase.class) public JAXBElement createTestSuiteTestcaseError(TestSuite.Testcase.Error value) { - return new JAXBElement(_TestSuiteTestcaseError_QNAME, TestSuite.Testcase.Error.class, TestSuite.Testcase.class, value); + return new JAXBElement<>(_TestSuiteTestcaseError_QNAME, TestSuite.Testcase.Error.class, TestSuite.Testcase.class, value); } } -- 2.51.2 From 30611ccb96e171cef8a325ca563162899c5ccee9 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 11:51:03 +0200 Subject: [PATCH 14/22] =?UTF-8?q?=E2=99=BB=20:=20cleanup=20JAXB=20TestSuit?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grading/junit/reports/TestSuite.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java index 8402f6a..ab7a2df 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java @@ -215,7 +215,7 @@ public class TestSuite { */ public List getProperties() { if (properties == null) { - properties = new ArrayList(); + properties = new ArrayList<>(); } return this.properties; } @@ -244,7 +244,7 @@ public class TestSuite { */ public List getTestcase() { if (testcase == null) { - testcase = new ArrayList(); + testcase = new ArrayList<>(); } return this.testcase; } @@ -502,7 +502,7 @@ public class TestSuite { */ public List getProperty() { if (property == null) { - property = new ArrayList(); + property = new ArrayList<>(); } return this.property; } @@ -762,7 +762,7 @@ public class TestSuite { */ public List getFailure() { if (failure == null) { - failure = new ArrayList(); + failure = new ArrayList<>(); } return this.failure; } @@ -791,7 +791,7 @@ public class TestSuite { */ public List getRerunFailure() { if (rerunFailure == null) { - rerunFailure = new ArrayList(); + rerunFailure = new ArrayList<>(); } return this.rerunFailure; } @@ -820,7 +820,7 @@ public class TestSuite { */ public List getFlakyFailure() { if (flakyFailure == null) { - flakyFailure = new ArrayList(); + flakyFailure = new ArrayList<>(); } return this.flakyFailure; } @@ -897,7 +897,7 @@ public class TestSuite { */ public List getRerunError() { if (rerunError == null) { - rerunError = new ArrayList(); + rerunError = new ArrayList<>(); } return this.rerunError; } @@ -926,7 +926,7 @@ public class TestSuite { */ public List getFlakyError() { if (flakyError == null) { - flakyError = new ArrayList(); + flakyError = new ArrayList<>(); } return this.flakyError; } -- 2.51.2 From f3c53c2fb93c9d95aae24d0b7053debdbea71a82 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 14:59:49 +0200 Subject: [PATCH 15/22] =?UTF-8?q?=E2=9C=A8=20:=20generate=20JAXB=20classes?= =?UTF-8?q?=20on=20build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 39 + .../grading/junit/JUnitTestSuite.java | 4 +- .../grading/junit/reports/ObjectFactory.java | 55 - .../junit/reports/TestReportParser.java | 6 +- .../grading/junit/reports/TestSuite.java | 2023 ----------------- .../junit/reports/TestSuiteParsingTest.java | 8 +- 6 files changed, 48 insertions(+), 2087 deletions(-) delete mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java delete mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java diff --git a/pom.xml b/pom.xml index 474e5da..d7592cb 100644 --- a/pom.xml +++ b/pom.xml @@ -121,6 +121,45 @@ org.springframework.boot spring-boot-maven-plugin + + + org.codehaus.mojo + jaxb2-maven-plugin + 3.1.0 + + + xjc + + xjc + + + + + + src/main/resources/surefire-test-report.xsd + + fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.4.0 + + + add-jaxb-sources + + add-source + + + + + + target/generated-sources/jaxb + + + org.jacoco jacoco-maven-plugin diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java index cafc800..ad66b61 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuite.java @@ -1,6 +1,6 @@ package fr.univ_lille.gitlab.classrooms.assignments.grading.junit; -import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports.TestSuite; +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports.Testsuite; import jakarta.persistence.Embeddable; import java.util.Objects; @@ -24,7 +24,7 @@ public class JUnitTestSuite { * @param testSuiteReport * @return */ - public static JUnitTestSuite fromTestSuiteReport(TestSuite testSuiteReport) { + public static JUnitTestSuite fromTestSuiteReport(Testsuite testSuiteReport) { var junitTestSuite = new JUnitTestSuite(); junitTestSuite.name = testSuiteReport.getName(); if (testSuiteReport.getTests() != null) { diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java deleted file mode 100644 index d65c87e..0000000 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/ObjectFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports; - -import jakarta.xml.bind.JAXBElement; -import jakarta.xml.bind.annotation.XmlElementDecl; -import jakarta.xml.bind.annotation.XmlRegistry; -import javax.xml.namespace.QName; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the generated package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - private static final QName _TestSuiteTestcaseSkipped_QNAME = new QName("", "skipped"); - private static final QName _TestSuiteTestcaseError_QNAME = new QName("", "error"); - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Skipped }{@code >} - * - * @param value - * Java instance representing xml element's value. - * @return - * the new instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Skipped }{@code >} - */ - @XmlElementDecl(namespace = "", name = "skipped", scope = TestSuite.Testcase.class) - public JAXBElement createTestSuiteTestcaseSkipped(TestSuite.Testcase.Skipped value) { - return new JAXBElement<>(_TestSuiteTestcaseSkipped_QNAME, TestSuite.Testcase.Skipped.class, TestSuite.Testcase.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Error }{@code >} - * - * @param value - * Java instance representing xml element's value. - * @return - * the new instance of {@link JAXBElement }{@code <}{@link TestSuite.Testcase.Error }{@code >} - */ - @XmlElementDecl(namespace = "", name = "error", scope = TestSuite.Testcase.class) - public JAXBElement createTestSuiteTestcaseError(TestSuite.Testcase.Error value) { - return new JAXBElement<>(_TestSuiteTestcaseError_QNAME, TestSuite.Testcase.Error.class, TestSuite.Testcase.class, value); - } - -} diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java index 82d5cff..a3d608e 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestReportParser.java @@ -10,9 +10,9 @@ import java.io.InputStream; @Component public class TestReportParser { - public TestSuite parseTestReport(InputStream inputStream) throws JAXBException { - var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); - var root = unmarshaller.unmarshal(new StreamSource(inputStream), TestSuite.class); + public Testsuite parseTestReport(InputStream inputStream) throws JAXBException { + var unmarshaller = JAXBContext.newInstance(Testsuite.class).createUnmarshaller(); + var root = unmarshaller.unmarshal(new StreamSource(inputStream), Testsuite.class); return root.getValue(); } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java deleted file mode 100644 index ab7a2df..0000000 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuite.java +++ /dev/null @@ -1,2023 +0,0 @@ -package fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports; - -import java.util.ArrayList; -import java.util.List; -import jakarta.xml.bind.JAXBElement; -import jakarta.xml.bind.annotation.XmlAccessType; -import jakarta.xml.bind.annotation.XmlAccessorType; -import jakarta.xml.bind.annotation.XmlAttribute; -import jakarta.xml.bind.annotation.XmlElement; -import jakarta.xml.bind.annotation.XmlElementRef; -import jakarta.xml.bind.annotation.XmlRootElement; -import jakarta.xml.bind.annotation.XmlType; -import jakarta.xml.bind.annotation.XmlValue; - - -/** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType>
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="properties" maxOccurs="unbounded" minOccurs="0">
- *           <complexType>
- *             <complexContent>
- *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                 <sequence>
- *                   <element name="property" maxOccurs="unbounded" minOccurs="0">
- *                     <complexType>
- *                       <complexContent>
- *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                           <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                           <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </restriction>
- *                       </complexContent>
- *                     </complexType>
- *                   </element>
- *                 </sequence>
- *               </restriction>
- *             </complexContent>
- *           </complexType>
- *         </element>
- *         <element name="testcase" maxOccurs="unbounded" minOccurs="0">
- *           <complexType>
- *             <complexContent>
- *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                 <sequence>
- *                   <element name="failure" maxOccurs="unbounded" minOccurs="0">
- *                     <complexType>
- *                       <simpleContent>
- *                         <extension base="<http://www.w3.org/2001/XMLSchema>string">
- *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </extension>
- *                       </simpleContent>
- *                     </complexType>
- *                   </element>
- *                   <element name="rerunFailure" maxOccurs="unbounded" minOccurs="0">
- *                     <complexType>
- *                       <complexContent>
- *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                           <sequence>
- *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                           </sequence>
- *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </restriction>
- *                       </complexContent>
- *                     </complexType>
- *                   </element>
- *                   <element name="flakyFailure" maxOccurs="unbounded" minOccurs="0">
- *                     <complexType>
- *                       <complexContent>
- *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                           <sequence>
- *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                           </sequence>
- *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </restriction>
- *                       </complexContent>
- *                     </complexType>
- *                   </element>
- *                   <element name="skipped" minOccurs="0">
- *                     <complexType>
- *                       <simpleContent>
- *                         <extension base="<http://www.w3.org/2001/XMLSchema>string">
- *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </extension>
- *                       </simpleContent>
- *                     </complexType>
- *                   </element>
- *                   <element name="error" minOccurs="0">
- *                     <complexType>
- *                       <simpleContent>
- *                         <extension base="<http://www.w3.org/2001/XMLSchema>string">
- *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </extension>
- *                       </simpleContent>
- *                     </complexType>
- *                   </element>
- *                   <element name="rerunError" maxOccurs="unbounded" minOccurs="0">
- *                     <complexType>
- *                       <complexContent>
- *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                           <sequence>
- *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                           </sequence>
- *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </restriction>
- *                       </complexContent>
- *                     </complexType>
- *                   </element>
- *                   <element name="flakyError" maxOccurs="unbounded" minOccurs="0">
- *                     <complexType>
- *                       <complexContent>
- *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                           <sequence>
- *                             <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *                             <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                             <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                           </sequence>
- *                           <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                           <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                         </restriction>
- *                       </complexContent>
- *                     </complexType>
- *                   </element>
- *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *                 </sequence>
- *                 <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                 <attribute name="classname" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                 <attribute name="group" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                 <attribute name="time" use="required" type="{http://www.w3.org/2001/XMLSchema}float" />
- *               </restriction>
- *             </complexContent>
- *           </complexType>
- *         </element>
- *       </sequence>
- *       <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="time" type="{http://www.w3.org/2001/XMLSchema}float" />
- *       <attribute name="tests" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="errors" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="skipped" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="failures" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="group" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = { - "properties", - "testcase" -}) -@XmlRootElement(name = "testsuite") -public class TestSuite { - - protected List properties; - protected List testcase; - @XmlAttribute(name = "version") - protected String version; - @XmlAttribute(name = "name", required = true) - protected String name; - @XmlAttribute(name = "time") - protected Float time; - @XmlAttribute(name = "tests", required = true) - protected String tests; - @XmlAttribute(name = "errors", required = true) - protected String errors; - @XmlAttribute(name = "skipped", required = true) - protected String skipped; - @XmlAttribute(name = "failures", required = true) - protected String failures; - @XmlAttribute(name = "group") - protected String group; - - /** - * Gets the value of the properties property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the properties property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getProperties().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link Properties } - * - * - */ - public List getProperties() { - if (properties == null) { - properties = new ArrayList<>(); - } - return this.properties; - } - - /** - * Gets the value of the testcase property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the testcase property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getTestcase().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link Testcase } - * - * - */ - public List getTestcase() { - if (testcase == null) { - testcase = new ArrayList<>(); - } - return this.testcase; - } - - /** - * Gets the value of the version property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getVersion() { - return version; - } - - /** - * Sets the value of the version property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setVersion(String value) { - this.version = value; - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - /** - * Gets the value of the time property. - * - * @return - * possible object is - * {@link Float } - * - */ - public Float getTime() { - return time; - } - - /** - * Sets the value of the time property. - * - * @param value - * allowed object is - * {@link Float } - * - */ - public void setTime(Float value) { - this.time = value; - } - - /** - * Gets the value of the tests property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getTests() { - return tests; - } - - /** - * Sets the value of the tests property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setTests(String value) { - this.tests = value; - } - - /** - * Gets the value of the errors property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getErrors() { - return errors; - } - - /** - * Sets the value of the errors property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setErrors(String value) { - this.errors = value; - } - - /** - * Gets the value of the skipped property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSkipped() { - return skipped; - } - - /** - * Sets the value of the skipped property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSkipped(String value) { - this.skipped = value; - } - - /** - * Gets the value of the failures property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getFailures() { - return failures; - } - - /** - * Sets the value of the failures property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setFailures(String value) { - this.failures = value; - } - - /** - * Gets the value of the group property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGroup() { - return group; - } - - /** - * Sets the value of the group property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGroup(String value) { - this.group = value; - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <sequence>
-     *         <element name="property" maxOccurs="unbounded" minOccurs="0">
-     *           <complexType>
-     *             <complexContent>
-     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *                 <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *                 <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </restriction>
-     *             </complexContent>
-     *           </complexType>
-     *         </element>
-     *       </sequence>
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "property" - }) - public static class Properties { - - protected List property; - - /** - * Gets the value of the property property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the property property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getProperty().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link Property } - * - * - */ - public List getProperty() { - if (property == null) { - property = new ArrayList<>(); - } - return this.property; - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <complexContent>
-         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-         *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *       <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </restriction>
-         *   </complexContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "") - public static class Property { - - @XmlAttribute(name = "name", required = true) - protected String name; - @XmlAttribute(name = "value", required = true) - protected String value; - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - /** - * Gets the value of the value property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getValue() { - return value; - } - - /** - * Sets the value of the value property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setValue(String value) { - this.value = value; - } - - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <sequence>
-     *         <element name="failure" maxOccurs="unbounded" minOccurs="0">
-     *           <complexType>
-     *             <simpleContent>
-     *               <extension base="<http://www.w3.org/2001/XMLSchema>string">
-     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </extension>
-     *             </simpleContent>
-     *           </complexType>
-     *         </element>
-     *         <element name="rerunFailure" maxOccurs="unbounded" minOccurs="0">
-     *           <complexType>
-     *             <complexContent>
-     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *                 <sequence>
-     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                 </sequence>
-     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </restriction>
-     *             </complexContent>
-     *           </complexType>
-     *         </element>
-     *         <element name="flakyFailure" maxOccurs="unbounded" minOccurs="0">
-     *           <complexType>
-     *             <complexContent>
-     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *                 <sequence>
-     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                 </sequence>
-     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </restriction>
-     *             </complexContent>
-     *           </complexType>
-     *         </element>
-     *         <element name="skipped" minOccurs="0">
-     *           <complexType>
-     *             <simpleContent>
-     *               <extension base="<http://www.w3.org/2001/XMLSchema>string">
-     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </extension>
-     *             </simpleContent>
-     *           </complexType>
-     *         </element>
-     *         <element name="error" minOccurs="0">
-     *           <complexType>
-     *             <simpleContent>
-     *               <extension base="<http://www.w3.org/2001/XMLSchema>string">
-     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </extension>
-     *             </simpleContent>
-     *           </complexType>
-     *         </element>
-     *         <element name="rerunError" maxOccurs="unbounded" minOccurs="0">
-     *           <complexType>
-     *             <complexContent>
-     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *                 <sequence>
-     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                 </sequence>
-     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </restriction>
-     *             </complexContent>
-     *           </complexType>
-     *         </element>
-     *         <element name="flakyError" maxOccurs="unbounded" minOccurs="0">
-     *           <complexType>
-     *             <complexContent>
-     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *                 <sequence>
-     *                   <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-     *                   <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                   <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *                 </sequence>
-     *                 <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *                 <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *               </restriction>
-     *             </complexContent>
-     *           </complexType>
-     *         </element>
-     *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-     *       </sequence>
-     *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *       <attribute name="classname" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *       <attribute name="group" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *       <attribute name="time" use="required" type="{http://www.w3.org/2001/XMLSchema}float" />
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "failure", - "rerunFailure", - "flakyFailure", - "skipped", - "error", - "rerunError", - "flakyError", - "systemOut", - "systemErr" - }) - public static class Testcase { - - @XmlElement(nillable = true) - protected List failure; - protected List rerunFailure; - protected List flakyFailure; - @XmlElementRef(name = "skipped", type = JAXBElement.class, required = false) - protected JAXBElement skipped; - @XmlElementRef(name = "error", type = JAXBElement.class, required = false) - protected JAXBElement error; - protected List rerunError; - protected List flakyError; - @XmlElement(name = "system-out") - protected String systemOut; - @XmlElement(name = "system-err") - protected String systemErr; - @XmlAttribute(name = "name", required = true) - protected String name; - @XmlAttribute(name = "classname") - protected String classname; - @XmlAttribute(name = "group") - protected String group; - @XmlAttribute(name = "time", required = true) - protected float time; - - /** - * Gets the value of the failure property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the failure property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getFailure().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link Failure } - * - * - */ - public List getFailure() { - if (failure == null) { - failure = new ArrayList<>(); - } - return this.failure; - } - - /** - * Gets the value of the rerunFailure property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the rerunFailure property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getRerunFailure().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link RerunFailure } - * - * - */ - public List getRerunFailure() { - if (rerunFailure == null) { - rerunFailure = new ArrayList<>(); - } - return this.rerunFailure; - } - - /** - * Gets the value of the flakyFailure property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the flakyFailure property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getFlakyFailure().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link FlakyFailure } - * - * - */ - public List getFlakyFailure() { - if (flakyFailure == null) { - flakyFailure = new ArrayList<>(); - } - return this.flakyFailure; - } - - /** - * Gets the value of the skipped property. - * - * @return - * possible object is - * {@link JAXBElement }{@code <}{@link Skipped }{@code >} - * - */ - public JAXBElement getSkipped() { - return skipped; - } - - /** - * Sets the value of the skipped property. - * - * @param value - * allowed object is - * {@link JAXBElement }{@code <}{@link Skipped }{@code >} - * - */ - public void setSkipped(JAXBElement value) { - this.skipped = value; - } - - /** - * Gets the value of the error property. - * - * @return - * possible object is - * {@link JAXBElement }{@code <}{@link Error }{@code >} - * - */ - public JAXBElement getError() { - return error; - } - - /** - * Sets the value of the error property. - * - * @param value - * allowed object is - * {@link JAXBElement }{@code <}{@link Error }{@code >} - * - */ - public void setError(JAXBElement value) { - this.error = value; - } - - /** - * Gets the value of the rerunError property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the rerunError property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getRerunError().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link RerunError } - * - * - */ - public List getRerunError() { - if (rerunError == null) { - rerunError = new ArrayList<>(); - } - return this.rerunError; - } - - /** - * Gets the value of the flakyError property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the flakyError property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getFlakyError().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link FlakyError } - * - * - */ - public List getFlakyError() { - if (flakyError == null) { - flakyError = new ArrayList<>(); - } - return this.flakyError; - } - - /** - * Gets the value of the systemOut property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemOut() { - return systemOut; - } - - /** - * Sets the value of the systemOut property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemOut(String value) { - this.systemOut = value; - } - - /** - * Gets the value of the systemErr property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemErr() { - return systemErr; - } - - /** - * Sets the value of the systemErr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemErr(String value) { - this.systemErr = value; - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - /** - * Gets the value of the classname property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getClassname() { - return classname; - } - - /** - * Sets the value of the classname property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setClassname(String value) { - this.classname = value; - } - - /** - * Gets the value of the group property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGroup() { - return group; - } - - /** - * Sets the value of the group property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGroup(String value) { - this.group = value; - } - - /** - * Gets the value of the time property. - * - */ - public float getTime() { - return time; - } - - /** - * Sets the value of the time property. - * - */ - public void setTime(float value) { - this.time = value; - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <simpleContent>
-         *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
-         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </extension>
-         *   </simpleContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "value" - }) - public static class Error { - - @XmlValue - protected String value; - @XmlAttribute(name = "message") - protected String message; - @XmlAttribute(name = "type", required = true) - protected String type; - - /** - * Gets the value of the value property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getValue() { - return value; - } - - /** - * Sets the value of the value property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setValue(String value) { - this.value = value; - } - - /** - * Gets the value of the message property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessage() { - return message; - } - - /** - * Sets the value of the message property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessage(String value) { - this.message = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setType(String value) { - this.type = value; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <simpleContent>
-         *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
-         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </extension>
-         *   </simpleContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "value" - }) - public static class Failure { - - @XmlValue - protected String value; - @XmlAttribute(name = "message") - protected String message; - @XmlAttribute(name = "type", required = true) - protected String type; - - /** - * Gets the value of the value property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getValue() { - return value; - } - - /** - * Sets the value of the value property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setValue(String value) { - this.value = value; - } - - /** - * Gets the value of the message property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessage() { - return message; - } - - /** - * Sets the value of the message property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessage(String value) { - this.message = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setType(String value) { - this.type = value; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <complexContent>
-         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-         *       <sequence>
-         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *       </sequence>
-         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </restriction>
-         *   </complexContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "stackTrace", - "systemOut", - "systemErr" - }) - public static class FlakyError { - - @XmlElement(required = true) - protected String stackTrace; - @XmlElement(name = "system-out") - protected String systemOut; - @XmlElement(name = "system-err") - protected String systemErr; - @XmlAttribute(name = "message") - protected String message; - @XmlAttribute(name = "type", required = true) - protected String type; - - /** - * Gets the value of the stackTrace property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getStackTrace() { - return stackTrace; - } - - /** - * Sets the value of the stackTrace property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setStackTrace(String value) { - this.stackTrace = value; - } - - /** - * Gets the value of the systemOut property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemOut() { - return systemOut; - } - - /** - * Sets the value of the systemOut property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemOut(String value) { - this.systemOut = value; - } - - /** - * Gets the value of the systemErr property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemErr() { - return systemErr; - } - - /** - * Sets the value of the systemErr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemErr(String value) { - this.systemErr = value; - } - - /** - * Gets the value of the message property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessage() { - return message; - } - - /** - * Sets the value of the message property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessage(String value) { - this.message = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setType(String value) { - this.type = value; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <complexContent>
-         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-         *       <sequence>
-         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *       </sequence>
-         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </restriction>
-         *   </complexContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "stackTrace", - "systemOut", - "systemErr" - }) - public static class FlakyFailure { - - @XmlElement(required = true) - protected String stackTrace; - @XmlElement(name = "system-out") - protected String systemOut; - @XmlElement(name = "system-err") - protected String systemErr; - @XmlAttribute(name = "message") - protected String message; - @XmlAttribute(name = "type", required = true) - protected String type; - - /** - * Gets the value of the stackTrace property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getStackTrace() { - return stackTrace; - } - - /** - * Sets the value of the stackTrace property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setStackTrace(String value) { - this.stackTrace = value; - } - - /** - * Gets the value of the systemOut property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemOut() { - return systemOut; - } - - /** - * Sets the value of the systemOut property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemOut(String value) { - this.systemOut = value; - } - - /** - * Gets the value of the systemErr property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemErr() { - return systemErr; - } - - /** - * Sets the value of the systemErr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemErr(String value) { - this.systemErr = value; - } - - /** - * Gets the value of the message property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessage() { - return message; - } - - /** - * Sets the value of the message property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessage(String value) { - this.message = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setType(String value) { - this.type = value; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <complexContent>
-         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-         *       <sequence>
-         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *       </sequence>
-         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </restriction>
-         *   </complexContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "stackTrace", - "systemOut", - "systemErr" - }) - public static class RerunError { - - @XmlElement(required = true) - protected String stackTrace; - @XmlElement(name = "system-out") - protected String systemOut; - @XmlElement(name = "system-err") - protected String systemErr; - @XmlAttribute(name = "message") - protected String message; - @XmlAttribute(name = "type", required = true) - protected String type; - - /** - * Gets the value of the stackTrace property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getStackTrace() { - return stackTrace; - } - - /** - * Sets the value of the stackTrace property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setStackTrace(String value) { - this.stackTrace = value; - } - - /** - * Gets the value of the systemOut property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemOut() { - return systemOut; - } - - /** - * Sets the value of the systemOut property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemOut(String value) { - this.systemOut = value; - } - - /** - * Gets the value of the systemErr property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemErr() { - return systemErr; - } - - /** - * Sets the value of the systemErr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemErr(String value) { - this.systemErr = value; - } - - /** - * Gets the value of the message property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessage() { - return message; - } - - /** - * Sets the value of the message property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessage(String value) { - this.message = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setType(String value) { - this.type = value; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <complexContent>
-         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-         *       <sequence>
-         *         <element name="stackTrace" type="{http://www.w3.org/2001/XMLSchema}string"/>
-         *         <element name="system-out" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *         <element name="system-err" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
-         *       </sequence>
-         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *       <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </restriction>
-         *   </complexContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "stackTrace", - "systemOut", - "systemErr" - }) - public static class RerunFailure { - - @XmlElement(required = true) - protected String stackTrace; - @XmlElement(name = "system-out") - protected String systemOut; - @XmlElement(name = "system-err") - protected String systemErr; - @XmlAttribute(name = "message") - protected String message; - @XmlAttribute(name = "type", required = true) - protected String type; - - /** - * Gets the value of the stackTrace property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getStackTrace() { - return stackTrace; - } - - /** - * Sets the value of the stackTrace property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setStackTrace(String value) { - this.stackTrace = value; - } - - /** - * Gets the value of the systemOut property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemOut() { - return systemOut; - } - - /** - * Sets the value of the systemOut property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemOut(String value) { - this.systemOut = value; - } - - /** - * Gets the value of the systemErr property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSystemErr() { - return systemErr; - } - - /** - * Sets the value of the systemErr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSystemErr(String value) { - this.systemErr = value; - } - - /** - * Gets the value of the message property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessage() { - return message; - } - - /** - * Sets the value of the message property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessage(String value) { - this.message = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setType(String value) { - this.type = value; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-         * <complexType>
-         *   <simpleContent>
-         *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
-         *       <attribute name="message" type="{http://www.w3.org/2001/XMLSchema}string" />
-         *     </extension>
-         *   </simpleContent>
-         * </complexType>
-         * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "value" - }) - public static class Skipped { - - @XmlValue - protected String value; - @XmlAttribute(name = "message") - protected String message; - - /** - * Gets the value of the value property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getValue() { - return value; - } - - /** - * Sets the value of the value property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setValue(String value) { - this.value = value; - } - - /** - * Gets the value of the message property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMessage() { - return message; - } - - /** - * Sets the value of the message property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMessage(String value) { - this.message = value; - } - - } - - } - -} diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuiteParsingTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuiteParsingTest.java index de75d14..5dd9d58 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuiteParsingTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/reports/TestSuiteParsingTest.java @@ -14,11 +14,11 @@ class TestSuiteParsingTest { @Test void testReadCucumberOuptut() throws IOException, JAXBException { - var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); + var unmarshaller = JAXBContext.newInstance(Testsuite.class).createUnmarshaller(); var file = new ClassPathResource("/cucumber-junit-output.xml"); - var root = unmarshaller.unmarshal(new StreamSource(file.getInputStream()), TestSuite.class); + var root = unmarshaller.unmarshal(new StreamSource(file.getInputStream()), Testsuite.class); var testSuite = root.getValue(); assertThat(testSuite.getName()).isEqualTo("Cucumber"); @@ -44,11 +44,11 @@ class TestSuiteParsingTest { @Test void testReadSurefireOutput() throws IOException, JAXBException { - var unmarshaller = JAXBContext.newInstance(TestSuite.class).createUnmarshaller(); + var unmarshaller = JAXBContext.newInstance(Testsuite.class).createUnmarshaller(); var file = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml"); - var root = unmarshaller.unmarshal(new StreamSource(file.getInputStream()), TestSuite.class); + var root = unmarshaller.unmarshal(new StreamSource(file.getInputStream()), Testsuite.class); var testSuite = root.getValue(); assertThat(testSuite.getName()).isEqualTo("test.dao.CatalogDaoTest"); -- 2.51.2 From 3ad9814c27ee7a9b81af5ce7019317df55f7c783 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 15:15:36 +0200 Subject: [PATCH 16/22] =?UTF-8?q?=E2=9C=85=20:=20add=20some=20tests=20for?= =?UTF-8?q?=20junit=20assignment=20grades?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grading/junit/JUnitAssignmentGrade.java | 10 ++++ .../StudentExerciseAssignmentTest.java | 24 ++++++++++ .../junit/JUnitAssignmentGradeTest.java | 46 +++++++++++++++++++ .../grading/junit/JUnitTestSuiteTest.java | 45 ++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignmentTest.java create mode 100644 src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGradeTest.java create mode 100644 src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuiteTest.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java index ebfe58e..60e5f7b 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java @@ -39,4 +39,14 @@ public class JUnitAssignmentGrade extends AssignmentGrade { .mapToInt(JUnitTestSuite::getMaxScore) .sum(); } + + @Override + public boolean equals(Object o) { + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } } diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignmentTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignmentTest.java new file mode 100644 index 0000000..6a1aff9 --- /dev/null +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignmentTest.java @@ -0,0 +1,24 @@ +package fr.univ_lille.gitlab.classrooms.assignments; + +import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.JUnitAssignmentGrade; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class StudentExerciseAssignmentTest { + + @Test + void shouldHaveOnlyOneGradeOfEachType() { + var studentExerciseAssignment = new StudentExerciseAssignment(); + + var junitGrade = new JUnitAssignmentGrade(); + + var anotherJunitGrade = new JUnitAssignmentGrade(); + + studentExerciseAssignment.getAssignmentGrades().add(junitGrade); + studentExerciseAssignment.getAssignmentGrades().add(anotherJunitGrade); + + assertThat(studentExerciseAssignment.getAssignmentGrades()).hasSize(1); + } +} diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGradeTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGradeTest.java new file mode 100644 index 0000000..31d0ec6 --- /dev/null +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGradeTest.java @@ -0,0 +1,46 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit; + +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +class JUnitAssignmentGradeTest { + + @Test + void maxScoreShouldBeTheSumOfSuiteMaxScores() { + var junitAssignmentGrade = new JUnitAssignmentGrade(); + + var firstJunitSuite = new JUnitTestSuite(); + firstJunitSuite.setName("First"); + firstJunitSuite.setTests(10); + + var secondJunitSuite = new JUnitTestSuite(); + secondJunitSuite.setName("Second"); + secondJunitSuite.setTests(5); + + junitAssignmentGrade.setTestSuites(Set.of(firstJunitSuite, secondJunitSuite)); + + assertThat(junitAssignmentGrade.getMaxScore()).isEqualTo(15); + } + + @Test + void scoreShouldBeTheSumOfSuitescores() { + var junitAssignmentGrade = new JUnitAssignmentGrade(); + + var firstJunitSuite = new JUnitTestSuite(); + firstJunitSuite.setName("First"); + firstJunitSuite.setTests(10); + firstJunitSuite.setFailures(3); + + var secondJunitSuite = new JUnitTestSuite(); + secondJunitSuite.setName("Second"); + secondJunitSuite.setTests(5); + + junitAssignmentGrade.setTestSuites(Set.of(firstJunitSuite, secondJunitSuite)); + + assertThat(junitAssignmentGrade.getScore()).isEqualTo(12); + } +} diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuiteTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuiteTest.java new file mode 100644 index 0000000..ec9f42e --- /dev/null +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitTestSuiteTest.java @@ -0,0 +1,45 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading.junit; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class JUnitTestSuiteTest { + + @Test + void maxScore_shouldBeTestCount() { + var testSuite = new JUnitTestSuite(); + testSuite.setTests(10); + + assertThat(testSuite.getMaxScore()).isEqualTo(10); + } + + @Test + void score_shouldBeTestSuccess() { + var testSuite = new JUnitTestSuite(); + testSuite.setTests(10); + testSuite.setErrors(1); + testSuite.setFailures(1); + testSuite.setSkipped(2); + + assertThat(testSuite.getScore()).isEqualTo(6); + } + + @Test + void suites_shouldBeEqual_whenHavingTheSameName(){ + var testSuite1 = new JUnitTestSuite(); + testSuite1.setName("Suite 1"); + + var testSuite2 = new JUnitTestSuite(); + testSuite2.setName("Suite 2"); + + var testSuite3 = new JUnitTestSuite(); + testSuite3.setName("Suite 1"); + + assertThat(testSuite1) + .isNotEqualTo(testSuite2) + .isEqualTo(testSuite3) + .doesNotHaveSameHashCodeAs(testSuite2) + .hasSameHashCodeAs(testSuite3); + } +} -- 2.51.2 From 89c3fed6f3d04c22e8ff8de938c0c9535e649e87 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 15:23:51 +0200 Subject: [PATCH 17/22] =?UTF-8?q?=E2=9C=A8=20:=20add=20AssignmentGradingEx?= =?UTF-8?q?ception=20to=20manage=20JAXB=20exceptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grading/AssignmentGradeService.java | 2 +- .../grading/AssignmentGradeServiceImpl.java | 7 +++---- .../grading/AssignmentGradingController.java | 6 +++++- .../grading/AssignmentGradingException.java | 7 +++++++ .../grading/AssignmentGradeServiceImplTest.java | 17 ++++++++++++++--- 5 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingException.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java index 0ef3d69..f515c7a 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeService.java @@ -6,6 +6,6 @@ import java.io.InputStream; public interface AssignmentGradeService { - void gradeAssignmentWithJUnitReport(StudentExerciseAssignment studentExerciseAssignment, InputStream inputStream); + void gradeAssignmentWithJUnitReport(StudentExerciseAssignment studentExerciseAssignment, InputStream inputStream) throws AssignmentGradingException; } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java index d2de011..2574591 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImpl.java @@ -4,7 +4,6 @@ import fr.univ_lille.gitlab.classrooms.assignments.StudentExerciseAssignment; import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.JUnitAssignmentGrade; import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.JUnitTestSuite; import fr.univ_lille.gitlab.classrooms.assignments.grading.junit.reports.TestReportParser; -import jakarta.transaction.Transactional; import jakarta.xml.bind.JAXBException; import org.springframework.stereotype.Service; @@ -23,8 +22,7 @@ class AssignmentGradeServiceImpl implements AssignmentGradeService { } @Override - @Transactional - public void gradeAssignmentWithJUnitReport(StudentExerciseAssignment studentExerciseAssignment, InputStream inputStream) { + public void gradeAssignmentWithJUnitReport(StudentExerciseAssignment studentExerciseAssignment, InputStream inputStream) throws AssignmentGradingException { // parse test suite try { var testSuiteReport = testReportParser.parseTestReport(inputStream); @@ -45,7 +43,8 @@ class AssignmentGradeServiceImpl implements AssignmentGradeService { // update the submission date studentExerciseAssignment.setSubmissionDate(ZonedDateTime.now()); } catch (JAXBException e) { - LOGGER.log(System.Logger.Level.ERROR, "Could parse JUnit Report"); + LOGGER.log(System.Logger.Level.ERROR, "Could not parse JUnit Report", e); + throw new AssignmentGradingException("Could not parse JUnit Report", e); } } } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java index 607ee7b..40451fc 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingController.java @@ -51,7 +51,11 @@ class AssignmentGradingController { .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); // grade using the test report - this.assignmentGradeService.gradeAssignmentWithJUnitReport(exerciseAssignment, testResultsFile.getInputStream()); + try { + this.assignmentGradeService.gradeAssignmentWithJUnitReport(exerciseAssignment, testResultsFile.getInputStream()); + } catch (AssignmentGradingException e) { + throw new ResponseStatusException(500, e.getMessage(), e); + } this.studentAssignmentService.save(exerciseAssignment); } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingException.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingException.java new file mode 100644 index 0000000..068dec8 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradingException.java @@ -0,0 +1,7 @@ +package fr.univ_lille.gitlab.classrooms.assignments.grading; + +public class AssignmentGradingException extends Exception { + public AssignmentGradingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java index 1e6ab10..686a67b 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGradeServiceImplTest.java @@ -11,6 +11,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.io.ClassPathResource; import java.io.IOException; +import java.io.InputStream; import java.time.ZonedDateTime; import static org.assertj.core.api.Assertions.*; @@ -25,7 +26,17 @@ class AssignmentGradeServiceImplTest { private TestReportParser testReportParser = new TestReportParser(); @Test - void testGradeAssignmentWithJUnitReport() throws IOException { + void testShouldThrowExceptionForIncorrectContent() { + var studentExerciseAssignment = new StudentExerciseAssignment(); + + var reportInputStream = InputStream.nullInputStream(); + + assertThatExceptionOfType(AssignmentGradingException.class) + .isThrownBy(() -> assignmentGradeService.gradeAssignmentWithJUnitReport(studentExerciseAssignment, reportInputStream)); + } + + @Test + void testGradeAssignmentWithJUnitReport() throws IOException, AssignmentGradingException { var studentExerciseAssignment = new StudentExerciseAssignment(); var reportInputStream = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml").getInputStream(); @@ -59,7 +70,7 @@ class AssignmentGradeServiceImplTest { } @Test - void testGradeAssignmentWithMultipleJUnitReports() throws IOException { + void testGradeAssignmentWithMultipleJUnitReports() throws IOException, AssignmentGradingException { var studentExerciseAssignment = new StudentExerciseAssignment(); var firstReportInputStream = new ClassPathResource("/junit-reports/TEST-test.dao.CatalogDaoTest.xml").getInputStream(); @@ -74,7 +85,7 @@ class AssignmentGradeServiceImplTest { } @Test - void testGradeAssignmentWithJUnitCucumberReport() throws IOException { + void testGradeAssignmentWithJUnitCucumberReport() throws IOException, AssignmentGradingException { var studentExerciseAssignment = new StudentExerciseAssignment(); var reportInputStream = new ClassPathResource("/cucumber-junit-output.xml").getInputStream(); -- 2.51.2 From 3c2b5c191bc72f64bcdfaca49a079af601cbed8f Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 15:58:26 +0200 Subject: [PATCH 18/22] =?UTF-8?q?=E2=99=BB=20:=20use=20entities=20instead?= =?UTF-8?q?=20of=20embeddables=20for=20inheritance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit embeddables do not support inheritance see https://en.wikibooks.org/wiki/Java_Persistence/Embeddables#Inheritance --- .../assignments/StudentExerciseAssignment.java | 4 ++-- .../assignments/grading/AssignmentGrade.java | 15 ++++++++++++++- .../grading/junit/JUnitAssignmentGrade.java | 4 ++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java index 7bee203..0131c1a 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java @@ -1,8 +1,8 @@ package fr.univ_lille.gitlab.classrooms.assignments; import fr.univ_lille.gitlab.classrooms.assignments.grading.AssignmentGrade; -import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; import java.util.HashSet; import java.util.Set; @@ -14,7 +14,7 @@ public class StudentExerciseAssignment extends StudentAssignment { private String gitlabProjectUrl; - @ElementCollection + @OneToMany private Set assignmentGrades = new HashSet<>(); public Long getGitlabProjectId() { diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java index 943cded..ee43c98 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/AssignmentGrade.java @@ -2,10 +2,15 @@ package fr.univ_lille.gitlab.classrooms.assignments.grading; import jakarta.persistence.*; -@Embeddable +import java.util.UUID; + +@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class AssignmentGrade { + @Id + private UUID id = UUID.randomUUID(); + @Enumerated(EnumType.STRING) private AssignmentGradeType type; @@ -16,6 +21,14 @@ public abstract class AssignmentGrade { this.type = type; } + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + public AssignmentGradeType getType() { return type; } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java index 60e5f7b..fae13ef 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/grading/junit/JUnitAssignmentGrade.java @@ -3,12 +3,12 @@ package fr.univ_lille.gitlab.classrooms.assignments.grading.junit; import fr.univ_lille.gitlab.classrooms.assignments.grading.AssignmentGrade; import fr.univ_lille.gitlab.classrooms.assignments.grading.AssignmentGradeType; import jakarta.persistence.ElementCollection; -import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; import java.util.HashSet; import java.util.Set; -@Embeddable +@Entity public class JUnitAssignmentGrade extends AssignmentGrade { public JUnitAssignmentGrade() { -- 2.51.2 From cdbcd0998ba6e9775af155891f16883a73514722 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 16:00:17 +0200 Subject: [PATCH 19/22] =?UTF-8?q?=F0=9F=93=9D=20:=20document=20properties?= =?UTF-8?q?=20to=20help=20schema=20updates=20generation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-local.properties | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index 71e8d3c..56cf354 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -10,4 +10,9 @@ spring.datasource.password=password spring.jpa.generate-ddl=false spring.jpa.hibernate.ddl-auto=update +# generate full creation sql script if needed +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=update +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=update.sql + spring.flyway.enabled=false -- 2.51.2 From fe99276b706ad9ba17b26a5a9a1b8fe671ae7073 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 16:00:45 +0200 Subject: [PATCH 20/22] =?UTF-8?q?=F0=9F=94=A7=20:=20use=20schema=20validat?= =?UTF-8?q?ion=20instead=20of=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-local.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index 56cf354..818b0e0 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -8,7 +8,7 @@ spring.datasource.password=password # validate ddl only spring.jpa.generate-ddl=false -spring.jpa.hibernate.ddl-auto=update +spring.jpa.hibernate.ddl-auto=validate # generate full creation sql script if needed #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata -- 2.51.2 From 21079759faeb4a1cb33fc45f6067ba73b8eac79c Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 16:21:19 +0200 Subject: [PATCH 21/22] =?UTF-8?q?=F0=9F=90=9B=20:=20add=20cascade=20all=20?= =?UTF-8?q?to=20assignment=20grades?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../classrooms/assignments/StudentExerciseAssignment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java index 0131c1a..2fabc19 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentExerciseAssignment.java @@ -1,6 +1,7 @@ package fr.univ_lille.gitlab.classrooms.assignments; import fr.univ_lille.gitlab.classrooms.assignments.grading.AssignmentGrade; +import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.OneToMany; @@ -14,7 +15,7 @@ public class StudentExerciseAssignment extends StudentAssignment { private String gitlabProjectUrl; - @OneToMany + @OneToMany(cascade = CascadeType.ALL) private Set assignmentGrades = new HashSet<>(); public Long getGitlabProjectId() { -- 2.51.2 From b89792a470eefb9766eb250fc13f0a6cc4a66b66 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Wed, 30 Aug 2023 16:34:32 +0200 Subject: [PATCH 22/22] =?UTF-8?q?=F0=9F=97=83=EF=B8=8F=20:=20add=20script?= =?UTF-8?q?=20for=20autograding=20assignments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migration/V18__JUNIT_ASSIGNMENT_GRADE.sql | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/resources/db/migration/V18__JUNIT_ASSIGNMENT_GRADE.sql diff --git a/src/main/resources/db/migration/V18__JUNIT_ASSIGNMENT_GRADE.sql b/src/main/resources/db/migration/V18__JUNIT_ASSIGNMENT_GRADE.sql new file mode 100644 index 0000000..252511d --- /dev/null +++ b/src/main/resources/db/migration/V18__JUNIT_ASSIGNMENT_GRADE.sql @@ -0,0 +1,27 @@ +create table junit_assignment_grade +( + id uuid primary key not null, + type character varying(255) +); + + +create table junit_assignment_grade_test_suites +( + junit_assignment_grade_id uuid not null + constraint fk_junit_assignment_grade references junit_assignment_grade, + name character varying(255), + tests integer not null, + errors integer not null, + failures integer not null, + skipped integer not null +); + + +create table student_exercise_assignment_assignment_grades +( + student_exercise_assignment_id uuid not null + constraint fk_student_exercise_assignment references student_exercise_assignment, + assignment_grades_id uuid not null, + primary key (student_exercise_assignment_id, assignment_grades_id) +); +