From fb19f57880f6d52b922413ba80f244bb39becdd5 Mon Sep 17 00:00:00 2001 From: Calum Robinson Date: Wed, 18 Mar 2020 18:31:46 +0000 Subject: [PATCH] Add GTEST_BRIEF option Only prints failures and a total pass count --- googletest/docs/advanced.md | 6 + googletest/include/gtest/gtest.h | 3 + googletest/src/gtest-internal-inl.h | 4 + googletest/src/gtest.cc | 166 +++++++++++++++++--- googletest/test/googletest-env-var-test.py | 1 + googletest/test/googletest-env-var-test_.cc | 5 + googletest/test/gtest_help_test.py | 1 + googletest/test/gtest_unittest.cc | 44 ++++++ 8 files changed, 204 insertions(+), 26 deletions(-) diff --git a/googletest/docs/advanced.md b/googletest/docs/advanced.md index 5677643d..5a46083c 100644 --- a/googletest/docs/advanced.md +++ b/googletest/docs/advanced.md @@ -2252,6 +2252,12 @@ disable colors, or let googletest decide. When the value is `auto`, googletest will use colors if and only if the output goes to a terminal and (on non-Windows platforms) the `TERM` environment variable is set to `xterm` or `xterm-color`. +#### Suppressing test passes + +By default, googletest prints 1 line of output for each test, indicating if it +passed or failed. To show only test failures, run the test program with +`--gtest_brief=1`, or set the GTEST_BRIEF environment variable to `1`. + #### Suppressing the Elapsed Time By default, googletest prints the time it takes to run each test. To disable diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index 0139fccf..af5e6b58 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -117,6 +117,9 @@ GTEST_DECLARE_bool_(list_tests); // in addition to its normal textual output. GTEST_DECLARE_string_(output); +// This flags control whether Google Test prints only test failures. +GTEST_DECLARE_bool_(brief); + // This flags control whether Google Test prints the elapsed time for each // test. GTEST_DECLARE_bool_(print_time); diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h index e42ff475..dbeef167 100644 --- a/googletest/src/gtest-internal-inl.h +++ b/googletest/src/gtest-internal-inl.h @@ -87,6 +87,7 @@ const char kColorFlag[] = "color"; const char kFilterFlag[] = "filter"; const char kListTestsFlag[] = "list_tests"; const char kOutputFlag[] = "output"; +const char kBriefFlag[] = "brief"; const char kPrintTimeFlag[] = "print_time"; const char kPrintUTF8Flag[] = "print_utf8"; const char kRandomSeedFlag[] = "random_seed"; @@ -168,6 +169,7 @@ class GTestFlagSaver { internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); list_tests_ = GTEST_FLAG(list_tests); output_ = GTEST_FLAG(output); + brief_ = GTEST_FLAG(brief); print_time_ = GTEST_FLAG(print_time); print_utf8_ = GTEST_FLAG(print_utf8); random_seed_ = GTEST_FLAG(random_seed); @@ -190,6 +192,7 @@ class GTestFlagSaver { GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; GTEST_FLAG(list_tests) = list_tests_; GTEST_FLAG(output) = output_; + GTEST_FLAG(brief) = brief_; GTEST_FLAG(print_time) = print_time_; GTEST_FLAG(print_utf8) = print_utf8_; GTEST_FLAG(random_seed) = random_seed_; @@ -212,6 +215,7 @@ class GTestFlagSaver { std::string internal_run_death_test_; bool list_tests_; std::string output_; + bool brief_; bool print_time_; bool print_utf8_; int32_t random_seed_; diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index 2eb2ecb8..3121ff89 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -273,6 +273,10 @@ GTEST_DEFINE_string_( "executable's name and, if necessary, made unique by adding " "digits."); +GTEST_DEFINE_bool_( + brief, internal::BoolFromGTestEnv("brief", false), + "True if only test failures should be displayed in text output."); + GTEST_DEFINE_bool_(print_time, internal::BoolFromGTestEnv("print_time", true), "True if and only if " GTEST_NAME_ " should display elapsed time in text output."); @@ -3566,6 +3570,110 @@ void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, // End PrettyUnitTestResultPrinter +// This class implements the TestEventListener interface. +// +// Class BriefUnitTestResultPrinter is copyable. +class BriefUnitTestResultPrinter : public TestEventListener { + public: + BriefUnitTestResultPrinter() {} + static void PrintTestName(const char* test_suite, const char* test) { + printf("%s.%s", test_suite, test); + } + + // The following methods override what's in the TestEventListener class. + void OnTestProgramStart(const UnitTest& /*unit_test*/) override {} + void OnTestIterationStart(const UnitTest& /*unit_test*/, int /*iteration*/) override { + } + void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {} + void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {} +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseStart(const TestCase& /*test_case*/) override {} +#else + void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {} +#endif // OnTestCaseStart + + void OnTestStart(const TestInfo& /*test_info*/) override {} + + void OnTestPartResult(const TestPartResult& result) override; + void OnTestEnd(const TestInfo& test_info) override; +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseEnd(const TestCase& /*test_case*/) override {} +#else + void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + + void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {} + void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {} + void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} +}; + +// Called after an assertion failure. +void BriefUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + switch (result.type()) { + // If the test part succeeded, we don't need to do anything. + case TestPartResult::kSuccess: + return; + default: + // Print failure message from the assertion + // (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); + } +} + +void BriefUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Failed()) { + ColoredPrintf(GTestColor::kRed, "[ FAILED ] "); + PrintTestName(test_info.test_suite_name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", + internal::StreamableToString(test_info.result()->elapsed_time()) + .c_str()); + } else { + printf("\n"); + } + fflush(stdout); + } +} + +void BriefUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(GTestColor::kGreen, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(GTestColor::kGreen, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + const int skipped_test_count = unit_test.skipped_test_count(); + if (skipped_test_count > 0) { + ColoredPrintf(GTestColor::kGreen, "[ SKIPPED ] "); + printf("%s.\n", FormatTestCount(skipped_test_count).c_str()); + } + + int num_disabled = unit_test.reportable_disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (unit_test.Passed()) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(GTestColor::kYellow, " YOU HAVE %d DISABLED %s\n\n", + num_disabled, num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End BriefUnitTestResultPrinter + // class TestEventRepeater // // This class forwards events to other event listeners. @@ -5316,6 +5424,10 @@ void UnitTestImpl::PostFlagParsingInit() { // to shut down the default XML output before invoking RUN_ALL_TESTS. ConfigureXmlOutput(); + if (GTEST_FLAG(brief)) { + listeners()->SetDefaultResultPrinter(new BriefUnitTestResultPrinter); + } + #if GTEST_CAN_STREAM_RESULTS_ // Configures listeners for streaming test results to the specified server. ConfigureStreamingOutput(); @@ -6087,6 +6199,8 @@ static const char kColorEncodedHelpMessage[] = "Test Output:\n" " @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" " Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "brief=1@D\n" +" Only print test failures.\n" " -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" " Don't print the elapsed time of each test.\n" " @G--" GTEST_FLAG_PREFIX_ "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G" @@ -6122,36 +6236,36 @@ static const char kColorEncodedHelpMessage[] = "For more information, please read the " GTEST_NAME_ " documentation at\n" "@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" "(not one in your own code or tests), please report it to\n" -"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + "@G<" GTEST_DEV_EMAIL_ ">@D.\n"; static bool ParseGoogleTestFlag(const char* const arg) { return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, >EST_FLAG(also_run_disabled_tests)) || - ParseBoolFlag(arg, kBreakOnFailureFlag, - >EST_FLAG(break_on_failure)) || - ParseBoolFlag(arg, kCatchExceptionsFlag, - >EST_FLAG(catch_exceptions)) || - ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || - ParseStringFlag(arg, kDeathTestStyleFlag, - >EST_FLAG(death_test_style)) || - ParseBoolFlag(arg, kDeathTestUseFork, - >EST_FLAG(death_test_use_fork)) || - ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || - ParseStringFlag(arg, kInternalRunDeathTestFlag, - >EST_FLAG(internal_run_death_test)) || - ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || - ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || - ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || - ParseBoolFlag(arg, kPrintUTF8Flag, >EST_FLAG(print_utf8)) || - ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || - ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || - ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || - ParseInt32Flag(arg, kStackTraceDepthFlag, - >EST_FLAG(stack_trace_depth)) || - ParseStringFlag(arg, kStreamResultToFlag, - >EST_FLAG(stream_result_to)) || - ParseBoolFlag(arg, kThrowOnFailureFlag, - >EST_FLAG(throw_on_failure)); + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kBriefFlag, >EST_FLAG(brief)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseBoolFlag(arg, kPrintUTF8Flag, >EST_FLAG(print_utf8)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, >EST_FLAG(throw_on_failure)); } #if GTEST_USE_OWN_FLAGFILE_FLAG_ diff --git a/googletest/test/googletest-env-var-test.py b/googletest/test/googletest-env-var-test.py index 2f0e406a..ce044fb5 100755 --- a/googletest/test/googletest-env-var-test.py +++ b/googletest/test/googletest-env-var-test.py @@ -88,6 +88,7 @@ class GTestEnvVarTest(gtest_test_utils.TestCase): TestFlag('filter', 'FooTest.Bar', '*') SetEnvVar('XML_OUTPUT_FILE', None) # For 'output' test TestFlag('output', 'xml:tmp/foo.xml', '') + TestFlag('brief', '1', '0') TestFlag('print_time', '0', '1') TestFlag('repeat', '999', '1') TestFlag('throw_on_failure', '1', '0') diff --git a/googletest/test/googletest-env-var-test_.cc b/googletest/test/googletest-env-var-test_.cc index fd2aa82f..295ff8ec 100644 --- a/googletest/test/googletest-env-var-test_.cc +++ b/googletest/test/googletest-env-var-test_.cc @@ -82,6 +82,11 @@ void PrintFlag(const char* flag) { return; } + if (strcmp(flag, "brief") == 0) { + cout << GTEST_FLAG(brief); + return; + } + if (strcmp(flag, "print_time") == 0) { cout << GTEST_FLAG(print_time); return; diff --git a/googletest/test/gtest_help_test.py b/googletest/test/gtest_help_test.py index 582d24c2..609615e8 100755 --- a/googletest/test/gtest_help_test.py +++ b/googletest/test/gtest_help_test.py @@ -68,6 +68,7 @@ HELP_REGEX = re.compile( FLAG_PREFIX + r'shuffle.*' + FLAG_PREFIX + r'random_seed=.*' + FLAG_PREFIX + r'color=.*' + + FLAG_PREFIX + r'brief.*' + FLAG_PREFIX + r'print_time.*' + FLAG_PREFIX + r'output=.*' + FLAG_PREFIX + r'break_on_failure.*' + diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 06c5e671..6b9ab459 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -44,6 +44,7 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) { || testing::GTEST_FLAG(filter) != "unknown" || testing::GTEST_FLAG(list_tests) || testing::GTEST_FLAG(output) != "unknown" + || testing::GTEST_FLAG(brief) || testing::GTEST_FLAG(print_time) || testing::GTEST_FLAG(random_seed) || testing::GTEST_FLAG(repeat) > 0 @@ -205,6 +206,7 @@ using testing::GTEST_FLAG(death_test_use_fork); using testing::GTEST_FLAG(filter); using testing::GTEST_FLAG(list_tests); using testing::GTEST_FLAG(output); +using testing::GTEST_FLAG(brief); using testing::GTEST_FLAG(print_time); using testing::GTEST_FLAG(random_seed); using testing::GTEST_FLAG(repeat); @@ -1601,6 +1603,7 @@ class GTestFlagSaverTest : public Test { GTEST_FLAG(filter) = ""; GTEST_FLAG(list_tests) = false; GTEST_FLAG(output) = ""; + GTEST_FLAG(brief) = false; GTEST_FLAG(print_time) = true; GTEST_FLAG(random_seed) = 0; GTEST_FLAG(repeat) = 1; @@ -1628,6 +1631,7 @@ class GTestFlagSaverTest : public Test { EXPECT_STREQ("", GTEST_FLAG(filter).c_str()); EXPECT_FALSE(GTEST_FLAG(list_tests)); EXPECT_STREQ("", GTEST_FLAG(output).c_str()); + EXPECT_FALSE(GTEST_FLAG(brief)); EXPECT_TRUE(GTEST_FLAG(print_time)); EXPECT_EQ(0, GTEST_FLAG(random_seed)); EXPECT_EQ(1, GTEST_FLAG(repeat)); @@ -1644,6 +1648,7 @@ class GTestFlagSaverTest : public Test { GTEST_FLAG(filter) = "abc"; GTEST_FLAG(list_tests) = true; GTEST_FLAG(output) = "xml:foo.xml"; + GTEST_FLAG(brief) = true; GTEST_FLAG(print_time) = false; GTEST_FLAG(random_seed) = 1; GTEST_FLAG(repeat) = 100; @@ -5502,6 +5507,7 @@ struct Flags { filter(""), list_tests(false), output(""), + brief(false), print_time(true), random_seed(0), repeat(1), @@ -5568,6 +5574,14 @@ struct Flags { return flags; } + // Creates a Flags struct where the gtest_brief flag has the given + // value. + static Flags Brief(bool brief) { + Flags flags; + flags.brief = brief; + return flags; + } + // Creates a Flags struct where the gtest_print_time flag has the given // value. static Flags PrintTime(bool print_time) { @@ -5632,6 +5646,7 @@ struct Flags { const char* filter; bool list_tests; const char* output; + bool brief; bool print_time; int32_t random_seed; int32_t repeat; @@ -5653,6 +5668,7 @@ class ParseFlagsTest : public Test { GTEST_FLAG(filter) = ""; GTEST_FLAG(list_tests) = false; GTEST_FLAG(output) = ""; + GTEST_FLAG(brief) = false; GTEST_FLAG(print_time) = true; GTEST_FLAG(random_seed) = 0; GTEST_FLAG(repeat) = 1; @@ -5683,6 +5699,7 @@ class ParseFlagsTest : public Test { EXPECT_STREQ(expected.filter, GTEST_FLAG(filter).c_str()); EXPECT_EQ(expected.list_tests, GTEST_FLAG(list_tests)); EXPECT_STREQ(expected.output, GTEST_FLAG(output).c_str()); + EXPECT_EQ(expected.brief, GTEST_FLAG(brief)); EXPECT_EQ(expected.print_time, GTEST_FLAG(print_time)); EXPECT_EQ(expected.random_seed, GTEST_FLAG(random_seed)); EXPECT_EQ(expected.repeat, GTEST_FLAG(repeat)); @@ -5965,6 +5982,33 @@ TEST_F(ParseFlagsTest, OutputXmlDirectory) { Flags::Output("xml:directory/path/"), false); } +// Tests having a --gtest_brief flag +TEST_F(ParseFlagsTest, BriefFlag) { + const char* argv[] = {"foo.exe", "--gtest_brief", nullptr}; + + const char* argv2[] = {"foo.exe", nullptr}; + + GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Brief(true), false); +} + +// Tests having a --gtest_brief flag with a "true" value +TEST_F(ParseFlagsTest, BriefFlagTrue) { + const char* argv[] = {"foo.exe", "--gtest_brief=1", nullptr}; + + const char* argv2[] = {"foo.exe", nullptr}; + + GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Brief(true), false); +} + +// Tests having a --gtest_brief flag with a "false" value +TEST_F(ParseFlagsTest, BriefFlagFalse) { + const char* argv[] = {"foo.exe", "--gtest_brief=0", nullptr}; + + const char* argv2[] = {"foo.exe", nullptr}; + + GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Brief(false), false); +} + // Tests having a --gtest_print_time flag TEST_F(ParseFlagsTest, PrintTimeFlag) { const char* argv[] = {"foo.exe", "--gtest_print_time", nullptr};