Commit 2134e3fd by Abseil Team Committed by Andy Getz

Googletest export

Adds ISO8601 timestamps to XML output and RFC3339 timestamps to JSON output. Adds timestamps to testsuites, testsuite and testcases structured JSON/XML output for better reporting how/where time is spent on tests. PiperOrigin-RevId: 260039817
parent 373ed74a
...@@ -588,6 +588,10 @@ class GTEST_API_ TestResult { ...@@ -588,6 +588,10 @@ class GTEST_API_ TestResult {
// Returns the elapsed time, in milliseconds. // Returns the elapsed time, in milliseconds.
TimeInMillis elapsed_time() const { return elapsed_time_; } TimeInMillis elapsed_time() const { return elapsed_time_; }
// Gets the time of the test case start, in ms from the start of the
// UNIX epoch.
TimeInMillis start_timestamp() const { return start_timestamp_; }
// Returns the i-th test part result among all the results. i can range from 0 // Returns the i-th test part result among all the results. i can range from 0
// to total_part_count() - 1. If i is not in that range, aborts the program. // to total_part_count() - 1. If i is not in that range, aborts the program.
const TestPartResult& GetTestPartResult(int i) const; const TestPartResult& GetTestPartResult(int i) const;
...@@ -618,6 +622,9 @@ class GTEST_API_ TestResult { ...@@ -618,6 +622,9 @@ class GTEST_API_ TestResult {
return test_properties_; return test_properties_;
} }
// Sets the start time.
void set_start_timestamp(TimeInMillis start) { start_timestamp_ = start; }
// Sets the elapsed time. // Sets the elapsed time.
void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
...@@ -661,6 +668,8 @@ class GTEST_API_ TestResult { ...@@ -661,6 +668,8 @@ class GTEST_API_ TestResult {
std::vector<TestProperty> test_properties_; std::vector<TestProperty> test_properties_;
// Running count of death tests. // Running count of death tests.
int death_test_count_; int death_test_count_;
// The start time, in milliseconds since UNIX Epoch.
TimeInMillis start_timestamp_;
// The elapsed time, in milliseconds. // The elapsed time, in milliseconds.
TimeInMillis elapsed_time_; TimeInMillis elapsed_time_;
...@@ -881,6 +890,10 @@ class GTEST_API_ TestSuite { ...@@ -881,6 +890,10 @@ class GTEST_API_ TestSuite {
// Returns the elapsed time, in milliseconds. // Returns the elapsed time, in milliseconds.
TimeInMillis elapsed_time() const { return elapsed_time_; } TimeInMillis elapsed_time() const { return elapsed_time_; }
// Gets the time of the test suite start, in ms from the start of the
// UNIX epoch.
TimeInMillis start_timestamp() const { return start_timestamp_; }
// Returns the i-th test among all the tests. i can range from 0 to // Returns the i-th test among all the tests. i can range from 0 to
// total_test_count() - 1. If i is not in that range, returns NULL. // total_test_count() - 1. If i is not in that range, returns NULL.
const TestInfo* GetTestInfo(int i) const; const TestInfo* GetTestInfo(int i) const;
...@@ -999,6 +1012,8 @@ class GTEST_API_ TestSuite { ...@@ -999,6 +1012,8 @@ class GTEST_API_ TestSuite {
internal::TearDownTestSuiteFunc tear_down_tc_; internal::TearDownTestSuiteFunc tear_down_tc_;
// True iff any test in this test suite should run. // True iff any test in this test suite should run.
bool should_run_; bool should_run_;
// The start time, in milliseconds since UNIX Epoch.
TimeInMillis start_timestamp_;
// Elapsed time, in milliseconds. // Elapsed time, in milliseconds.
TimeInMillis elapsed_time_; TimeInMillis elapsed_time_;
// Holds test properties recorded during execution of SetUpTestSuite and // Holds test properties recorded during execution of SetUpTestSuite and
......
...@@ -2032,9 +2032,7 @@ std::string AppendUserMessage(const std::string& gtest_msg, ...@@ -2032,9 +2032,7 @@ std::string AppendUserMessage(const std::string& gtest_msg,
// Creates an empty TestResult. // Creates an empty TestResult.
TestResult::TestResult() TestResult::TestResult()
: death_test_count_(0), : death_test_count_(0), start_timestamp_(0), elapsed_time_(0) {}
elapsed_time_(0) {
}
// D'tor. // D'tor.
TestResult::~TestResult() { TestResult::~TestResult() {
...@@ -2103,13 +2101,7 @@ static const char* const kReservedTestSuitesAttributes[] = { ...@@ -2103,13 +2101,7 @@ static const char* const kReservedTestSuitesAttributes[] = {
// The list of reserved attributes used in the <testsuite> element of XML // The list of reserved attributes used in the <testsuite> element of XML
// output. // output.
static const char* const kReservedTestSuiteAttributes[] = { static const char* const kReservedTestSuiteAttributes[] = {
"disabled", "disabled", "errors", "failures", "name", "tests", "time", "timestamp"};
"errors",
"failures",
"name",
"tests",
"time"
};
// The list of reserved attributes used in the <testcase> element of XML output. // The list of reserved attributes used in the <testcase> element of XML output.
static const char* const kReservedTestCaseAttributes[] = { static const char* const kReservedTestCaseAttributes[] = {
...@@ -2117,10 +2109,10 @@ static const char* const kReservedTestCaseAttributes[] = { ...@@ -2117,10 +2109,10 @@ static const char* const kReservedTestCaseAttributes[] = {
"value_param", "file", "line"}; "value_param", "file", "line"};
// Use a slightly different set for allowed output to ensure existing tests can // Use a slightly different set for allowed output to ensure existing tests can
// still RecordProperty("result") // still RecordProperty("result") or "RecordProperty(timestamp")
static const char* const kReservedOutputTestCaseAttributes[] = { static const char* const kReservedOutputTestCaseAttributes[] = {
"classname", "name", "status", "time", "type_param", "classname", "name", "status", "time", "type_param",
"value_param", "file", "line", "result"}; "value_param", "file", "line", "result", "timestamp"};
template <int kSize> template <int kSize>
std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) { std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
...@@ -2705,6 +2697,7 @@ void TestInfo::Run() { ...@@ -2705,6 +2697,7 @@ void TestInfo::Run() {
test, &Test::DeleteSelf_, "the test fixture's destructor"); test, &Test::DeleteSelf_, "the test fixture's destructor");
} }
result_.set_start_timestamp(start);
result_.set_elapsed_time(internal::GetTimeInMillis() - start); result_.set_elapsed_time(internal::GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished. // Notifies the unit test event listener that a test has just finished.
...@@ -2774,6 +2767,7 @@ TestSuite::TestSuite(const char* a_name, const char* a_type_param, ...@@ -2774,6 +2767,7 @@ TestSuite::TestSuite(const char* a_name, const char* a_type_param,
set_up_tc_(set_up_tc), set_up_tc_(set_up_tc),
tear_down_tc_(tear_down_tc), tear_down_tc_(tear_down_tc),
should_run_(false), should_run_(false),
start_timestamp_(0),
elapsed_time_(0) {} elapsed_time_(0) {}
// Destructor of TestSuite. // Destructor of TestSuite.
...@@ -2823,11 +2817,11 @@ void TestSuite::Run() { ...@@ -2823,11 +2817,11 @@ void TestSuite::Run() {
internal::HandleExceptionsInMethodIfSupported( internal::HandleExceptionsInMethodIfSupported(
this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()"); this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");
const internal::TimeInMillis start = internal::GetTimeInMillis(); start_timestamp_ = internal::GetTimeInMillis();
for (int i = 0; i < total_test_count(); i++) { for (int i = 0; i < total_test_count(); i++) {
GetMutableTestInfo(i)->Run(); GetMutableTestInfo(i)->Run();
} }
elapsed_time_ = internal::GetTimeInMillis() - start; elapsed_time_ = internal::GetTimeInMillis() - start_timestamp_;
impl->os_stack_trace_getter()->UponLeavingGTest(); impl->os_stack_trace_getter()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported( internal::HandleExceptionsInMethodIfSupported(
...@@ -3788,6 +3782,9 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, ...@@ -3788,6 +3782,9 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
: "suppressed"); : "suppressed");
OutputXmlAttribute(stream, kTestsuite, "time", OutputXmlAttribute(stream, kTestsuite, "time",
FormatTimeInMillisAsSeconds(result.elapsed_time())); FormatTimeInMillisAsSeconds(result.elapsed_time()));
OutputXmlAttribute(
stream, kTestsuite, "timestamp",
FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
OutputXmlAttribute(stream, kTestsuite, "classname", test_suite_name); OutputXmlAttribute(stream, kTestsuite, "classname", test_suite_name);
int failures = 0; int failures = 0;
...@@ -3838,6 +3835,9 @@ void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream, ...@@ -3838,6 +3835,9 @@ void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream,
OutputXmlAttribute(stream, kTestsuite, "errors", "0"); OutputXmlAttribute(stream, kTestsuite, "errors", "0");
OutputXmlAttribute(stream, kTestsuite, "time", OutputXmlAttribute(stream, kTestsuite, "time",
FormatTimeInMillisAsSeconds(test_suite.elapsed_time())); FormatTimeInMillisAsSeconds(test_suite.elapsed_time()));
OutputXmlAttribute(
stream, kTestsuite, "timestamp",
FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
*stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result()); *stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
} }
*stream << ">\n"; *stream << ">\n";
...@@ -3864,11 +3864,11 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, ...@@ -3864,11 +3864,11 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
stream, kTestsuites, "disabled", stream, kTestsuites, "disabled",
StreamableToString(unit_test.reportable_disabled_test_count())); StreamableToString(unit_test.reportable_disabled_test_count()));
OutputXmlAttribute(stream, kTestsuites, "errors", "0"); OutputXmlAttribute(stream, kTestsuites, "errors", "0");
OutputXmlAttribute(stream, kTestsuites, "time",
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
OutputXmlAttribute( OutputXmlAttribute(
stream, kTestsuites, "timestamp", stream, kTestsuites, "timestamp",
FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
OutputXmlAttribute(stream, kTestsuites, "time",
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
if (GTEST_FLAG(shuffle)) { if (GTEST_FLAG(shuffle)) {
OutputXmlAttribute(stream, kTestsuites, "random_seed", OutputXmlAttribute(stream, kTestsuites, "random_seed",
...@@ -4156,6 +4156,9 @@ void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream, ...@@ -4156,6 +4156,9 @@ void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream,
? (result.Skipped() ? "SKIPPED" : "COMPLETED") ? (result.Skipped() ? "SKIPPED" : "COMPLETED")
: "SUPPRESSED", : "SUPPRESSED",
kIndent); kIndent);
OutputJsonKey(stream, kTestsuite, "timestamp",
FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
kIndent);
OutputJsonKey(stream, kTestsuite, "time", OutputJsonKey(stream, kTestsuite, "time",
FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent); FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent);
OutputJsonKey(stream, kTestsuite, "classname", test_suite_name, kIndent, OutputJsonKey(stream, kTestsuite, "classname", test_suite_name, kIndent,
...@@ -4202,6 +4205,10 @@ void JsonUnitTestResultPrinter::PrintJsonTestSuite( ...@@ -4202,6 +4205,10 @@ void JsonUnitTestResultPrinter::PrintJsonTestSuite(
OutputJsonKey(stream, kTestsuite, "disabled", OutputJsonKey(stream, kTestsuite, "disabled",
test_suite.reportable_disabled_test_count(), kIndent); test_suite.reportable_disabled_test_count(), kIndent);
OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent); OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
OutputJsonKey(
stream, kTestsuite, "timestamp",
FormatEpochTimeInMillisAsRFC3339(test_suite.start_timestamp()),
kIndent);
OutputJsonKey(stream, kTestsuite, "time", OutputJsonKey(stream, kTestsuite, "time",
FormatTimeInMillisAsDuration(test_suite.elapsed_time()), FormatTimeInMillisAsDuration(test_suite.elapsed_time()),
kIndent, false); kIndent, false);
......
...@@ -67,11 +67,14 @@ EXPECTED_1 = { ...@@ -67,11 +67,14 @@ EXPECTED_1 = {
0, 0,
u'time': u'time':
u'*', u'*',
u'timestamp':
u'*',
u'testsuite': [{ u'testsuite': [{
u'name': u'TestSomeProperties', u'name': u'TestSomeProperties',
u'status': u'RUN', u'status': u'RUN',
u'result': u'COMPLETED', u'result': u'COMPLETED',
u'time': u'*', u'time': u'*',
u'timestamp': u'*',
u'classname': u'PropertyOne', u'classname': u'PropertyOne',
u'SetUpProp': u'1', u'SetUpProp': u'1',
u'TestSomeProperty': u'1', u'TestSomeProperty': u'1',
...@@ -108,10 +111,13 @@ EXPECTED_2 = { ...@@ -108,10 +111,13 @@ EXPECTED_2 = {
0, 0,
u'time': u'time':
u'*', u'*',
u'timestamp':
u'*',
u'testsuite': [{ u'testsuite': [{
u'name': u'TestSomeProperties', u'name': u'TestSomeProperties',
u'status': u'RUN', u'status': u'RUN',
u'result': u'COMPLETED', u'result': u'COMPLETED',
u'timestamp': u'*',
u'time': u'*', u'time': u'*',
u'classname': u'PropertyTwo', u'classname': u'PropertyTwo',
u'SetUpProp': u'2', u'SetUpProp': u'2',
......
...@@ -42,8 +42,8 @@ GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_" ...@@ -42,8 +42,8 @@ GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_"
EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests"> <testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
<testsuite name="PropertyOne" tests="1" failures="0" disabled="0" errors="0" time="*"> <testsuite name="PropertyOne" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
<testcase name="TestSomeProperties" status="run" result="completed" time="*" classname="PropertyOne"> <testcase name="TestSomeProperties" status="run" result="completed" time="*" timestamp="*" classname="PropertyOne">
<properties> <properties>
<property name="SetUpProp" value="1"/> <property name="SetUpProp" value="1"/>
<property name="TestSomeProperty" value="1"/> <property name="TestSomeProperty" value="1"/>
...@@ -56,8 +56,8 @@ EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?> ...@@ -56,8 +56,8 @@ EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests"> <testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
<testsuite name="PropertyTwo" tests="1" failures="0" disabled="0" errors="0" time="*"> <testsuite name="PropertyTwo" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
<testcase name="TestSomeProperties" status="run" result="completed" time="*" classname="PropertyTwo"> <testcase name="TestSomeProperties" status="run" result="completed" time="*" timestamp="*" classname="PropertyTwo">
<properties> <properties>
<property name="SetUpProp" value="2"/> <property name="SetUpProp" value="2"/>
<property name="TestSomeProperty" value="2"/> <property name="TestSomeProperty" value="2"/>
......
...@@ -169,7 +169,7 @@ class GTestXMLTestCase(gtest_test_utils.TestCase): ...@@ -169,7 +169,7 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
* The stack traces are removed. * The stack traces are removed.
""" """
if element.tagName == 'testsuites': if element.tagName in ('testsuites', 'testsuite', 'testcase'):
timestamp = element.getAttributeNode('timestamp') timestamp = element.getAttributeNode('timestamp')
timestamp.value = re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d$', timestamp.value = re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d$',
'*', timestamp.value) '*', timestamp.value)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment