element exists with the ID '#test-duration-trend-chart'.
- */
- view.getTestDurationTrend(configuration, function (lineModel) {
- echartsJenkinsApi.renderConfigurableZoomableTrendChart('test-duration-trend-chart', lineModel.responseJSON, trendConfigurationDialogId);
- });
-
- /**
- * Creates a build trend chart that shows the test results across a number of builds.
- * Requires that a DOM
element exists with the ID '#test-result-trend-chart'.
- */
- view.getTestResultTrend(configuration, function (lineModel) {
- echartsJenkinsApi.renderConfigurableZoomableTrendChart('test-result-trend-chart', lineModel.responseJSON, trendConfigurationDialogId);
- });
- }
-
- /**
- * Store and restore the selected carousel image in browser's local storage.
- * Additionally, the trend chart is redrawn.
- *
- */
- function storeAndRestoreCarousel (carouselId) {
- const carousel = $('#' + carouselId);
- carousel.on('slid.bs.carousel', function (e) {
- localStorage.setItem(carouselId, e.to);
- const chart = $(e.relatedTarget).find('>:first-child')[0].echart;
- if (chart) {
- chart.resize();
- }
- });
- const activeCarousel = localStorage.getItem(carouselId);
- if (activeCarousel) {
- const carouselControl = new bootstrap5.Carousel(carousel[0]);
- carouselControl.to(parseInt(activeCarousel));
- carouselControl.pause();
- }
- }
- })
-})(jQuery3);
diff --git a/src/test/java/hudson/tasks/junit/CaseResultTest.java b/src/test/java/hudson/tasks/junit/CaseResultTest.java
index 74ac6354c..fe05b170d 100644
--- a/src/test/java/hudson/tasks/junit/CaseResultTest.java
+++ b/src/test/java/hudson/tasks/junit/CaseResultTest.java
@@ -91,7 +91,8 @@ public void testIssue20090516() throws Exception {
FreeStyleBuild b = configureTestBuild(null);
TestResult tr = b.getAction(TestResultAction.class).getResult();
assertEquals(3,tr.getFailedTests().size());
- CaseResult cr = tr.getFailedTests().get(0);
+ // Alphabetic order to ensure a stable list regardless of parallel execution or multiple result suites.
+ CaseResult cr = tr.getFailedTests().get(2);
assertEquals("org.twia.vendor.VendorManagerTest",cr.getClassName());
assertEquals("testGetVendorFirmKeyForVendorRep",cr.getName());
diff --git a/src/test/java/hudson/tasks/junit/SuiteResult2Test.java b/src/test/java/hudson/tasks/junit/SuiteResult2Test.java
index 152a99255..00657f225 100644
--- a/src/test/java/hudson/tasks/junit/SuiteResult2Test.java
+++ b/src/test/java/hudson/tasks/junit/SuiteResult2Test.java
@@ -97,7 +97,7 @@ public class SuiteResult2Test {
}
private SuiteResult parseOne(File file) throws Exception {
- List
results = SuiteResult.parse(file, false, null);
+ List results = SuiteResult.parse(file, false, false, null);
assertEquals(1,results.size());
return results.get(0);
}
diff --git a/src/test/java/hudson/tasks/junit/SuiteResultTest.java b/src/test/java/hudson/tasks/junit/SuiteResultTest.java
index 0bd65fae4..5a993543e 100644
--- a/src/test/java/hudson/tasks/junit/SuiteResultTest.java
+++ b/src/test/java/hudson/tasks/junit/SuiteResultTest.java
@@ -67,19 +67,19 @@ private SuiteResult parseOne(File file) throws Exception {
}
private SuiteResult parseOne(File file, StdioRetention stdioRetention) throws Exception {
- List results = SuiteResult.parse(file, stdioRetention, false, null);
+ List results = SuiteResult.parse(file, stdioRetention, false, false, null);
assertEquals(1,results.size());
return results.get(0);
}
private SuiteResult parseOneWithProperties(File file) throws Exception {
- List results = SuiteResult.parse(file, StdioRetention.DEFAULT, true, null);
+ List results = SuiteResult.parse(file, StdioRetention.DEFAULT, true, false,null);
assertEquals(1,results.size());
return results.get(0);
}
private List parseSuites(File file) throws Exception {
- return SuiteResult.parse(file, StdioRetention.DEFAULT, false, null);
+ return SuiteResult.parse(file, StdioRetention.DEFAULT, false, false, null);
}
@Issue("JENKINS-1233")
@@ -120,7 +120,7 @@ public void testIssue1463() throws Exception {
@Issue("JENKINS-1472")
@Test
public void testIssue1472() throws Exception {
- List results = SuiteResult.parse(getDataFile("junit-report-1472.xml"), false, null);
+ List results = SuiteResult.parse(getDataFile("junit-report-1472.xml"), false, false, null);
assertTrue(results.size()>20); // lots of data here
SuiteResult sr0 = results.get(0);
diff --git a/src/test/java/hudson/tasks/junit/TestResultTest.java b/src/test/java/hudson/tasks/junit/TestResultTest.java
index fa4b9dfb9..eec0fde91 100644
--- a/src/test/java/hudson/tasks/junit/TestResultTest.java
+++ b/src/test/java/hudson/tasks/junit/TestResultTest.java
@@ -35,14 +35,10 @@
import java.util.Collection;
import java.util.List;
-import org.apache.tools.ant.DirectoryScanner;
-import org.junit.Test;
+import org.apache.commons.io.FileUtils;import org.apache.tools.ant.DirectoryScanner;
+import org.junit.Rule;import org.junit.Test;
-import org.jvnet.hudson.test.Issue;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
+import org.junit.rules.TemporaryFolder;import org.jvnet.hudson.test.Issue;import static org.junit.Assert.*;
/**
* Tests the JUnit result XML file parsing in {@link TestResult}.
@@ -50,6 +46,9 @@
* @author dty
*/
public class TestResultTest {
+ @Rule
+ public TemporaryFolder tmp = new TemporaryFolder();
+
protected static File getDataFile(String name) throws URISyntaxException {
return new File(TestResultTest.class.getResource(name).toURI());
}
@@ -295,7 +294,7 @@ public void skipOldReports() throws Exception {
directoryScanner.setIncludes(new String[]{"*.xml"});
directoryScanner.scan();
assertEquals( "directory scanner must find 2 files", 2, directoryScanner.getIncludedFiles().length);
- TestResult testResult = new TestResult(start, directoryScanner, true, false, new PipelineTestDetails(),true);
+ TestResult testResult = new TestResult(start, directoryScanner, true, false, false, new PipelineTestDetails(),true);
testResult.tally();
assertEquals("Wrong number of testsuites", 2, testResult.getSuites().size());
@@ -322,7 +321,21 @@ public void parseOldReports() throws Exception {
assertEquals("Wrong number of test cases", 6, testResult.getTotalCount());
}
-
+ @Test
+ public void clampDuration() throws Exception {
+ long start = System.currentTimeMillis();
+ File testResultFile1 = new File("src/test/resources/hudson/tasks/junit/junit-report-bad-duration.xml");
+ DirectoryScanner directoryScanner = new DirectoryScanner();
+ directoryScanner.setBasedir(new File("src/test/resources/hudson/tasks/junit/"));
+ directoryScanner.setIncludes(new String[]{"*-bad-duration.xml"});
+ directoryScanner.scan();
+ assertEquals( "directory scanner must find 1 files", 1, directoryScanner.getIncludedFiles().length);
+ TestResult testResult = new TestResult(start, directoryScanner, true, false, new PipelineTestDetails(), false);
+ testResult.tally();
+ assertEquals("Negative duration is invalid", 100, testResult.getDuration(), 0.00001);
+ assertEquals("Wrong number of testsuites", 1, testResult.getSuites().size());
+ assertEquals("Wrong number of test cases", 2, testResult.getTotalCount());
+ }
@Test
public void testStartTimes() throws Exception {
// Tests that start times are as expected for file with a mix of valid,
@@ -330,7 +343,6 @@ public void testStartTimes() throws Exception {
TestResult testResult = new TestResult();
testResult.parse(getDataFile("junit-report-testsuite-various-timestamps.xml"));
testResult.tally();
-
// Test that TestResult startTime is the startTime of the earliest suite.
assertEquals(1704281235000L, testResult.getStartTime());
@@ -402,4 +414,31 @@ public void testStartTimes() throws Exception {
}
+ /*
+ For performance reasons, we parse the XML directly.
+ Make sure parser handles all the fields.
+ */
+ @Test
+ public void bigResultReadWrite() throws Exception {
+ List results = SuiteResult.parse(getDataFile("junit-report-huge.xml"), StdioRetention.ALL, true, true, null);
+ assertEquals(1, results.size());
+ SuiteResult sr = results.get(0);
+
+ TestResult tr = new TestResult();
+ tr.getSuites().add(sr);
+ XmlFile f = new XmlFile(TestResultAction.XSTREAM, tmp.newFile("junitResult.xml"));
+ f.write(tr);
+
+ TestResult tr2 = new TestResult();
+ tr2.parse(f);
+ XmlFile f2 = new XmlFile(TestResultAction.XSTREAM, tmp.newFile("junitResult2.xml"));
+ f2.write(tr2);
+
+ assertEquals(2, tr.getSuites().stream().findFirst().get().getProperties().size());
+ assertEquals(2, tr2.getSuites().stream().findFirst().get().getProperties().size());
+
+ boolean isTwoEqual = FileUtils.contentEquals(f.getFile(), f2.getFile());
+ assertTrue("Forgot to implement XML parsing for something?", isTwoEqual);
+ }
+
}
diff --git a/src/test/java/hudson/tasks/junit/pipeline/JUnitResultsStepTest.java b/src/test/java/hudson/tasks/junit/pipeline/JUnitResultsStepTest.java
index d31010294..9fa4c249c 100644
--- a/src/test/java/hudson/tasks/junit/pipeline/JUnitResultsStepTest.java
+++ b/src/test/java/hudson/tasks/junit/pipeline/JUnitResultsStepTest.java
@@ -283,7 +283,7 @@ public void parallelInStage() throws Exception {
" touch 'third-result.xml'\n" +
" parallel(a: { def first = junit(testResults: 'first-result.xml'); assert first.totalCount == 6 },\n" +
" b: { def second = junit(testResults: 'second-result.xml'); assert second.totalCount == 1 },\n" +
- " c: { def third = junit(testResults: 'third-result.xml'); assert third.totalCount == 3 })\n" +
+ " c: { def third = junit(testResults: 'third-result.xml', keepTestNames: true); assert third.totalCount == 3 })\n" +
" }\n" +
"}\n", true
));
@@ -294,9 +294,9 @@ public void parallelInStage() throws Exception {
assertEquals(5, action.getResult().getSuites().size());
assertEquals(10, action.getTotalCount());
- assertBranchResults(r, 1, 6, 0, "a", "first", null);
- assertBranchResults(r, 1, 1, 0, "b", "first", null);
- assertBranchResults(r, 3, 3, 1, "c", "first", null);
+ assertBranchResults(r, 1, 6, 0, "a", "first", null, false);
+ assertBranchResults(r, 1, 1, 0, "b", "first", null, false);
+ assertBranchResults(r, 3, 3, 1, "c", "first", null, true);
assertStageResults(r, 5, 10, 1, "first");
}
@@ -315,7 +315,7 @@ public void stageInParallel() throws Exception {
" touch 'third-result.xml'\n" +
" parallel(a: { stage('a') { def first = junit(testResults: 'first-result.xml'); assert first.totalCount == 6 } },\n" +
" b: { stage('b') { def second = junit(testResults: 'second-result.xml'); assert second.totalCount == 1 } },\n" +
- " c: { stage('d') { def third = junit(testResults: 'third-result.xml'); assert third.totalCount == 3 } })\n" +
+ " c: { stage('d') { def third = junit(testResults: 'third-result.xml', keepTestNames: true); assert third.totalCount == 3 } })\n" +
" }\n" +
"}\n", true
));
@@ -329,11 +329,11 @@ public void stageInParallel() throws Exception {
// assertBranchResults looks to make sure the display names for tests are "(stageName) / (branchName) / (testName)"
// That should still effectively be the case here, even though there's a stage inside each branch, because the
// branch and nested stage have the same name.
- assertBranchResults(r, 1, 6, 0, "a", "outer", null);
- assertBranchResults(r, 1, 1, 0, "b", "outer", null);
+ assertBranchResults(r, 1, 6, 0, "a", "outer", null, false);
+ assertBranchResults(r, 1, 1, 0, "b", "outer", null, false);
// ...except for branch c. That contains a stage named 'd', so its test should have display names like
// "outer / c / d / (testName)"
- assertBranchResults(r, 3, 3, 1, "c", "outer", "d");
+ assertBranchResults(r, 3, 3, 1, "c", "outer", "d", true);
}
@Test
@@ -497,17 +497,28 @@ private static Predicate stageForName(final String name) {
public static void assertBranchResults(WorkflowRun run, int suiteCount, int testCount, int failCount, String branchName, String stageName,
String innerStageName) {
+ assertBranchResults(run, suiteCount, testCount, failCount, branchName, stageName, innerStageName, false);
+ }
+
+ public static void assertBranchResults(WorkflowRun run, int suiteCount, int testCount, int failCount, String branchName, String stageName,
+ String innerStageName, boolean keepTestNames) {
FlowExecution execution = run.getExecution();
DepthFirstScanner scanner = new DepthFirstScanner();
BlockStartNode aBranch = (BlockStartNode)scanner.findFirstMatch(execution, branchForName(branchName));
assertNotNull(aBranch);
TestResult branchResult = assertBlockResults(run, suiteCount, testCount, failCount, aBranch);
- String namePrefix = stageName + " / " + branchName;
- if (innerStageName != null) {
- namePrefix += " / " + innerStageName;
+ String namePrefix;
+ if (!keepTestNames) {
+ namePrefix = stageName + " / " + branchName;
+ if (innerStageName != null) {
+ namePrefix += " / " + innerStageName;
+ }
+ namePrefix += " / ";
+ } else {
+ namePrefix = "";
}
for (CaseResult c : branchResult.getPassedTests()) {
- assertEquals(namePrefix + " / " + c.getTransformedTestName(), c.getDisplayName());
+ assertEquals(namePrefix + c.getTransformedTestName(), c.getDisplayName());
}
}
diff --git a/src/test/java/io/jenkins/plugins/junit/storage/TestResultStorageJunitTest.java b/src/test/java/io/jenkins/plugins/junit/storage/TestResultStorageJunitTest.java
index 5dc852954..767a7b780 100644
--- a/src/test/java/io/jenkins/plugins/junit/storage/TestResultStorageJunitTest.java
+++ b/src/test/java/io/jenkins/plugins/junit/storage/TestResultStorageJunitTest.java
@@ -476,7 +476,7 @@ public List getHistorySummary(int offset) {
Job, ?> theJob = Jenkins.get().getItemByFullName(getJobName(), Job.class);
if (theJob != null) {
Run, ?> run = theJob.getBuildByNumber(buildNumber);
- historyTestResultSummaries.add(new HistoryTestResultSummary(run, duration, failed, skipped, passed));
+ historyTestResultSummaries.add(new HistoryTestResultSummary(run, null, duration, failed, skipped, passed));
}
}
return historyTestResultSummaries;
diff --git a/src/test/resources/hudson/tasks/junit/junit-report-bad-duration.xml b/src/test/resources/hudson/tasks/junit/junit-report-bad-duration.xml
new file mode 100644
index 000000000..1217e8a0c
--- /dev/null
+++ b/src/test/resources/hudson/tasks/junit/junit-report-bad-duration.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/hudson/tasks/junit/junit-report-huge.xml b/src/test/resources/hudson/tasks/junit/junit-report-huge.xml
new file mode 100644
index 000000000..19cde5f24
--- /dev/null
+++ b/src/test/resources/hudson/tasks/junit/junit-report-huge.xml
@@ -0,0 +1,244 @@
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
+
+
+
+ Config line 1
+ Config line 2
+ Config line 3
+
+
+ This is stdout
+[[ATTACHMENT|attachment.txt]]
+This is stderr
+[[ATTACHMENT|attachment.txt]]
+
\ No newline at end of file