Skip to content

Commit a2f9db3

Browse files
authored
Add support for 'properties' (#541)
1 parent af5d6b5 commit a2f9db3

File tree

9 files changed

+158
-0
lines changed

9 files changed

+158
-0
lines changed

src/main/java/hudson/tasks/junit/CaseResult.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import java.io.IOException;
4747
import java.util.ArrayList;
4848
import java.util.Collection;
49+
import java.util.HashMap;
50+
import java.util.Map;
4951
import java.util.Collections;
5052
import java.util.Comparator;
5153
import java.util.List;
@@ -78,6 +80,7 @@ public class CaseResult extends TestResult implements Comparable<CaseResult> {
7880
private final String skippedMessage;
7981
private final String errorStackTrace;
8082
private final String errorDetails;
83+
private final Map<String, String> properties;
8184
@SuppressFBWarnings(value = "SE_TRANSIENT_FIELD_NOT_RESTORED", justification = "Specific method to restore it")
8285
private transient SuiteResult parent;
8386

@@ -129,6 +132,7 @@ public CaseResult(SuiteResult parent, String testName, String errorStackTrace, S
129132
this.duration = 0.0f;
130133
this.skipped = false;
131134
this.skippedMessage = null;
135+
this.properties = Collections.emptyMap();
132136
}
133137

134138
@Restricted(Beta.class)
@@ -154,6 +158,7 @@ public CaseResult(
154158

155159
this.skipped = skippedMessage != null;
156160
this.skippedMessage = skippedMessage;
161+
this.properties = Collections.emptyMap();
157162
}
158163

159164
CaseResult(SuiteResult parent, Element testCase, String testClassName, boolean keepLongStdio) {
@@ -191,6 +196,22 @@ public CaseResult(
191196
Collection<CaseResult> _this = Collections.singleton(this);
192197
stdout = fixNULs(possiblyTrimStdio(_this, keepLongStdio, testCase.elementText("system-out")));
193198
stderr = fixNULs(possiblyTrimStdio(_this, keepLongStdio, testCase.elementText("system-err")));
199+
200+
// parse properties
201+
Map<String, String> properties = new HashMap<String, String>();
202+
Element properties_element = testCase.element("properties");
203+
if (properties_element != null) {
204+
List<Element> property_elements = properties_element.elements("property");
205+
for (Element prop : property_elements){
206+
if (prop.attributeValue("name") != null) {
207+
if (prop.attributeValue("value") != null)
208+
properties.put(prop.attributeValue("name"), prop.attributeValue("value"));
209+
else
210+
properties.put(prop.attributeValue("name"), prop.getText());
211+
}
212+
}
213+
}
214+
this.properties = properties;
194215
}
195216

196217
static String possiblyTrimStdio(Collection<CaseResult> results, boolean keepLongStdio, String stdio) { // HUDSON-6516
@@ -613,6 +634,12 @@ public String getErrorDetails() {
613634
return errorDetails;
614635
}
615636

637+
@Exported
638+
@Override
639+
public Map<String, String> getProperties() {
640+
return properties;
641+
}
642+
616643
/**
617644
* @return true if the test was not skipped and did not fail, false otherwise.
618645
*/

src/main/java/hudson/tasks/junit/SuiteResult.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public final class SuiteResult implements Serializable {
7373
private final String stdout;
7474
private final String stderr;
7575
private float duration;
76+
private final Map<String, String> properties;
77+
7678
/**
7779
* The 'timestamp' attribute of the test suite.
7880
* AFAICT, this is not a required attribute in XML, so the value may be null.
@@ -125,6 +127,7 @@ public SuiteResult(String name, String stdout, String stderr, @CheckForNull Pipe
125127
this.nodeId = null;
126128
}
127129
this.file = null;
130+
this.properties = Collections.emptyMap();
128131
}
129132

130133
private synchronized Map<String, CaseResult> casesByName() {
@@ -285,6 +288,23 @@ private SuiteResult(File xmlReport, Element suite, boolean keepLongStdio, @Check
285288

286289
this.stdout = CaseResult.fixNULs(stdout);
287290
this.stderr = CaseResult.fixNULs(stderr);
291+
292+
// parse properties
293+
Map<String, String> properties = new HashMap<String, String>();
294+
Element properties_element = suite.element("properties");
295+
if (properties_element != null) {
296+
List<Element> property_elements = properties_element.elements("property");
297+
for (Element prop : property_elements){
298+
if (prop.attributeValue("name") != null) {
299+
if (prop.attributeValue("value") != null)
300+
properties.put(prop.attributeValue("name"), prop.attributeValue("value"));
301+
else
302+
properties.put(prop.attributeValue("name"), prop.getText());
303+
}
304+
}
305+
}
306+
307+
this.properties = properties;
288308
}
289309

290310
public void addCase(CaseResult cr) {
@@ -379,6 +399,16 @@ public String getStderr() {
379399
return stderr;
380400
}
381401

402+
/**
403+
* The properties of this test.
404+
*
405+
* @return the properties of this test.
406+
*/
407+
@Exported
408+
public Map<String, String> getProperties() {
409+
return properties;
410+
}
411+
382412
/**
383413
* The absolute path to the original test report. OS-dependent.
384414
*

src/main/java/hudson/tasks/junit/TestResult.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,11 @@ public String getStderr() {
657657
return sb.toString();
658658
}
659659

660+
@Override
661+
public Map<String, String> getProperties() {
662+
return Collections.emptyMap();
663+
}
664+
660665
/**
661666
* If there was an error or a failure, this is the stack trace, or otherwise null.
662667
*/

src/main/java/hudson/tasks/test/TestResult.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import hudson.model.Result;
2929

3030
import java.util.Collection;
31+
import java.util.Collections;
32+
import java.util.Map;
3133

3234
import static java.util.Collections.emptyList;
3335

@@ -249,6 +251,10 @@ public String getErrorDetails() {
249251
return "";
250252
}
251253

254+
public Map<String, String> getProperties() {
255+
return Collections.emptyMap();
256+
}
257+
252258
/**
253259
* @return true if the test was not skipped and did not fail, false otherwise.
254260
*/

src/main/resources/hudson/tasks/junit/CaseResult/index.jelly

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ THE SOFTWARE.
6868
</j:forEach>
6969
</table>
7070

71+
<j:forEach var="p" items="${it.properties}">
72+
<h3>${p.key}</h3>
73+
<pre><j:out value="${p.value}"/></pre>
74+
</j:forEach>
75+
7176
<j:if test="${!empty(it.skippedMessage)}">
7277
<h3>${%Skip Message}</h3>
7378
<pre><j:out value="${it.annotate(it.skippedMessage)}"/></pre>

src/main/resources/hudson/tasks/junit/CaseResult/summary.jelly

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ THE SOFTWARE.
5555
<j:set var="id" value="${h.generateId()}"/>
5656

5757
<local:item id="${id}" name="error" title="${%Error Details}" value="${it.errorDetails}" opened="true"/>
58+
<j:forEach var="p" items="${it.properties}">
59+
<local:item id="${id}" name="${p.key}" title="${p.key}" value="${p.value}"/>
60+
</j:forEach>
5861
<local:item id="${id}" name="stacktrace" title="${%Stack Trace}" value="${it.errorStackTrace}"/>
5962
<local:item id="${id}" name="stdout" title="${%Standard Output}" value="${it.stdout}"/>
6063
<local:item id="${id}" name="stderr" title="${%Standard Error}" value="${it.stderr}"/>

src/test/java/hudson/tasks/junit/CaseResultTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import java.util.ArrayList;
5656
import java.util.Collections;
5757
import java.util.List;
58+
import java.util.Map;
5859

5960
import static org.junit.Assert.assertEquals;
6061
import static org.junit.Assert.assertNotNull;
@@ -340,6 +341,45 @@ public void emptyName() throws Exception {
340341
rule.buildAndAssertSuccess(p);
341342
}
342343

344+
@Test
345+
public void testProperties() throws Exception {
346+
String projectName = "properties-test";
347+
String testResultResourceFile = "junit-report-with-properties.xml";
348+
349+
FreeStyleProject p = rule.createFreeStyleProject(projectName);
350+
p.getPublishersList().add(new JUnitResultArchiver("*.xml"));
351+
p.getBuildersList().add(new TestBuilder() {
352+
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
353+
FilePath junitFile = build.getWorkspace().child("junit.xml");
354+
junitFile.copyFrom(getClass().getResource(testResultResourceFile));
355+
// sadly this can be flaky for 1ms.... (but hey changing to nano even in core might complicated :))
356+
junitFile.touch(System.currentTimeMillis()+1L);
357+
return true;
358+
}
359+
});
360+
FreeStyleBuild b = rule.assertBuildStatus(Result.UNSTABLE, p.scheduleBuild2(0).get());
361+
362+
TestResult tr = b.getAction(TestResultAction.class).getResult();
363+
364+
assertEquals(1, tr.getSuites().size());
365+
366+
SuiteResult sr = tr.getSuite("io.jenkins.example.with.properties");
367+
Map<String,String> props = sr.getProperties();
368+
assertEquals(props.get("prop1"), "value1");
369+
String[] lines = props.get("multiline").split("\n");
370+
assertEquals("", lines[0]);
371+
assertEquals(" Config line 1", lines[1]);
372+
assertEquals(" Config line 2", lines[2]);
373+
assertEquals(" Config line 3", lines[3]);
374+
375+
assertEquals(2, sr.getCases().size());
376+
CaseResult cr;
377+
cr = sr.getCase("io.jenkins.example.with.properties.testCaseA");
378+
assertEquals("description of test testCaseA", cr.getProperties().get("description"));
379+
cr = sr.getCase("io.jenkins.example.with.properties.testCaseZ");
380+
assertEquals(0, cr.getProperties().size());
381+
}
382+
343383
private String composeXPath(String[] fields) throws Exception {
344384
StringBuilder tmp = new StringBuilder(100);
345385
for ( String f : fields ) {

src/test/java/hudson/tasks/junit/SuiteResultTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2727
import java.io.File;
2828
import java.util.List;
29+
import java.util.Map;
2930
import java.net.URISyntaxException;
3031
import org.apache.commons.io.FileUtils;
3132

@@ -352,4 +353,23 @@ public void testTestSuiteTimeAttribute() throws Exception {
352353
assertEquals(40.0f, results.get(2).getDuration(), 2); //testsuit time
353354
assertEquals(20.0f, results.get(3).getDuration(), 2); //sum of test cases time
354355
}
356+
357+
@Test
358+
public void testProperties() throws Exception {
359+
SuiteResult sr = parseOne(getDataFile("junit-report-with-properties.xml"));
360+
Map<String,String> props = sr.getProperties();
361+
assertEquals(props.get("prop1"), "value1");
362+
String[] lines = props.get("multiline").split("\n");
363+
assertEquals("", lines[0]);
364+
assertEquals(" Config line 1", lines[1]);
365+
assertEquals(" Config line 2", lines[2]);
366+
assertEquals(" Config line 3", lines[3]);
367+
368+
assertEquals(2, sr.getCases().size());
369+
CaseResult cr;
370+
cr = sr.getCase("io.jenkins.example.with.properties.testCaseA");
371+
assertEquals("description of test testCaseA", cr.getProperties().get("description"));
372+
cr = sr.getCase("io.jenkins.example.with.properties.testCaseZ");
373+
assertEquals(0, cr.getProperties().size());
374+
}
355375
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<testsuites>
3+
<testsuite name="io.jenkins.example.with.properties" time="2.000" tests="2" errors="0" skipped="0" failures="1">
4+
<properties>
5+
<property name="prop1" value="value1" />
6+
<property name="multiline">
7+
Config line 1
8+
Config line 2
9+
Config line 3
10+
</property>
11+
</properties>
12+
<testcase name="testCaseA" classname="io.jenkins.example.with.properties" time="1.000">
13+
<failure message="expected: [a] but was: [b]" type="org.junit.ComparisonFailure">
14+
org.junit.ComparisonFailure: expected: [a] but was: [b]
15+
</failure>
16+
<properties>
17+
<property name="description">description of test testCaseA</property>
18+
</properties>
19+
</testcase>
20+
<testcase name="testCaseZ" classname="io.jenkins.example.with.properties" time="1.000" />
21+
</testsuite>
22+
</testsuites>

0 commit comments

Comments
 (0)