Skip to content

Commit 1ced315

Browse files
Abseil TeamXiaoyi Zhang
Abseil Team
authored and
Xiaoyi Zhang
committed
Googletest export
Add --gtest_fail_fast support to googletest. - Analogous functionality to to golang -test.failfast and python --failfast - Stops test execution upon first test failure. - Also add support Bazel equivalent env var (TESTBRIDGE_TEST_RUNNER_FAIL_FAST) PiperOrigin-RevId: 302488880
1 parent 749148f commit 1ced315

10 files changed

+784
-54
lines changed

googletest/docs/advanced.md

+9
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,15 @@ For example:
21162116
everything in test suite `FooTest` except `FooTest.Bar` and everything in
21172117
test suite `BarTest` except `BarTest.Foo`.
21182118

2119+
#### Stop test execution upon first failure
2120+
2121+
By default, a googletest program runs all tests the user has defined. In some
2122+
cases (e.g. iterative test development & execution) it may be desirable stop
2123+
test execution upon first failure (trading improved latency for completeness).
2124+
If `GTEST_FAIL_FAST` environment variable or `--gtest_fail_fast` flag is set,
2125+
the test runner will stop execution as soon as the first test failure is
2126+
found.
2127+
21192128
#### Temporarily Disabling Tests
21202129

21212130
If you have a broken test that you cannot fix right away, you can add the

googletest/include/gtest/gtest.h

+10
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ GTEST_DECLARE_bool_(catch_exceptions);
101101
// to let Google Test decide.
102102
GTEST_DECLARE_string_(color);
103103

104+
// This flag controls whether the test runner should continue execution past
105+
// first failure.
106+
GTEST_DECLARE_bool_(fail_fast);
107+
104108
// This flag sets up the filter to select by name using a glob pattern
105109
// the tests to run. If the filter is not given all tests are executed.
106110
GTEST_DECLARE_string_(filter);
@@ -795,6 +799,9 @@ class GTEST_API_ TestInfo {
795799
// deletes it.
796800
void Run();
797801

802+
// Skip and records the test result for this object.
803+
void Skip();
804+
798805
static void ClearTestResult(TestInfo* test_info) {
799806
test_info->result_.Clear();
800807
}
@@ -943,6 +950,9 @@ class GTEST_API_ TestSuite {
943950
// Runs every test in this TestSuite.
944951
void Run();
945952

953+
// Skips the execution of tests under this TestSuite
954+
void Skip();
955+
946956
// Runs SetUpTestSuite() for this TestSuite. This wrapper is needed
947957
// for catching exceptions thrown from SetUpTestSuite().
948958
void RunSetUpTestSuite() {

googletest/src/gtest-internal-inl.h

+4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
8484
const char kBreakOnFailureFlag[] = "break_on_failure";
8585
const char kCatchExceptionsFlag[] = "catch_exceptions";
8686
const char kColorFlag[] = "color";
87+
const char kFailFast[] = "fail_fast";
8788
const char kFilterFlag[] = "filter";
8889
const char kListTestsFlag[] = "list_tests";
8990
const char kOutputFlag[] = "output";
@@ -164,6 +165,7 @@ class GTestFlagSaver {
164165
color_ = GTEST_FLAG(color);
165166
death_test_style_ = GTEST_FLAG(death_test_style);
166167
death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
168+
fail_fast_ = GTEST_FLAG(fail_fast);
167169
filter_ = GTEST_FLAG(filter);
168170
internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
169171
list_tests_ = GTEST_FLAG(list_tests);
@@ -187,6 +189,7 @@ class GTestFlagSaver {
187189
GTEST_FLAG(death_test_style) = death_test_style_;
188190
GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
189191
GTEST_FLAG(filter) = filter_;
192+
GTEST_FLAG(fail_fast) = fail_fast_;
190193
GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
191194
GTEST_FLAG(list_tests) = list_tests_;
192195
GTEST_FLAG(output) = output_;
@@ -208,6 +211,7 @@ class GTestFlagSaver {
208211
std::string color_;
209212
std::string death_test_style_;
210213
bool death_test_use_fork_;
214+
bool fail_fast_;
211215
std::string filter_;
212216
std::string internal_run_death_test_;
213217
bool list_tests_;

googletest/src/gtest.cc

+105-25
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,21 @@ static const char* GetDefaultFilter() {
213213
return kUniversalFilter;
214214
}
215215

216+
// Bazel passes in the argument to '--test_runner_fail_fast' via the
217+
// TESTBRIDGE_TEST_RUNNER_FAIL_FAST environment variable.
218+
static bool GetDefaultFailFast() {
219+
const char* const testbridge_test_runner_fail_fast =
220+
internal::posix::GetEnv("TESTBRIDGE_TEST_RUNNER_FAIL_FAST");
221+
if (testbridge_test_runner_fail_fast != nullptr) {
222+
return strcmp(testbridge_test_runner_fail_fast, "1") == 0;
223+
}
224+
return false;
225+
}
226+
227+
GTEST_DEFINE_bool_(
228+
fail_fast, internal::BoolFromGTestEnv("fail_fast", GetDefaultFailFast()),
229+
"True if and only if a test failure should stop further test execution.");
230+
216231
GTEST_DEFINE_bool_(
217232
also_run_disabled_tests,
218233
internal::BoolFromGTestEnv("also_run_disabled_tests", false),
@@ -2863,6 +2878,28 @@ void TestInfo::Run() {
28632878
impl->set_current_test_info(nullptr);
28642879
}
28652880

2881+
// Skip and records a skipped test result for this object.
2882+
void TestInfo::Skip() {
2883+
if (!should_run_) return;
2884+
2885+
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
2886+
impl->set_current_test_info(this);
2887+
2888+
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
2889+
2890+
// Notifies the unit test event listeners that a test is about to start.
2891+
repeater->OnTestStart(*this);
2892+
2893+
const TestPartResult test_part_result =
2894+
TestPartResult(TestPartResult::kSkip, this->file(), this->line(), "");
2895+
impl->GetTestPartResultReporterForCurrentThread()->ReportTestPartResult(
2896+
test_part_result);
2897+
2898+
// Notifies the unit test event listener that a test has just finished.
2899+
repeater->OnTestEnd(*this);
2900+
impl->set_current_test_info(nullptr);
2901+
}
2902+
28662903
// class TestSuite
28672904

28682905
// Gets the number of successful tests in this test suite.
@@ -2975,6 +3012,12 @@ void TestSuite::Run() {
29753012
start_timestamp_ = internal::GetTimeInMillis();
29763013
for (int i = 0; i < total_test_count(); i++) {
29773014
GetMutableTestInfo(i)->Run();
3015+
if (GTEST_FLAG(fail_fast) && GetMutableTestInfo(i)->result()->Failed()) {
3016+
for (int j = i + 1; j < total_test_count(); j++) {
3017+
GetMutableTestInfo(j)->Skip();
3018+
}
3019+
break;
3020+
}
29783021
}
29793022
elapsed_time_ = internal::GetTimeInMillis() - start_timestamp_;
29803023

@@ -2992,6 +3035,36 @@ void TestSuite::Run() {
29923035
impl->set_current_test_suite(nullptr);
29933036
}
29943037

3038+
// Skips all tests under this TestSuite.
3039+
void TestSuite::Skip() {
3040+
if (!should_run_) return;
3041+
3042+
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
3043+
impl->set_current_test_suite(this);
3044+
3045+
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
3046+
3047+
// Call both legacy and the new API
3048+
repeater->OnTestSuiteStart(*this);
3049+
// Legacy API is deprecated but still available
3050+
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
3051+
repeater->OnTestCaseStart(*this);
3052+
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
3053+
3054+
for (int i = 0; i < total_test_count(); i++) {
3055+
GetMutableTestInfo(i)->Skip();
3056+
}
3057+
3058+
// Call both legacy and the new API
3059+
repeater->OnTestSuiteEnd(*this);
3060+
// Legacy API is deprecated but still available
3061+
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
3062+
repeater->OnTestCaseEnd(*this);
3063+
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
3064+
3065+
impl->set_current_test_suite(nullptr);
3066+
}
3067+
29953068
// Clears the results of all tests in this test suite.
29963069
void TestSuite::ClearResult() {
29973070
ad_hoc_test_result_.Clear();
@@ -5523,6 +5596,13 @@ bool UnitTestImpl::RunAllTests() {
55235596
for (int test_index = 0; test_index < total_test_suite_count();
55245597
test_index++) {
55255598
GetMutableSuiteCase(test_index)->Run();
5599+
if (GTEST_FLAG(fail_fast) &&
5600+
GetMutableSuiteCase(test_index)->Failed()) {
5601+
for (int j = test_index + 1; j < total_test_suite_count(); j++) {
5602+
GetMutableSuiteCase(j)->Skip();
5603+
}
5604+
break;
5605+
}
55265606
}
55275607
}
55285608

@@ -6127,31 +6207,31 @@ static const char kColorEncodedHelpMessage[] =
61276207
static bool ParseGoogleTestFlag(const char* const arg) {
61286208
return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
61296209
&GTEST_FLAG(also_run_disabled_tests)) ||
6130-
ParseBoolFlag(arg, kBreakOnFailureFlag,
6131-
&GTEST_FLAG(break_on_failure)) ||
6132-
ParseBoolFlag(arg, kCatchExceptionsFlag,
6133-
&GTEST_FLAG(catch_exceptions)) ||
6134-
ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
6135-
ParseStringFlag(arg, kDeathTestStyleFlag,
6136-
&GTEST_FLAG(death_test_style)) ||
6137-
ParseBoolFlag(arg, kDeathTestUseFork,
6138-
&GTEST_FLAG(death_test_use_fork)) ||
6139-
ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
6140-
ParseStringFlag(arg, kInternalRunDeathTestFlag,
6141-
&GTEST_FLAG(internal_run_death_test)) ||
6142-
ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
6143-
ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
6144-
ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
6145-
ParseBoolFlag(arg, kPrintUTF8Flag, &GTEST_FLAG(print_utf8)) ||
6146-
ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
6147-
ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
6148-
ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
6149-
ParseInt32Flag(arg, kStackTraceDepthFlag,
6150-
&GTEST_FLAG(stack_trace_depth)) ||
6151-
ParseStringFlag(arg, kStreamResultToFlag,
6152-
&GTEST_FLAG(stream_result_to)) ||
6153-
ParseBoolFlag(arg, kThrowOnFailureFlag,
6154-
&GTEST_FLAG(throw_on_failure));
6210+
ParseBoolFlag(arg, kBreakOnFailureFlag,
6211+
&GTEST_FLAG(break_on_failure)) ||
6212+
ParseBoolFlag(arg, kCatchExceptionsFlag,
6213+
&GTEST_FLAG(catch_exceptions)) ||
6214+
ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
6215+
ParseStringFlag(arg, kDeathTestStyleFlag,
6216+
&GTEST_FLAG(death_test_style)) ||
6217+
ParseBoolFlag(arg, kDeathTestUseFork,
6218+
&GTEST_FLAG(death_test_use_fork)) ||
6219+
ParseBoolFlag(arg, kFailFast, &GTEST_FLAG(fail_fast)) ||
6220+
ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
6221+
ParseStringFlag(arg, kInternalRunDeathTestFlag,
6222+
&GTEST_FLAG(internal_run_death_test)) ||
6223+
ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
6224+
ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
6225+
ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
6226+
ParseBoolFlag(arg, kPrintUTF8Flag, &GTEST_FLAG(print_utf8)) ||
6227+
ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
6228+
ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
6229+
ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
6230+
ParseInt32Flag(arg, kStackTraceDepthFlag,
6231+
&GTEST_FLAG(stack_trace_depth)) ||
6232+
ParseStringFlag(arg, kStreamResultToFlag,
6233+
&GTEST_FLAG(stream_result_to)) ||
6234+
ParseBoolFlag(arg, kThrowOnFailureFlag, &GTEST_FLAG(throw_on_failure));
61556235
}
61566236

61576237
#if GTEST_USE_OWN_FLAGFILE_FLAG_

googletest/test/BUILD.bazel

+16
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ cc_test(
5858
"googletest-catch-exceptions-test_.cc",
5959
"googletest-color-test_.cc",
6060
"googletest-env-var-test_.cc",
61+
"googletest-failfast-unittest_.cc",
6162
"googletest-filter-unittest_.cc",
6263
"googletest-break-on-failure-unittest_.cc",
6364
"googletest-listener-test.cc",
@@ -222,6 +223,21 @@ py_test(
222223
deps = [":gtest_test_utils"],
223224
)
224225

226+
cc_binary(
227+
name = "googletest-failfast-unittest_",
228+
testonly = 1,
229+
srcs = ["googletest-failfast-unittest_.cc"],
230+
deps = ["//:gtest"],
231+
)
232+
233+
py_test(
234+
name = "googletest-failfast-unittest",
235+
size = "medium",
236+
srcs = ["googletest-failfast-unittest.py"],
237+
data = [":googletest-failfast-unittest_"],
238+
deps = [":gtest_test_utils"],
239+
)
240+
225241
cc_binary(
226242
name = "googletest-filter-unittest_",
227243
testonly = 1,

googletest/test/googletest-env-var-test.py

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ def testEnvVarAffectsFlag(self):
8585

8686
TestFlag('break_on_failure', '1', '0')
8787
TestFlag('color', 'yes', 'auto')
88+
SetEnvVar('TESTBRIDGE_TEST_RUNNER_FAIL_FAST', None) # For 'fail_fast' test
89+
TestFlag('fail_fast', '1', '0')
8890
TestFlag('filter', 'FooTest.Bar', '*')
8991
SetEnvVar('XML_OUTPUT_FILE', None) # For 'output' test
9092
TestFlag('output', 'xml:tmp/foo.xml', '')

googletest/test/googletest-env-var-test_.cc

+5
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ void PrintFlag(const char* flag) {
7272
return;
7373
}
7474

75+
if (strcmp(flag, "fail_fast") == 0) {
76+
cout << GTEST_FLAG(fail_fast);
77+
return;
78+
}
79+
7580
if (strcmp(flag, "filter") == 0) {
7681
cout << GTEST_FLAG(filter);
7782
return;

0 commit comments

Comments
 (0)