This is an automated email from the ASF dual-hosted git repository.
olamy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
The following commit(s) were added to refs/heads/master by this push:
new 0fba0ef1d Introduce reportTestTimestamp option and include timestamp
for test sets and test cases (#3261)
0fba0ef1d is described below
commit 0fba0ef1da8a410680100307f9742bdedc8e33b7
Author: Kevin Nammour <[email protected]>
AuthorDate: Mon Mar 2 13:10:17 2026 +0200
Introduce reportTestTimestamp option and include timestamp for test sets
and test cases (#3261)
* Introduce reportTestTimestamp option and include start timestamps in XML
reports
* Explicitly state deprecation reason of StatelessXmlReporter ctor, and
inline toIsoInstant logic
* Make test/testset startAt getters package private, and remove sleep
behavior in dummy tests
* Adapt surefire test report format to include timestamp field
---
.../plugin/surefire/AbstractSurefireMojo.java | 13 +++
.../maven/plugin/surefire/CommonReflector.java | 2 +
.../surefire/StartupReportConfiguration.java | 10 +++
.../DefaultStatelessReportMojoConfiguration.java | 4 +-
.../extensions/SurefireStatelessReporter.java | 3 +-
.../junit5/JUnit5Xml30StatelessReporter.java | 3 +-
.../surefire/report/NullStatelessXmlReporter.java | 2 +-
.../surefire/report/StatelessXmlReporter.java | 21 ++++-
.../plugin/surefire/report/TestSetRunListener.java | 15 ++--
.../maven/plugin/surefire/report/TestSetStats.java | 8 ++
.../plugin/surefire/report/WrappedReportEntry.java | 11 ++-
.../maven/plugin/surefire/CommonReflectorTest.java | 1 +
.../surefire/booterclient/ForkStarterTest.java | 2 +
.../booterclient/TestSetMockReporterFactory.java | 1 +
.../surefire/extensions/StatelessReporterTest.java | 4 +-
.../report/DefaultReporterFactoryTest.java | 3 +
.../surefire/report/StatelessXmlReporterTest.java | 55 +++++++++++--
.../surefire/report/WrappedReportEntryTest.java | 25 +++---
.../maven/surefire/report/FileReporterTest.java | 4 +-
.../site/resources/xsd/surefire-test-report.xsd | 2 +
.../StatelessReportMojoConfiguration.java | 11 ++-
.../maven/surefire/its/ReportTestTimestampIT.java | 96 ++++++++++++++++++++++
.../resources/disable-timestamp-element/pom.xml | 58 +++++++++++++
.../src/test/java/TestA.java | 18 ++++
.../resources/enable-timestamp-element/pom.xml | 58 +++++++++++++
.../src/test/java/TestA.java | 18 ++++
.../maven/surefire/junitcore/JUnitCoreTester.java | 1 +
27 files changed, 415 insertions(+), 34 deletions(-)
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index 3b9ed93d5..35addccf6 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -748,6 +748,14 @@ public abstract class AbstractSurefireMojo extends
AbstractMojo implements Suref
@Parameter(property = "enablePropertiesElement", defaultValue = "true")
private boolean enablePropertiesElement;
+ /**
+ * Flag for including/excluding the event start timestamp of {@code
<testsuite />} and {@code <testcase />} elements in XML reports.
+ *
+ * @since 3.5.5
+ */
+ @Parameter(property = "reportTestTimestamp", defaultValue = "false")
+ private boolean reportTestTimestamp;
+
/**
* The current build session instance.
*/
@@ -2109,6 +2117,7 @@ private StartupReportConfiguration
getStartupReportConfiguration(boolean isForki
isForking,
isEnableOutErrElements(),
isEnablePropertiesElement(),
+ isReportTestTimestamp(),
xmlReporter,
outReporter,
testsetReporter,
@@ -3652,6 +3661,10 @@ public boolean isEnablePropertiesElement() {
return enablePropertiesElement;
}
+ public boolean isReportTestTimestamp() {
+ return reportTestTimestamp;
+ }
+
@SuppressWarnings("UnusedDeclaration")
public void setEnablePropertiesElement(boolean enablePropertiesElement) {
this.enablePropertiesElement = enablePropertiesElement;
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
index 83bf6a0d5..7ae2e54d5 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
@@ -91,6 +91,7 @@ private Object createStartupReportConfiguration(@Nonnull
StartupReportConfigurat
boolean.class,
boolean.class,
boolean.class,
+ boolean.class,
statelessTestsetReporter,
consoleOutputReporter,
statelessTestsetInfoReporter,
@@ -111,6 +112,7 @@ private Object createStartupReportConfiguration(@Nonnull
StartupReportConfigurat
reporterConfiguration.isForking(),
reporterConfiguration.isEnableOutErrElements(),
reporterConfiguration.isEnablePropertiesElement(),
+ reporterConfiguration.isReportTestTimestamp(),
reporterConfiguration.getXmlReporter().clone(surefireClassLoader),
reporterConfiguration.getConsoleOutputReporter().clone(surefireClassLoader),
reporterConfiguration.getTestsetReporter().clone(surefireClassLoader),
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
index cd805c7c7..45f642b5c 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
@@ -90,6 +90,8 @@ public final class StartupReportConfiguration {
private final boolean enablePropertiesElement;
+ private final boolean reportTestTimestamp;
+
private final SurefireStatelessReporter xmlReporter;
private final SurefireConsoleOutputReporter consoleOutputReporter;
@@ -120,6 +122,7 @@ public StartupReportConfiguration(
boolean isForking,
boolean enableOutErrElements,
boolean enablePropertiesElement,
+ boolean reportTestTimestamp,
SurefireStatelessReporter xmlReporter,
SurefireConsoleOutputReporter consoleOutputReporter,
SurefireStatelessTestsetInfoReporter testsetReporter,
@@ -142,6 +145,7 @@ public StartupReportConfiguration(
this.isForking = isForking;
this.enableOutErrElements = enableOutErrElements;
this.enablePropertiesElement = enablePropertiesElement;
+ this.reportTestTimestamp = reportTestTimestamp;
this.xmlReporter = xmlReporter;
this.consoleOutputReporter = consoleOutputReporter;
this.testsetReporter = testsetReporter;
@@ -183,6 +187,7 @@ public StartupReportConfiguration(
isForking,
true,
true,
+ false,
xmlReporter,
consoleOutputReporter,
testsetReporter,
@@ -236,6 +241,7 @@ public StatelessReportEventListener<WrappedReportEntry,
TestSetStats> instantiat
xsdSchemaLocation,
enableOutErrElements,
enablePropertiesElement,
+ reportTestTimestamp,
testClassMethodRunHistory);
return xmlReporter.isDisable() ? null :
xmlReporter.createListener(xmlReporterConfig);
@@ -306,6 +312,10 @@ public boolean isEnablePropertiesElement() {
return enablePropertiesElement;
}
+ public boolean isReportTestTimestamp() {
+ return reportTestTimestamp;
+ }
+
private File resolveReportsDirectory(Integer forkNumber) {
return forkNumber == null ? reportsDirectory :
replaceForkThreadsInPath(reportsDirectory, forkNumber);
}
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/DefaultStatelessReportMojoConfiguration.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/DefaultStatelessReportMojoConfiguration.java
index 44479a13d..1a1974f0f 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/DefaultStatelessReportMojoConfiguration.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/DefaultStatelessReportMojoConfiguration.java
@@ -45,6 +45,7 @@ public DefaultStatelessReportMojoConfiguration(
String xsdSchemaLocation,
boolean enableOutErrElements,
boolean enablePropertiesElement,
+ boolean reportTestTimestamp,
Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory) {
super(
reportsDirectory,
@@ -53,7 +54,8 @@ public DefaultStatelessReportMojoConfiguration(
rerunFailingTestsCount,
xsdSchemaLocation,
enableOutErrElements,
- enablePropertiesElement);
+ enablePropertiesElement,
+ reportTestTimestamp);
this.testClassMethodRunHistory = testClassMethodRunHistory;
}
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessReporter.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessReporter.java
index 0f0d4ca0d..c8cb31459 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessReporter.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessReporter.java
@@ -72,7 +72,8 @@ public StatelessReportEventListener<WrappedReportEntry,
TestSetStats> createList
false,
false,
configuration.isEnableOutErrElements(),
- configuration.isEnablePropertiesElement());
+ configuration.isEnablePropertiesElement(),
+ configuration.isReportTestTimestamp());
}
@Override
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5Xml30StatelessReporter.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5Xml30StatelessReporter.java
index d6719da26..9090a9751 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5Xml30StatelessReporter.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5Xml30StatelessReporter.java
@@ -110,7 +110,8 @@ public StatelessReportEventListener<WrappedReportEntry,
TestSetStats> createList
getUsePhrasedTestCaseClassName(),
getUsePhrasedTestCaseMethodName(),
configuration.isEnableOutErrElements(),
- configuration.isEnablePropertiesElement());
+ configuration.isEnablePropertiesElement(),
+ configuration.isReportTestTimestamp());
}
@Override
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java
index d4738df40..bcc0d94cc 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java
@@ -29,7 +29,7 @@ class NullStatelessXmlReporter extends StatelessXmlReporter {
static final NullStatelessXmlReporter INSTANCE = new
NullStatelessXmlReporter();
private NullStatelessXmlReporter() {
- super(null, null, false, 0, null, null, null, false, false, false,
false, true, true);
+ super(null, null, false, 0, null, null, null, false, false, false,
false, true, true, false);
}
@Override
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
index d67cb5440..17547db9b 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
@@ -26,6 +26,7 @@
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedHashMap;
@@ -120,6 +121,12 @@ public class StatelessXmlReporter implements
StatelessReportEventListener<Wrappe
private final boolean enablePropertiesElement;
+ private final boolean reportTestTimestamp;
+
+ /**
+ * @deprecated Prefer adding a new constructor that accepts a
configuration object, e.g.
+ * {@link
org.apache.maven.surefire.extensions.StatelessReportMojoConfiguration}.
+ */
@Deprecated
public StatelessXmlReporter(
File reportsDirectory,
@@ -134,7 +141,8 @@ public StatelessXmlReporter(
boolean phrasedClassName,
boolean phrasedMethodName,
boolean enableOutErrElements,
- boolean enablePropertiesElement) {
+ boolean enablePropertiesElement,
+ boolean reportTestTimestamp) {
this.reportsDirectory = reportsDirectory;
this.reportNameSuffix = reportNameSuffix;
this.trimStackTrace = trimStackTrace;
@@ -148,6 +156,7 @@ public StatelessXmlReporter(
this.phrasedMethodName = phrasedMethodName;
this.enableOutErrElements = enableOutErrElements;
this.enablePropertiesElement = enablePropertiesElement;
+ this.reportTestTimestamp = reportTestTimestamp;
}
@Override
@@ -464,6 +473,11 @@ private void startTestElement(XMLWriter ppw,
WrappedReportEntry report) throws I
if (report.getElapsed() != null) {
ppw.addAttribute("time", String.valueOf(report.getElapsed() /
ONE_SECOND));
}
+
+ if (reportTestTimestamp && report.getStartTime() > 0L) {
+ ppw.addAttribute(
+ "timestamp",
Instant.ofEpochMilli(report.getStartTime()).toString());
+ }
}
private void createTestSuiteElement(
@@ -490,6 +504,11 @@ private void createTestSuiteElement(
ppw.addAttribute("time", String.valueOf(report.getElapsed() /
ONE_SECOND));
}
+ if (reportTestTimestamp && report.getStartTime() > 0L) {
+ ppw.addAttribute(
+ "timestamp",
Instant.ofEpochMilli(report.getStartTime()).toString());
+ }
+
// Count actual unique test methods and their final results from
classMethodStatistics (accumulated across
// reruns)
int actualTestCount = 0;
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
index 3879ef54d..b3cb43616 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
@@ -288,21 +288,26 @@ public void testAssumptionFailure(ReportEntry report) {
private WrappedReportEntry wrap(ReportEntry other, ReportEntryType
reportEntryType) {
int estimatedElapsed = 0;
+ // Skipped tests don't call testStart, and thus fallback on current
time
+ long startTimestamp = System.currentTimeMillis();
+ TestSetStats testSetStats = getTestSetStats(other);
+
if (reportEntryType != SKIPPED) {
Integer etime = other.getElapsed();
- estimatedElapsed = etime == null ?
getTestSetStats(other).getElapsedSinceLastStart() : etime;
+ estimatedElapsed = etime == null ?
testSetStats.getElapsedSinceLastStart() : etime;
+ startTimestamp = testSetStats.getTestStartAt();
}
- return new WrappedReportEntry(other, reportEntryType,
estimatedElapsed, testStdOut, testStdErr);
+ return new WrappedReportEntry(other, reportEntryType, startTimestamp,
estimatedElapsed, testStdOut, testStdErr);
}
private WrappedReportEntry wrapTestSet(TestSetReportEntry other) {
+ TestSetStats testSetStats = getTestSetStats(other);
return new WrappedReportEntry(
other,
null,
- other.getElapsed() != null
- ? other.getElapsed()
- : getTestSetStats(other).getElapsedSinceTestSetStart(),
+ testSetStats.getTestSetStartAt(),
+ other.getElapsed() != null ? other.getElapsed() :
testSetStats.getElapsedSinceTestSetStart(),
testStdOut,
testStdErr,
other.getSystemProperties());
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
index de4a9ce66..6d37d9eff 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java
@@ -82,11 +82,19 @@ public void testSetStart() {
lastStartAt = testSetStartAt;
}
+ long getTestSetStartAt() {
+ return testSetStartAt;
+ }
+
public void testStart() {
testStartAt = System.currentTimeMillis();
lastStartAt = testStartAt;
}
+ long getTestStartAt() {
+ return testStartAt;
+ }
+
private void finishTest(WrappedReportEntry reportEntry) {
reportEntries.add(reportEntry);
incrementCompletedCount();
diff --git
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java
index c443d27cb..4c5f7de21 100644
---
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java
+++
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java
@@ -44,6 +44,8 @@ public class WrappedReportEntry implements TestSetReportEntry
{
private final ReportEntryType reportEntryType;
+ private final long startTime;
+
private final Integer elapsed;
private final Utf8RecodingDeferredFileOutputStream stdout;
@@ -63,12 +65,14 @@ public class WrappedReportEntry implements
TestSetReportEntry {
public WrappedReportEntry(
ReportEntry original,
ReportEntryType reportEntryType,
+ long startTime,
Integer estimatedElapsed,
Utf8RecodingDeferredFileOutputStream stdout,
Utf8RecodingDeferredFileOutputStream stdErr,
Map<String, String> systemProperties) {
this.original = original;
this.reportEntryType = reportEntryType;
+ this.startTime = startTime;
this.elapsed = estimatedElapsed;
this.stdout = stdout;
this.stdErr = stdErr;
@@ -78,10 +82,15 @@ public WrappedReportEntry(
public WrappedReportEntry(
ReportEntry original,
ReportEntryType reportEntryType,
+ long startTime,
Integer estimatedElapsed,
Utf8RecodingDeferredFileOutputStream stdout,
Utf8RecodingDeferredFileOutputStream stdErr) {
- this(original, reportEntryType, estimatedElapsed, stdout, stdErr,
Collections.emptyMap());
+ this(original, reportEntryType, startTime, estimatedElapsed, stdout,
stdErr, Collections.emptyMap());
+ }
+
+ public long getStartTime() {
+ return startTime;
}
@Override
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/CommonReflectorTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/CommonReflectorTest.java
index 510d5d1d5..8f9ba782a 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/CommonReflectorTest.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/CommonReflectorTest.java
@@ -85,6 +85,7 @@ public void setup() {
false,
true,
true,
+ false,
xmlReporter,
consoleOutputReporter,
infoReporter,
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java
index 6a774ace8..f5507a924 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java
@@ -165,6 +165,7 @@ public void processShouldExitWithoutSayingGoodBye() throws
Exception {
true,
true,
true,
+ false,
xmlReporter,
outputReporter,
statelessTestsetInfoReporter,
@@ -253,6 +254,7 @@ public void processShouldWaitForAck() throws Exception {
true,
true,
true,
+ false,
xmlReporter,
outputReporter,
statelessTestsetInfoReporter,
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
index fe7791ea6..e256250a2 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
@@ -69,6 +69,7 @@ private static StartupReportConfiguration defaultValue() {
true,
true,
true,
+ false,
new SurefireStatelessReporter(),
new SurefireConsoleOutputReporter(),
new SurefireStatelessTestsetInfoReporter(),
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/StatelessReporterTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/StatelessReporterTest.java
index c628f8b14..4fe2a49d5 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/StatelessReporterTest.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/StatelessReporterTest.java
@@ -66,7 +66,7 @@ public void shouldCreateConsoleListener() {
String schema =
"https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd";
Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory = new
HashMap<>();
DefaultStatelessReportMojoConfiguration config = new
DefaultStatelessReportMojoConfiguration(
- reportsDirectory, reportNameSuffix, true, 5, schema, true,
true, testClassMethodRunHistory);
+ reportsDirectory, reportNameSuffix, true, 5, schema, true,
true, false, testClassMethodRunHistory);
SurefireStatelessReporter extension = new SurefireStatelessReporter();
assertThat(extension.getVersion()).isEqualTo("3.0.2");
@@ -141,7 +141,7 @@ public void shouldCreateJUnit5ConsoleListener() {
String schema =
"https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd";
Map<String, Deque<WrappedReportEntry>> testClassMethodRunHistory = new
HashMap<>();
DefaultStatelessReportMojoConfiguration config = new
DefaultStatelessReportMojoConfiguration(
- reportsDirectory, reportNameSuffix, true, 5, schema, true,
true, testClassMethodRunHistory);
+ reportsDirectory, reportNameSuffix, true, 5, schema, true,
true, false, testClassMethodRunHistory);
JUnit5Xml30StatelessReporter extension = new
JUnit5Xml30StatelessReporter();
assertThat(extension.getVersion()).isEqualTo("3.0.2");
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
index 12ad8db8c..918b9c106 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java
@@ -94,6 +94,7 @@ public void testMergeTestHistoryResult() throws Exception {
false,
true,
true,
+ false,
new SurefireStatelessReporter(),
new SurefireConsoleOutputReporter(),
new SurefireStatelessTestsetInfoReporter(),
@@ -330,6 +331,7 @@ public void testLogger() {
false,
true,
true,
+ false,
new SurefireStatelessReporter(),
new SurefireConsoleOutputReporter(),
new SurefireStatelessTestsetInfoReporter(),
@@ -397,6 +399,7 @@ public void testCreateReporterWithZeroStatistics() {
false,
true,
true,
+ false,
new SurefireStatelessReporter(),
new SurefireConsoleOutputReporter(),
new SurefireStatelessTestsetInfoReporter(),
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java
index 362facb15..59f1a9b38 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java
@@ -111,13 +111,14 @@ public void testFileNameWithoutSuffix() {
false,
false,
true,
- true);
+ true,
+ false);
reporter.cleanTestHistoryMap();
ReportEntry reportEntry = new SimpleReportEntry(
NORMAL_RUN, 0L, getClass().getName(), null,
getClass().getName(), null, 12);
- WrappedReportEntry testSetReportEntry =
- new WrappedReportEntry(reportEntry, ReportEntryType.SUCCESS,
12, null, null, systemProps());
+ WrappedReportEntry testSetReportEntry = new WrappedReportEntry(
+ reportEntry, ReportEntryType.SUCCESS, 1771085631L, 12, null,
null, systemProps());
stats.testSucceeded(testSetReportEntry);
reporter.testSetCompleted(testSetReportEntry, stats);
@@ -131,7 +132,7 @@ public void testAllFieldsSerialized() throws IOException {
ReportEntry reportEntry =
new SimpleReportEntry(NORMAL_RUN, 0L, getClass().getName(),
null, TEST_ONE, null, 12);
WrappedReportEntry testSetReportEntry =
- new WrappedReportEntry(reportEntry, SUCCESS, 12, null, null,
systemProps());
+ new WrappedReportEntry(reportEntry, SUCCESS, 1771085631L, 12,
null, null, systemProps());
expectedReportFile = new File(reportDir, "TEST-" +
getClass().getName() + ".xml");
stats.testSucceeded(testSetReportEntry);
@@ -155,6 +156,7 @@ public void testAllFieldsSerialized() throws IOException {
WrappedReportEntry t2 = new WrappedReportEntry(
new SimpleReportEntry(NORMAL_RUN, 0L, getClass().getName(),
null, TEST_TWO, null, stackTraceWriter, 13),
ReportEntryType.ERROR,
+ 1771085631L,
13,
stdOut,
stdErr);
@@ -173,7 +175,8 @@ public void testAllFieldsSerialized() throws IOException {
false,
false,
true,
- true);
+ true,
+ false);
reporter.testSetCompleted(testSetReportEntry, stats);
FileInputStream fileInputStream = new
FileInputStream(expectedReportFile);
@@ -213,6 +216,7 @@ public void testOutputRerunFlakyFailure() throws
IOException {
WrappedReportEntry testSetReportEntry = new WrappedReportEntry(
new SimpleReportEntry(NORMAL_RUN, 0L, getClass().getName(),
null, TEST_ONE, null, 12),
ReportEntryType.SUCCESS,
+ 1771085631L,
12,
null,
null,
@@ -233,6 +237,7 @@ public void testOutputRerunFlakyFailure() throws
IOException {
WrappedReportEntry testTwoFirstError = new WrappedReportEntry(
new SimpleReportEntry(NORMAL_RUN, 0L, cls, null, TEST_TWO,
null, stackTraceWriterOne, 5),
ReportEntryType.ERROR,
+ 1771085631L,
5,
createStdOutput(firstRunOut),
createStdOutput(firstRunErr));
@@ -240,6 +245,7 @@ public void testOutputRerunFlakyFailure() throws
IOException {
WrappedReportEntry testTwoSecondError = new WrappedReportEntry(
new SimpleReportEntry(RERUN_TEST_AFTER_FAILURE, 1L, cls, null,
TEST_TWO, null, stackTraceWriterTwo, 13),
ReportEntryType.ERROR,
+ 1771085631L,
13,
createStdOutput(secondRunOut),
createStdOutput(secondRunErr));
@@ -247,6 +253,7 @@ public void testOutputRerunFlakyFailure() throws
IOException {
WrappedReportEntry testThreeFirstRun = new WrappedReportEntry(
new SimpleReportEntry(NORMAL_RUN, 2L, cls, null, TEST_THREE,
null, stackTraceWriterOne, 13),
ReportEntryType.FAILURE,
+ 1771085631L,
13,
createStdOutput(firstRunOut),
createStdOutput(firstRunErr));
@@ -255,6 +262,7 @@ public void testOutputRerunFlakyFailure() throws
IOException {
new SimpleReportEntry(
RERUN_TEST_AFTER_FAILURE, 3L, cls, null, TEST_THREE,
null, stackTraceWriterTwo, 2),
ReportEntryType.SUCCESS,
+ 1771085631L,
2,
createStdOutput(secondRunOut),
createStdOutput(secondRunErr));
@@ -277,7 +285,8 @@ public void testOutputRerunFlakyFailure() throws
IOException {
false,
false,
true,
- true);
+ true,
+ false);
reporter.testSetCompleted(testSetReportEntry, stats);
reporter.testSetCompleted(testSetReportEntry, rerunStats);
@@ -352,6 +361,7 @@ public void testOutputRerunFlakyAssumption() throws
IOException {
new SimpleReportEntry(
NORMAL_RUN, 1L, getClass().getName(), null, TEST_TWO,
null, stackTraceWriterOne, 5),
ERROR,
+ 1771085631L,
5,
createStdOutput(firstRunOut),
createStdOutput(firstRunErr));
@@ -369,6 +379,7 @@ public void testOutputRerunFlakyAssumption() throws
IOException {
stackTraceWriterTwo,
13),
SKIPPED,
+ 1771085631L,
13,
createStdOutput(secondRunOut),
createStdOutput(secondRunErr));
@@ -376,12 +387,26 @@ public void testOutputRerunFlakyAssumption() throws
IOException {
rerunStats.testSucceeded(testTwoSecondError);
StatelessXmlReporter reporter = new StatelessXmlReporter(
- reportDir, null, false, 1, new HashMap<>(), XSD, "3.0.2",
false, false, false, false, true, true);
+ reportDir,
+ null,
+ false,
+ 1,
+ new HashMap<>(),
+ XSD,
+ "3.0.2",
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false);
WrappedReportEntry testSetReportEntry = new WrappedReportEntry(
new SimpleReportEntry(
RERUN_TEST_AFTER_FAILURE, 1L, getClass().getName(),
null, null, null, stackTraceWriterOne, 5),
ERROR,
+ 1771085631L,
20,
createStdOutput(firstRunOut),
createStdOutput(firstRunErr));
@@ -535,12 +560,26 @@ public void
testReporterHandlesATestWithoutMessageAndWithEmptyStackTrace() {
new SimpleReportEntry(
NORMAL_RUN, 1L, getClass().getName(), null, "a test
name", null, stackTraceWriterOne, 5),
ERROR,
+ 1771085631L,
5,
null,
null);
StatelessXmlReporter reporter = new StatelessXmlReporter(
- reportDir, null, false, 1, new HashMap<>(), XSD, "3.0.2",
false, false, false, false, true, true);
+ reportDir,
+ null,
+ false,
+ 1,
+ new HashMap<>(),
+ XSD,
+ "3.0.2",
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false);
reporter.testSetCompleted(testReport, stats);
}
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java
index 6d337467a..04dfb2574 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java
@@ -35,7 +35,12 @@ public class WrappedReportEntryTest extends TestCase {
public void testClassNameOnly() {
String className = "surefire.testcase.JunitParamsTest";
WrappedReportEntry wr = new WrappedReportEntry(
- new SimpleReportEntry(NORMAL_RUN, 1L, className, null, null,
null), SUCCESS, 12, null, null);
+ new SimpleReportEntry(NORMAL_RUN, 1L, className, null, null,
null),
+ SUCCESS,
+ 1771085631L,
+ 12,
+ null,
+ null);
final String reportName = wr.getReportSourceName();
assertEquals("surefire.testcase.JunitParamsTest.null",
wr.getClassMethodName());
assertEquals("surefire.testcase.JunitParamsTest", reportName);
@@ -47,7 +52,7 @@ public void testClassNameOnly() {
public void testRegular() {
ReportEntry reportEntry =
new SimpleReportEntry(NORMAL_RUN, 1L,
"surefire.testcase.JunitParamsTest", null, "testSum", null);
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, null, 12,
null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, null,
1771085631L, 12, null, null);
assertEquals("surefire.testcase.JunitParamsTest.testSum",
wr.getClassMethodName());
assertEquals("surefire.testcase.JunitParamsTest",
wr.getReportSourceName());
assertEquals("surefire.testcase.JunitParamsTest",
wr.getReportSourceName(""));
@@ -66,7 +71,7 @@ public void testRegular() {
public void testDisplayNames() {
ReportEntry reportEntry = new SimpleReportEntry(
NORMAL_RUN, 0L, "surefire.testcase.JunitParamsTest", "dn1",
"testSum", "dn2", "exception");
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, ERROR, 12,
null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, ERROR,
1771085631L, 12, null, null);
assertEquals("surefire.testcase.JunitParamsTest.testSum",
wr.getClassMethodName());
assertEquals("dn1", wr.getReportSourceName());
assertEquals("dn1(BDD)", wr.getReportSourceName("BDD"));
@@ -90,7 +95,7 @@ public void testEqualDisplayNames() {
"surefire.testcase.JunitParamsTest",
"testSum",
"testSum");
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, FAILURE,
12, null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, FAILURE,
1771085631L, 12, null, null);
assertEquals("surefire.testcase.JunitParamsTest",
wr.getReportSourceName());
assertEquals("surefire.testcase.JunitParamsTest(BDD)",
wr.getReportSourceName("BDD"));
assertEquals("testSum", wr.getReportName());
@@ -102,7 +107,7 @@ public void testEqualDisplayNames() {
public void testGetReportNameWithParams() {
String className = "[0] 1\u002C 2\u002C 3 (testSum)";
ReportEntry reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
className, null, null, null);
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
12, null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
1771085631L, 12, null, null);
final String reportName = wr.getReportSourceName();
assertEquals("[0] 1, 2, 3 (testSum)", reportName);
assertFalse(wr.isSucceeded());
@@ -114,7 +119,7 @@ public void
testGetReportNameWithGroupWhenSourceTextIsNull() {
String className = "ClassName";
String classText = null;
ReportEntry reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
className, classText, null, null);
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
12, null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
1771085631L, 12, null, null);
assertEquals(className, wr.getReportNameWithGroup());
}
@@ -122,7 +127,7 @@ public void
testGetReportNameWithGroupWhenSourceTextIsEmpty() {
String className = "ClassName";
String classText = "";
ReportEntry reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
className, classText, null, null);
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
12, null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
1771085631L, 12, null, null);
assertEquals(className, wr.getReportNameWithGroup());
}
@@ -130,7 +135,7 @@ public void
testGetReportNameWithGroupWhenSourceTextIsBlank() {
String className = "ClassName";
String classText = " ";
ReportEntry reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
className, classText, null, null);
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
12, null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
1771085631L, 12, null, null);
assertEquals(className, wr.getReportNameWithGroup());
}
@@ -138,14 +143,14 @@ public void
testGetReportNameWithGroupWhenSourceTextIsProvided() {
String className = "ClassName";
String classText = "The Class Name";
ReportEntry reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
className, classText, null, null);
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
12, null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, SKIPPED,
1771085631L, 12, null, null);
assertEquals(classText, wr.getReportNameWithGroup());
}
public void testElapsed() {
String className = "[0] 1\u002C 2\u002C 3 (testSum)";
ReportEntry reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
className, null, null, null);
- WrappedReportEntry wr = new WrappedReportEntry(reportEntry, null, 12,
null, null);
+ WrappedReportEntry wr = new WrappedReportEntry(reportEntry, null,
1771085631L, 12, null, null);
String elapsedTimeSummary = wr.getElapsedTimeSummary();
assertEquals("[0] 1, 2, 3 (testSum) -- Time elapsed: 0.012 s",
elapsedTimeSummary);
}
diff --git
a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java
index 12c159023..d9292ee96 100644
---
a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java
+++
b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java
@@ -47,7 +47,7 @@ public void testFileNameWithoutSuffix() {
File reportDir = new File("target");
reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
getClass().getName(), null, TEST_NAME, null);
WrappedReportEntry wrappedReportEntry =
- new WrappedReportEntry(reportEntry, ReportEntryType.SUCCESS,
12, null, null);
+ new WrappedReportEntry(reportEntry, ReportEntryType.SUCCESS,
1771085631L, 12, null, null);
reporter = new FileReporter(reportDir, null, Charset.defaultCharset(),
false, false, false);
reporter.testSetCompleted(wrappedReportEntry, createTestSetStats(),
new ArrayList<>());
@@ -68,7 +68,7 @@ public void testFileNameWithSuffix() {
String suffixText = "sampleSuffixText";
reportEntry = new SimpleReportEntry(NORMAL_RUN, 1L,
getClass().getName(), null, TEST_NAME, null);
WrappedReportEntry wrappedReportEntry =
- new WrappedReportEntry(reportEntry, ReportEntryType.SUCCESS,
12, null, null);
+ new WrappedReportEntry(reportEntry, ReportEntryType.SUCCESS,
1771085631L, 12, null, null);
reporter = new FileReporter(reportDir, suffixText,
Charset.defaultCharset(), false, false, false);
reporter.testSetCompleted(wrappedReportEntry, createTestSetStats(),
new ArrayList<>());
diff --git
a/maven-surefire-plugin/src/site/resources/xsd/surefire-test-report.xsd
b/maven-surefire-plugin/src/site/resources/xsd/surefire-test-report.xsd
index a70bed30d..72ee09047 100644
--- a/maven-surefire-plugin/src/site/resources/xsd/surefire-test-report.xsd
+++ b/maven-surefire-plugin/src/site/resources/xsd/surefire-test-report.xsd
@@ -116,12 +116,14 @@
<xs:attribute name="classname" type="xs:string"/>
<xs:attribute name="group" type="xs:string"/>
<xs:attribute name="time" type="xs:float" use="required"/>
+ <xs:attribute name="timestamp" type="xs:dateTime"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="version" type="xs:string"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="time" type="xs:float"/>
+ <xs:attribute name="timestamp" type="xs:dateTime"/>
<xs:attribute name="tests" type="xs:string" use="required"/>
<xs:attribute name="errors" type="xs:string" use="required"/>
<xs:attribute name="skipped" type="xs:string" use="required"/>
diff --git
a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportMojoConfiguration.java
b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportMojoConfiguration.java
index 694e50b4d..ac4d666da 100644
---
a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportMojoConfiguration.java
+++
b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportMojoConfiguration.java
@@ -40,6 +40,9 @@ public class StatelessReportMojoConfiguration {
private final boolean enablePropertiesElement;
+ private final boolean reportTestTimestamp;
+
+ @SuppressWarnings("checkstyle:parameternumber")
public StatelessReportMojoConfiguration(
File reportsDirectory,
String reportNameSuffix,
@@ -47,7 +50,8 @@ public StatelessReportMojoConfiguration(
int rerunFailingTestsCount,
String xsdSchemaLocation,
boolean enableOutErrElements,
- boolean enablePropertiesElement) {
+ boolean enablePropertiesElement,
+ boolean reportTestTimestamp) {
this.reportsDirectory = reportsDirectory;
this.reportNameSuffix = reportNameSuffix;
this.trimStackTrace = trimStackTrace;
@@ -55,6 +59,7 @@ public StatelessReportMojoConfiguration(
this.xsdSchemaLocation = xsdSchemaLocation;
this.enableOutErrElements = enableOutErrElements;
this.enablePropertiesElement = enablePropertiesElement;
+ this.reportTestTimestamp = reportTestTimestamp;
}
public File getReportsDirectory() {
@@ -84,4 +89,8 @@ public boolean isEnableOutErrElements() {
public boolean isEnablePropertiesElement() {
return enablePropertiesElement;
}
+
+ public boolean isReportTestTimestamp() {
+ return reportTestTimestamp;
+ }
}
diff --git
a/surefire-its/src/test/java/org/apache/maven/surefire/its/ReportTestTimestampIT.java
b/surefire-its/src/test/java/org/apache/maven/surefire/its/ReportTestTimestampIT.java
new file mode 100644
index 000000000..5da12f136
--- /dev/null
+++
b/surefire-its/src/test/java/org/apache/maven/surefire/its/ReportTestTimestampIT.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.surefire.its;
+
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.maven.surefire.its.fixture.OutputValidator;
+import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.apache.maven.surefire.its.fixture.TestFile;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ReportTestTimestampIT extends SurefireJUnit4IntegrationTestCase {
+ @Test
+ public void testReportTestTimestampDisabled() {
+ OutputValidator outputValidator =
unpack("/disable-timestamp-element").executeTest();
+ TestFile reportFile =
outputValidator.getSurefireReportsXmlFile("TEST-TestA.xml");
+
+ String xml = reportFile.slurpFile();
+
+ // testsuite has no timestamp
+ assertFalse(
+ "Unexpected timestamp on testsuite",
xml.matches(".*<testsuite[^>]*\\btimestamp=\"[^\"]+\"[^>]*>.*"));
+
+ // no testcase has timestamp
+ int testcaseWithTsCount = countMatches(xml,
"<testcase[^>]*\\btimestamp=\"[^\"]+\"");
+ assertEquals("Unexpected timestamp on testcase", 0,
testcaseWithTsCount);
+ }
+
+ @Test
+ public void testReportTestTimestampEnabled() {
+ OutputValidator outputValidator =
unpack("/enable-timestamp-element").executeTest();
+ TestFile reportFile =
outputValidator.getSurefireReportsXmlFile("TEST-TestA.xml");
+
+ String xml = reportFile.slurpFile();
+
+ // testsuite has timestamp
+ assertTrue("Missing timestamp on testsuite",
xml.matches(".*<testsuite[^>]*\\btimestamp=\"[^\"]+\"[^>]*>.*"));
+
+ // each testcase has timestamp
+ int testcaseCount = countMatches(xml, "<testcase");
+ int testcaseWithTsCount = countMatches(xml,
"<testcase[^>]*\\btimestamp=\"[^\"]+\"");
+ assertEquals("Not all testcases have timestamp", testcaseCount,
testcaseWithTsCount);
+
+ assertAllTimestampsIso(xml);
+ }
+
+ private static int countMatches(String input, String regex) {
+ Matcher matcher = Pattern.compile(regex).matcher(input);
+ int count = 0;
+ while (matcher.find()) {
+ count++;
+ }
+ return count;
+ }
+
+ private static void assertAllTimestampsIso(String xml) {
+ Matcher matcher =
Pattern.compile("timestamp=\"([^\"]+)\"").matcher(xml);
+ while (matcher.find()) {
+ String timestamp = matcher.group(1);
+ assertTrue("Invalid ISO timestamp: " + timestamp,
isIsoTimestamp(timestamp));
+ }
+ }
+
+ private static boolean isIsoTimestamp(String timestamp) {
+ try {
+ DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp,
OffsetDateTime::from);
+ return true;
+ } catch (DateTimeParseException ex) {
+ return false;
+ }
+ }
+}
diff --git a/surefire-its/src/test/resources/disable-timestamp-element/pom.xml
b/surefire-its/src/test/resources/disable-timestamp-element/pom.xml
new file mode 100644
index 000000000..15e20ea60
--- /dev/null
+++ b/surefire-its/src/test/resources/disable-timestamp-element/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>it-parent</artifactId>
+ <version>1.0</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.maven.plugins.surefire</groupId>
+ <artifactId>disable-timestamp-element</artifactId>
+ <version>1.0</version>
+ <url>http://maven.apache.org</url>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.0</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <testFailureIgnore>true</testFailureIgnore>
+ <reportTestTimestamp>false</reportTestTimestamp>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/surefire-its/src/test/resources/disable-timestamp-element/src/test/java/TestA.java
b/surefire-its/src/test/resources/disable-timestamp-element/src/test/java/TestA.java
new file mode 100644
index 000000000..66391e702
--- /dev/null
+++
b/surefire-its/src/test/resources/disable-timestamp-element/src/test/java/TestA.java
@@ -0,0 +1,18 @@
+import org.junit.Test;
+import org.junit.Ignore;
+
+public class TestA {
+ @Ignore("Skipping this test still has to report a processing event
timestamp")
+ @Test
+ public void skipped() throws Exception {
+ }
+
+ @Test
+ public void success() throws Exception {
+ }
+
+ @Test
+ public void failure() throws Exception {
+ throw new Exception("This test is supposed to fail.");
+ }
+}
diff --git a/surefire-its/src/test/resources/enable-timestamp-element/pom.xml
b/surefire-its/src/test/resources/enable-timestamp-element/pom.xml
new file mode 100644
index 000000000..4bf016d99
--- /dev/null
+++ b/surefire-its/src/test/resources/enable-timestamp-element/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>it-parent</artifactId>
+ <version>1.0</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.maven.plugins.surefire</groupId>
+ <artifactId>enable-timestamp-element</artifactId>
+ <version>1.0</version>
+ <url>http://maven.apache.org</url>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.0</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <testFailureIgnore>true</testFailureIgnore>
+ <reportTestTimestamp>true</reportTestTimestamp>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/surefire-its/src/test/resources/enable-timestamp-element/src/test/java/TestA.java
b/surefire-its/src/test/resources/enable-timestamp-element/src/test/java/TestA.java
new file mode 100644
index 000000000..66391e702
--- /dev/null
+++
b/surefire-its/src/test/resources/enable-timestamp-element/src/test/java/TestA.java
@@ -0,0 +1,18 @@
+import org.junit.Test;
+import org.junit.Ignore;
+
+public class TestA {
+ @Ignore("Skipping this test still has to report a processing event
timestamp")
+ @Test
+ public void skipped() throws Exception {
+ }
+
+ @Test
+ public void success() throws Exception {
+ }
+
+ @Test
+ public void failure() throws Exception {
+ throw new Exception("This test is supposed to fail.");
+ }
+}
diff --git
a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
index 1a4f74c29..475bba43f 100644
---
a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
+++
b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java
@@ -112,6 +112,7 @@ private static StartupReportConfiguration
defaultStartupReportConfiguration() {
false,
true,
true,
+ false,
new SurefireStatelessReporter(),
new SurefireConsoleOutputReporter(),
new SurefireStatelessTestsetInfoReporter(),