mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-23 11:43:29 +01:00
JUnit reporter uses only 3 decimal places when reporting durations
We used to use whatever precision we ended up having from C++'s stdlib. However, some relatively popular tools, like Jenkins, use Maven SureFire XML schema to validate JUnit test reports, and Maven SureFire schema requires the duration to have at most 3 decimal places. For compatibility, the JUnit reporter will now respect this limitation. Closes #2221
This commit is contained in:
parent
b15b862d86
commit
581c46249a
@ -18,6 +18,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -56,6 +57,17 @@ namespace Catch {
|
|||||||
return it->substr(1);
|
return it->substr(1);
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Formats the duration in seconds to 3 decimal places.
|
||||||
|
// This is done because some genius defined Maven Surefire schema
|
||||||
|
// in a way that only accepts 3 decimal places, and tools like
|
||||||
|
// Jenkins use that schema for validation JUnit reporter output.
|
||||||
|
std::string formatDuration( double seconds ) {
|
||||||
|
ReusableStringStream rss;
|
||||||
|
rss << std::fixed << std::setprecision( 3 ) << seconds;
|
||||||
|
return rss.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
JunitReporter::JunitReporter( ReporterConfig const& _config )
|
JunitReporter::JunitReporter( ReporterConfig const& _config )
|
||||||
@ -125,7 +137,7 @@ namespace Catch {
|
|||||||
if( m_config->showDurations() == ShowDurations::Never )
|
if( m_config->showDurations() == ShowDurations::Never )
|
||||||
xml.writeAttribute( "time", "" );
|
xml.writeAttribute( "time", "" );
|
||||||
else
|
else
|
||||||
xml.writeAttribute( "time", suiteTime );
|
xml.writeAttribute( "time", formatDuration( suiteTime ) );
|
||||||
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
|
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
|
||||||
|
|
||||||
// Write properties if there are any
|
// Write properties if there are any
|
||||||
@ -192,7 +204,7 @@ namespace Catch {
|
|||||||
xml.writeAttribute( "classname", className );
|
xml.writeAttribute( "classname", className );
|
||||||
xml.writeAttribute( "name", name );
|
xml.writeAttribute( "name", name );
|
||||||
}
|
}
|
||||||
xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
|
xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) );
|
||||||
// This is not ideal, but it should be enough to mimic gtest's
|
// This is not ideal, but it should be enough to mimic gtest's
|
||||||
// junit output.
|
// junit output.
|
||||||
// Ideally the JUnit reporter would also handle `skipTest`
|
// Ideally the JUnit reporter would also handle `skipTest`
|
||||||
|
@ -28,7 +28,10 @@ filelocParser = re.compile(r'''
|
|||||||
''', re.VERBOSE)
|
''', re.VERBOSE)
|
||||||
lineNumberParser = re.compile(r' line="[0-9]*"')
|
lineNumberParser = re.compile(r' line="[0-9]*"')
|
||||||
hexParser = re.compile(r'\b(0[xX][0-9a-fA-F]+)\b')
|
hexParser = re.compile(r'\b(0[xX][0-9a-fA-F]+)\b')
|
||||||
durationsParser = re.compile(r' time="[0-9]*\.[0-9]*"')
|
# Note: junit must serialize time with 3 (or or less) decimal places
|
||||||
|
# before generalizing this parser, make sure that this is checked
|
||||||
|
# in other places too.
|
||||||
|
junitDurationsParser = re.compile(r' time="[0-9]*\.[0-9]{3}"')
|
||||||
sonarqubeDurationParser = re.compile(r' duration="[0-9]+"')
|
sonarqubeDurationParser = re.compile(r' duration="[0-9]+"')
|
||||||
timestampsParser = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z')
|
timestampsParser = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z')
|
||||||
versionParser = re.compile(r'Catch v[0-9]+\.[0-9]+\.[0-9]+(-develop\.[0-9]+)?')
|
versionParser = re.compile(r'Catch v[0-9]+\.[0-9]+\.[0-9]+(-develop\.[0-9]+)?')
|
||||||
@ -138,7 +141,7 @@ def filterLine(line, isCompact):
|
|||||||
line = hexParser.sub("0x<hex digits>", line)
|
line = hexParser.sub("0x<hex digits>", line)
|
||||||
|
|
||||||
# strip durations and timestamps
|
# strip durations and timestamps
|
||||||
line = durationsParser.sub(' time="{duration}"', line)
|
line = junitDurationsParser.sub(' time="{duration}"', line)
|
||||||
line = sonarqubeDurationParser.sub(' duration="{duration}"', line)
|
line = sonarqubeDurationParser.sub(' duration="{duration}"', line)
|
||||||
line = timestampsParser.sub('{iso8601-timestamp}', line)
|
line = timestampsParser.sub('{iso8601-timestamp}', line)
|
||||||
line = specialCaseParser.sub('file:\g<1>', line)
|
line = specialCaseParser.sub('file:\g<1>', line)
|
||||||
|
Loading…
Reference in New Issue
Block a user