Commit f5fa71f7 authored by vladlosev's avatar vladlosev
Browse files

Implements support for calling Test::RecordProperty() outside of a test.

parent 5f18b68b
...@@ -158,6 +158,7 @@ class StreamingListenerTest; ...@@ -158,6 +158,7 @@ class StreamingListenerTest;
class TestResultAccessor; class TestResultAccessor;
class TestEventListenersAccessor; class TestEventListenersAccessor;
class TestEventRepeater; class TestEventRepeater;
class UnitTestRecordPropertyTestHelper;
class WindowsDeathTest; class WindowsDeathTest;
class UnitTestImpl* GetUnitTestImpl(); class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResult::Type result_type, void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
...@@ -381,20 +382,21 @@ class GTEST_API_ Test { ...@@ -381,20 +382,21 @@ class GTEST_API_ Test {
// non-fatal) failure. // non-fatal) failure.
static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
// Logs a property for the current test. Only the last value for a given // Logs a property for the current test, test case, or for the entire
// key is remembered. // invocation of the test program when used outside of the context of a
// These are public static so they can be called from utility functions // test case. Only the last value for a given key is remembered. These
// that are not members of the test fixture. // are public static so they can be called from utility functions that are
// The arguments are const char* instead strings, as Google Test is used // not members of the test fixture. Calls to RecordProperty made during
// on platforms where string doesn't compile. // lifespan of the test (from the moment its constructor starts to the
// // moment its destructor finishes) will be output in XML as attributes of
// Note that a driving consideration for these RecordProperty methods // the <testcase> element. Properties recorded from fixture's
// was to produce xml output suited to the Greenspan charting utility, // SetUpTestCase or TearDownTestCase are logged as attributes of the
// which at present will only chart values that fit in a 32-bit int. It // corresponding <testsuite> element. Calls to RecordProperty made in the
// is the user's responsibility to restrict their values to 32-bit ints // global context (before or after invocation of RUN_ALL_TESTS and from
// if they intend them to be used with Greenspan. // SetUp/TearDown method of Environment objects registered with Google
static void RecordProperty(const char* key, const char* value); // Test) will be output as attributes of the <testsuites> element.
static void RecordProperty(const char* key, int value); static void RecordProperty(const std::string& key, const std::string& value);
static void RecordProperty(const std::string& key, int value);
protected: protected:
// Creates a Test object. // Creates a Test object.
...@@ -463,7 +465,7 @@ class TestProperty { ...@@ -463,7 +465,7 @@ class TestProperty {
// C'tor. TestProperty does NOT have a default constructor. // C'tor. TestProperty does NOT have a default constructor.
// Always use this constructor (with parameters) to create a // Always use this constructor (with parameters) to create a
// TestProperty object. // TestProperty object.
TestProperty(const char* a_key, const char* a_value) : TestProperty(const std::string& a_key, const std::string& a_value) :
key_(a_key), value_(a_value) { key_(a_key), value_(a_value) {
} }
...@@ -478,7 +480,7 @@ class TestProperty { ...@@ -478,7 +480,7 @@ class TestProperty {
} }
// Sets a new value, overriding the one supplied in the constructor. // Sets a new value, overriding the one supplied in the constructor.
void SetValue(const char* new_value) { void SetValue(const std::string& new_value) {
value_ = new_value; value_ = new_value;
} }
...@@ -537,6 +539,7 @@ class GTEST_API_ TestResult { ...@@ -537,6 +539,7 @@ class GTEST_API_ TestResult {
private: private:
friend class TestInfo; friend class TestInfo;
friend class TestCase;
friend class UnitTest; friend class UnitTest;
friend class internal::DefaultGlobalTestPartResultReporter; friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::ExecDeathTest; friend class internal::ExecDeathTest;
...@@ -561,13 +564,16 @@ class GTEST_API_ TestResult { ...@@ -561,13 +564,16 @@ class GTEST_API_ TestResult {
// a non-fatal failure if invalid (e.g., if it conflicts with reserved // a non-fatal failure if invalid (e.g., if it conflicts with reserved
// key names). If a property is already recorded for the same key, the // key names). If a property is already recorded for the same key, the
// value will be updated, rather than storing multiple values for the same // value will be updated, rather than storing multiple values for the same
// key. // key. xml_element specifies the element for which the property is being
void RecordProperty(const TestProperty& test_property); // recorded and is used for validation.
void RecordProperty(const std::string& xml_element,
const TestProperty& test_property);
// Adds a failure if the key is a reserved attribute of Google Test // Adds a failure if the key is a reserved attribute of Google Test
// testcase tags. Returns true if the property is valid. // testcase tags. Returns true if the property is valid.
// TODO(russr): Validate attribute names are legal and human readable. // TODO(russr): Validate attribute names are legal and human readable.
static bool ValidateTestProperty(const TestProperty& test_property); static bool ValidateTestProperty(const std::string& xml_element,
const TestProperty& test_property);
// Adds a test part result to the list. // Adds a test part result to the list.
void AddTestPartResult(const TestPartResult& test_part_result); void AddTestPartResult(const TestPartResult& test_part_result);
...@@ -792,6 +798,10 @@ class GTEST_API_ TestCase { ...@@ -792,6 +798,10 @@ class GTEST_API_ TestCase {
// 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;
// Returns the TestResult that holds test properties recorded during
// execution of SetUpTestCase and TearDownTestCase.
const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
private: private:
friend class Test; friend class Test;
friend class internal::UnitTestImpl; friend class internal::UnitTestImpl;
...@@ -880,6 +890,9 @@ class GTEST_API_ TestCase { ...@@ -880,6 +890,9 @@ class GTEST_API_ TestCase {
bool should_run_; bool should_run_;
// Elapsed time, in milliseconds. // Elapsed time, in milliseconds.
TimeInMillis elapsed_time_; TimeInMillis elapsed_time_;
// Holds test properties recorded during execution of SetUpTestCase and
// TearDownTestCase.
TestResult ad_hoc_test_result_;
// We disallow copying TestCases. // We disallow copying TestCases.
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
...@@ -1165,6 +1178,10 @@ class GTEST_API_ UnitTest { ...@@ -1165,6 +1178,10 @@ class GTEST_API_ UnitTest {
// total_test_case_count() - 1. If i is not in that range, returns NULL. // total_test_case_count() - 1. If i is not in that range, returns NULL.
const TestCase* GetTestCase(int i) const; const TestCase* GetTestCase(int i) const;
// Returns the TestResult containing information on test failures and
// properties logged outside of individual test cases.
const TestResult& ad_hoc_test_result() const;
// Returns the list of event listeners that can be used to track events // Returns the list of event listeners that can be used to track events
// inside Google Test. // inside Google Test.
TestEventListeners& listeners(); TestEventListeners& listeners();
...@@ -1192,9 +1209,12 @@ class GTEST_API_ UnitTest { ...@@ -1192,9 +1209,12 @@ class GTEST_API_ UnitTest {
const std::string& os_stack_trace) const std::string& os_stack_trace)
GTEST_LOCK_EXCLUDED_(mutex_); GTEST_LOCK_EXCLUDED_(mutex_);
// Adds a TestProperty to the current TestResult object. If the result already // Adds a TestProperty to the current TestResult object when invoked from
// contains a property with the same key, the value will be updated. // inside a test, to current TestCase's ad_hoc_test_result_ when invoked
void RecordPropertyForCurrentTest(const char* key, const char* value); // from SetUpTestCase or TearDownTestCase, or to the global property set
// when invoked elsewhere. If the result already contains a property with
// the same key, the value will be updated.
void RecordProperty(const std::string& key, const std::string& value);
// Gets the i-th test case among all the test cases. i can range from 0 to // Gets the i-th test case among all the test cases. i can range from 0 to
// total_test_case_count() - 1. If i is not in that range, returns NULL. // total_test_case_count() - 1. If i is not in that range, returns NULL.
...@@ -1210,6 +1230,7 @@ class GTEST_API_ UnitTest { ...@@ -1210,6 +1230,7 @@ class GTEST_API_ UnitTest {
friend class internal::AssertHelper; friend class internal::AssertHelper;
friend class internal::ScopedTrace; friend class internal::ScopedTrace;
friend class internal::StreamingListenerTest; friend class internal::StreamingListenerTest;
friend class internal::UnitTestRecordPropertyTestHelper;
friend Environment* AddGlobalTestEnvironment(Environment* env); friend Environment* AddGlobalTestEnvironment(Environment* env);
friend internal::UnitTestImpl* internal::GetUnitTestImpl(); friend internal::UnitTestImpl* internal::GetUnitTestImpl();
friend void internal::ReportFailureInUnknownLocation( friend void internal::ReportFailureInUnknownLocation(
......
...@@ -348,8 +348,7 @@ class TestPropertyKeyIs { ...@@ -348,8 +348,7 @@ class TestPropertyKeyIs {
// Constructor. // Constructor.
// //
// TestPropertyKeyIs has NO default constructor. // TestPropertyKeyIs has NO default constructor.
explicit TestPropertyKeyIs(const char* key) explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
: key_(key) {}
// Returns true iff the test name of test property matches on key_. // Returns true iff the test name of test property matches on key_.
bool operator()(const TestProperty& test_property) const { bool operator()(const TestProperty& test_property) const {
...@@ -712,6 +711,12 @@ class GTEST_API_ UnitTestImpl { ...@@ -712,6 +711,12 @@ class GTEST_API_ UnitTestImpl {
ad_hoc_test_result_.Clear(); ad_hoc_test_result_.Clear();
} }
// Adds a TestProperty to the current TestResult object when invoked in a
// context of a test or a test case, or to the global property set. If the
// result already contains a property with the same key, the value will be
// updated.
void RecordProperty(const TestProperty& test_property);
enum ReactionToSharding { enum ReactionToSharding {
HONOR_SHARDING_PROTOCOL, HONOR_SHARDING_PROTOCOL,
IGNORE_SHARDING_PROTOCOL IGNORE_SHARDING_PROTOCOL
...@@ -1038,8 +1043,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) { ...@@ -1038,8 +1043,9 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
class TestResultAccessor { class TestResultAccessor {
public: public:
static void RecordProperty(TestResult* test_result, static void RecordProperty(TestResult* test_result,
const std::string& xml_element,
const TestProperty& property) { const TestProperty& property) {
test_result->RecordProperty(property); test_result->RecordProperty(xml_element, property);
} }
static void ClearTestPartResults(TestResult* test_result) { static void ClearTestPartResults(TestResult* test_result) {
......
This diff is collapsed.
...@@ -180,6 +180,18 @@ class TestEventListenersAccessor { ...@@ -180,6 +180,18 @@ class TestEventListenersAccessor {
} }
}; };
class UnitTestRecordPropertyTestHelper : public Test {
protected:
UnitTestRecordPropertyTestHelper() {}
// Forwards to UnitTest::RecordProperty() to bypass access controls.
void UnitTestRecordProperty(const char* key, const std::string& value) {
unit_test_.RecordProperty(key, value);
}
UnitTest unit_test_;
};
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
...@@ -188,6 +200,7 @@ using testing::AssertionResult; ...@@ -188,6 +200,7 @@ using testing::AssertionResult;
using testing::AssertionSuccess; using testing::AssertionSuccess;
using testing::DoubleLE; using testing::DoubleLE;
using testing::EmptyTestEventListener; using testing::EmptyTestEventListener;
using testing::Environment;
using testing::FloatLE; using testing::FloatLE;
using testing::GTEST_FLAG(also_run_disabled_tests); using testing::GTEST_FLAG(also_run_disabled_tests);
using testing::GTEST_FLAG(break_on_failure); using testing::GTEST_FLAG(break_on_failure);
...@@ -213,6 +226,7 @@ using testing::StaticAssertTypeEq; ...@@ -213,6 +226,7 @@ using testing::StaticAssertTypeEq;
using testing::Test; using testing::Test;
using testing::TestCase; using testing::TestCase;
using testing::TestEventListeners; using testing::TestEventListeners;
using testing::TestInfo;
using testing::TestPartResult; using testing::TestPartResult;
using testing::TestPartResultArray; using testing::TestPartResultArray;
using testing::TestProperty; using testing::TestProperty;
...@@ -1447,7 +1461,7 @@ TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) { ...@@ -1447,7 +1461,7 @@ TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) {
TEST(TestResultPropertyTest, OnePropertyFoundWhenAdded) { TEST(TestResultPropertyTest, OnePropertyFoundWhenAdded) {
TestResult test_result; TestResult test_result;
TestProperty property("key_1", "1"); TestProperty property("key_1", "1");
TestResultAccessor::RecordProperty(&test_result, property); TestResultAccessor::RecordProperty(&test_result, "testcase", property);
ASSERT_EQ(1, test_result.test_property_count()); ASSERT_EQ(1, test_result.test_property_count());
const TestProperty& actual_property = test_result.GetTestProperty(0); const TestProperty& actual_property = test_result.GetTestProperty(0);
EXPECT_STREQ("key_1", actual_property.key()); EXPECT_STREQ("key_1", actual_property.key());
...@@ -1459,8 +1473,8 @@ TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) { ...@@ -1459,8 +1473,8 @@ TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
TestResult test_result; TestResult test_result;
TestProperty property_1("key_1", "1"); TestProperty property_1("key_1", "1");
TestProperty property_2("key_2", "2"); TestProperty property_2("key_2", "2");
TestResultAccessor::RecordProperty(&test_result, property_1); TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
TestResultAccessor::RecordProperty(&test_result, property_2); TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
ASSERT_EQ(2, test_result.test_property_count()); ASSERT_EQ(2, test_result.test_property_count());
const TestProperty& actual_property_1 = test_result.GetTestProperty(0); const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
EXPECT_STREQ("key_1", actual_property_1.key()); EXPECT_STREQ("key_1", actual_property_1.key());
...@@ -1478,10 +1492,10 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) { ...@@ -1478,10 +1492,10 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
TestProperty property_2_1("key_2", "2"); TestProperty property_2_1("key_2", "2");
TestProperty property_1_2("key_1", "12"); TestProperty property_1_2("key_1", "12");
TestProperty property_2_2("key_2", "22"); TestProperty property_2_2("key_2", "22");
TestResultAccessor::RecordProperty(&test_result, property_1_1); TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_1);
TestResultAccessor::RecordProperty(&test_result, property_2_1); TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_1);
TestResultAccessor::RecordProperty(&test_result, property_1_2); TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_2);
TestResultAccessor::RecordProperty(&test_result, property_2_2); TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_2);
ASSERT_EQ(2, test_result.test_property_count()); ASSERT_EQ(2, test_result.test_property_count());
const TestProperty& actual_property_1 = test_result.GetTestProperty(0); const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
...@@ -1494,14 +1508,14 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) { ...@@ -1494,14 +1508,14 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
} }
// Tests TestResult::GetTestProperty(). // Tests TestResult::GetTestProperty().
TEST(TestResultPropertyDeathTest, GetTestProperty) { TEST(TestResultPropertyTest, GetTestProperty) {
TestResult test_result; TestResult test_result;
TestProperty property_1("key_1", "1"); TestProperty property_1("key_1", "1");
TestProperty property_2("key_2", "2"); TestProperty property_2("key_2", "2");
TestProperty property_3("key_3", "3"); TestProperty property_3("key_3", "3");
TestResultAccessor::RecordProperty(&test_result, property_1); TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
TestResultAccessor::RecordProperty(&test_result, property_2); TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
TestResultAccessor::RecordProperty(&test_result, property_3); TestResultAccessor::RecordProperty(&test_result, "testcase", property_3);
const TestProperty& fetched_property_1 = test_result.GetTestProperty(0); const TestProperty& fetched_property_1 = test_result.GetTestProperty(0);
const TestProperty& fetched_property_2 = test_result.GetTestProperty(1); const TestProperty& fetched_property_2 = test_result.GetTestProperty(1);
...@@ -1520,42 +1534,6 @@ TEST(TestResultPropertyDeathTest, GetTestProperty) { ...@@ -1520,42 +1534,6 @@ TEST(TestResultPropertyDeathTest, GetTestProperty) {
EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(-1), ""); EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(-1), "");
} }
// When a property using a reserved key is supplied to this function, it tests
// that a non-fatal failure is added, a fatal failure is not added, and that the
// property is not recorded.
void ExpectNonFatalFailureRecordingPropertyWithReservedKey(const char* key) {
TestResult test_result;
TestProperty property(key, "1");
EXPECT_NONFATAL_FAILURE(
TestResultAccessor::RecordProperty(&test_result, property),
"Reserved key");
ASSERT_EQ(0, test_result.test_property_count()) << "Not recorded";
}
// Attempting to recording a property with the Reserved literal "name"
// should add a non-fatal failure and the property should not be recorded.
TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledName) {
ExpectNonFatalFailureRecordingPropertyWithReservedKey("name");
}
// Attempting to recording a property with the Reserved literal "status"
// should add a non-fatal failure and the property should not be recorded.
TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledStatus) {
ExpectNonFatalFailureRecordingPropertyWithReservedKey("status");
}
// Attempting to recording a property with the Reserved literal "time"
// should add a non-fatal failure and the property should not be recorded.
TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledTime) {
ExpectNonFatalFailureRecordingPropertyWithReservedKey("time");
}
// Attempting to recording a property with the Reserved literal "classname"
// should add a non-fatal failure and the property should not be recorded.
TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledClassname) {
ExpectNonFatalFailureRecordingPropertyWithReservedKey("classname");
}
// Tests that GTestFlagSaver works on Windows and Mac. // Tests that GTestFlagSaver works on Windows and Mac.
class GTestFlagSaverTest : public Test { class GTestFlagSaverTest : public Test {
...@@ -1961,6 +1939,168 @@ TEST(UnitTestTest, ReturnsPlausibleTimestamp) { ...@@ -1961,6 +1939,168 @@ TEST(UnitTestTest, ReturnsPlausibleTimestamp) {
EXPECT_LE(UnitTest::GetInstance()->start_timestamp(), GetTimeInMillis()); EXPECT_LE(UnitTest::GetInstance()->start_timestamp(), GetTimeInMillis());
} }
// When a property using a reserved key is supplied to this function, it
// tests that a non-fatal failure is added, a fatal failure is not added,
// and that the property is not recorded.
void ExpectNonFatalFailureRecordingPropertyWithReservedKey(
const TestResult& test_result, const char* key) {
EXPECT_NONFATAL_FAILURE(Test::RecordProperty(key, "1"), "Reserved key");
ASSERT_EQ(0, test_result.test_property_count()) << "Property for key '" << key
<< "' recorded unexpectedly.";
}
void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
const char* key) {
const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
ASSERT_TRUE(test_info != NULL);
ExpectNonFatalFailureRecordingPropertyWithReservedKey(*test_info->result(),
key);
}
void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
const char* key) {
const TestCase* test_case = UnitTest::GetInstance()->current_test_case();
ASSERT_TRUE(test_case != NULL);
ExpectNonFatalFailureRecordingPropertyWithReservedKey(
test_case->ad_hoc_test_result(), key);
}
void ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
const char* key) {
ExpectNonFatalFailureRecordingPropertyWithReservedKey(
UnitTest::GetInstance()->ad_hoc_test_result(), key);
}
// Tests that property recording functions in UnitTest outside of tests
// functions correcly. Creating a separate instance of UnitTest ensures it
// is in a state similar to the UnitTest's singleton's between tests.
class UnitTestRecordPropertyTest :
public testing::internal::UnitTestRecordPropertyTestHelper {
public:
static void SetUpTestCase() {
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
"disabled");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
"errors");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
"failures");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
"name");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
"tests");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
"time");
Test::RecordProperty("test_case_key_1", "1");
const TestCase* test_case = UnitTest::GetInstance()->current_test_case();
ASSERT_TRUE(test_case != NULL);
ASSERT_EQ(1, test_case->ad_hoc_test_result().test_property_count());
EXPECT_STREQ("test_case_key_1",
test_case->ad_hoc_test_result().GetTestProperty(0).key());
EXPECT_STREQ("1",
test_case->ad_hoc_test_result().GetTestProperty(0).value());
}
};
// Tests TestResult has the expected property when added.
TEST_F(UnitTestRecordPropertyTest, OnePropertyFoundWhenAdded) {
UnitTestRecordProperty("key_1", "1");
ASSERT_EQ(1, unit_test_.ad_hoc_test_result().test_property_count());
EXPECT_STREQ("key_1",
unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
EXPECT_STREQ("1",
unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
}
// Tests TestResult has multiple properties when added.
TEST_F(UnitTestRecordPropertyTest, MultiplePropertiesFoundWhenAdded) {
UnitTestRecordProperty("key_1", "1");
UnitTestRecordProperty("key_2", "2");
ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
EXPECT_STREQ("key_1",
unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
EXPECT_STREQ("1", unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
EXPECT_STREQ("key_2",
unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
EXPECT_STREQ("2", unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
}
// Tests TestResult::RecordProperty() overrides values for duplicate keys.
TEST_F(UnitTestRecordPropertyTest, OverridesValuesForDuplicateKeys) {
UnitTestRecordProperty("key_1", "1");
UnitTestRecordProperty("key_2", "2");
UnitTestRecordProperty("key_1", "12");
UnitTestRecordProperty("key_2", "22");
ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
EXPECT_STREQ("key_1",
unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
EXPECT_STREQ("12",
unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
EXPECT_STREQ("key_2",
unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
EXPECT_STREQ("22",
unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
}
TEST_F(UnitTestRecordPropertyTest,
AddFailureInsideTestsWhenUsingTestCaseReservedKeys) {
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
"name");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
"value_param");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
"type_param");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
"status");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
"time");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
"classname");
}
TEST_F(UnitTestRecordPropertyTest,
AddRecordWithReservedKeysGeneratesCorrectPropertyList) {
EXPECT_NONFATAL_FAILURE(
Test::RecordProperty("name", "1"),
"'classname', 'name', 'status', 'time', 'type_param', and 'value_param'"
" are reserved");
}
class UnitTestRecordPropertyTestEnvironment : public Environment {
public:
virtual void TearDown() {
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"tests");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"failures");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"disabled");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"errors");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"name");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"timestamp");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"time");
ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
"random_seed");
}
};
// This will test property recording outside of any test or test case.
static Environment* record_property_env =
AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
// This group of tests is for predicate assertions (ASSERT_PRED*, etc) // This group of tests is for predicate assertions (ASSERT_PRED*, etc)
// of various arities. They do not attempt to be exhaustive. Rather, // of various arities. They do not attempt to be exhaustive. Rather,
// view them as smoke tests that can be easily reviewed and verified. // view them as smoke tests that can be easily reviewed and verified.
......
...@@ -57,7 +57,7 @@ else: ...@@ -57,7 +57,7 @@ else:
STACK_TRACE_TEMPLATE = '' STACK_TRACE_TEMPLATE = ''
EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="23" failures="4" disabled="2" errors="0" time="*" timestamp="*" name="AllTests"> <testsuites tests="23" failures="4" disabled="2" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*"> <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*">
<testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/> <testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
</testsuite> </testsuite>
...@@ -97,7 +97,7 @@ Invalid characters in brackets []%(stack)s]]></failure> ...@@ -97,7 +97,7 @@ Invalid characters in brackets []%(stack)s]]></failure>
<testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*"> <testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*">
<testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/> <testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/>
</testsuite> </testsuite>
<testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*"> <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*" SetUpTestCase="yes" TearDownTestCase="aye">
<testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest" key_1="1"/> <testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest" key_1="1"/>
<testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest" key_int="1"/> <testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest" key_int="1"/>
<testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest" key_1="1" key_2="2" key_3="3"/> <testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest" key_1="1" key_2="2" key_3="3"/>
......
...@@ -95,6 +95,9 @@ TEST(InvalidCharactersTest, InvalidCharactersInMessage) { ...@@ -95,6 +95,9 @@ TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
} }
class PropertyRecordingTest : public Test { class PropertyRecordingTest : public Test {
public:
static void SetUpTestCase() { RecordProperty("SetUpTestCase", "yes"); }
static void TearDownTestCase() { RecordProperty("TearDownTestCase", "aye"); }
}; };
TEST_F(PropertyRecordingTest, OneProperty) { TEST_F(PropertyRecordingTest, OneProperty) {
...@@ -120,12 +123,12 @@ TEST(NoFixtureTest, RecordProperty) { ...@@ -120,12 +123,12 @@ TEST(NoFixtureTest, RecordProperty) {
RecordProperty("key", "1"); RecordProperty("key", "1");
} }
void ExternalUtilityThatCallsRecordProperty(const char* key, int value) { void ExternalUtilityThatCallsRecordProperty(const std::string& key, int value) {
testing::Test::RecordProperty(key, value); testing::Test::RecordProperty(key, value);
} }
void ExternalUtilityThatCallsRecordProperty(const char* key, void ExternalUtilityThatCallsRecordProperty(const std::string& key,
const char* value) { const std::string& value) {
testing::Test::RecordProperty(key, value); testing::Test::RecordProperty(key, value);
} }
...@@ -173,5 +176,6 @@ int main(int argc, char** argv) { ...@@ -173,5 +176,6 @@ int main(int argc, char** argv) {
TestEventListeners& listeners = UnitTest::GetInstance()->listeners(); TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
delete listeners.Release(listeners.default_xml_generator()); delete listeners.Release(listeners.default_xml_generator());
} }
testing::Test::RecordProperty("ad_hoc_property", "42");
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
...@@ -80,7 +80,9 @@ class GTestXMLTestCase(gtest_test_utils.TestCase): ...@@ -80,7 +80,9 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
actual_attributes = actual_node .attributes actual_attributes = actual_node .attributes
self.assertEquals( self.assertEquals(
expected_attributes.length, actual_attributes.length, expected_attributes.length, actual_attributes.length,
'attribute numbers differ in element ' + actual_node.tagName) 'attribute numbers differ in element %s:\nExpected: %r\nActual: %r' % (
actual_node.tagName, expected_attributes.keys(),
actual_attributes.keys()))
for i in range(expected_attributes.length): for i in range(expected_attributes.length):
expected_attr = expected_attributes.item(i) expected_attr = expected_attributes.item(i)
actual_attr = actual_attributes.get(expected_attr.name) actual_attr = actual_attributes.get(expected_attr.name)
......
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