mirror of
https://github.com/google/googletest.git
synced 2024-12-27 10:11:03 +08:00
Add ability to throw from ASSERT
while not losing benefits of EXPECT, and not killing the whole test, as with --gtest_throw_on_failure. 183822976
This commit is contained in:
parent
ea31cb15f0
commit
092d088533
@ -872,13 +872,33 @@ TEST(FooTest, Bar) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Since we don't use exceptions, it is technically impossible to
|
To alleviate this, gUnit provides three different solutions. You could use
|
||||||
implement the intended behavior here. To alleviate this, Google Test
|
either exceptions, the `(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
|
||||||
provides two solutions. You could use either the
|
`HasFatalFailure()` function. They are described in the following two
|
||||||
`(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
|
|
||||||
`HasFatalFailure()` function. They are described in the following two
|
|
||||||
subsections.
|
subsections.
|
||||||
|
|
||||||
|
#### Asserting on Subroutines with an exception
|
||||||
|
|
||||||
|
The following code can turn ASSERT-failure into an exception:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
class ThrowListener : public testing::EmptyTestEventListener {
|
||||||
|
void OnTestPartResult(const testing::TestPartResult& result) override {
|
||||||
|
if (result.type() == testing::TestPartResult::kFatalFailure) {
|
||||||
|
throw testing::AssertionException(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
...
|
||||||
|
testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This listener should be added after other listeners if you have any, otherwise
|
||||||
|
they won't see failed `OnTestPartResult`.
|
||||||
|
|
||||||
### Asserting on Subroutines ###
|
### Asserting on Subroutines ###
|
||||||
|
|
||||||
As shown above, if your test calls a subroutine that has an `ASSERT_*`
|
As shown above, if your test calls a subroutine that has an `ASSERT_*`
|
||||||
|
@ -138,7 +138,7 @@ GTEST_DECLARE_int32_(stack_trace_depth);
|
|||||||
|
|
||||||
// When this flag is specified, a failed assertion will throw an
|
// When this flag is specified, a failed assertion will throw an
|
||||||
// exception if exceptions are enabled, or exit the program with a
|
// exception if exceptions are enabled, or exit the program with a
|
||||||
// non-zero code otherwise.
|
// non-zero code otherwise. For use with an external test framework.
|
||||||
GTEST_DECLARE_bool_(throw_on_failure);
|
GTEST_DECLARE_bool_(throw_on_failure);
|
||||||
|
|
||||||
// When this flag is set with a "host:port" string, on supported
|
// When this flag is set with a "host:port" string, on supported
|
||||||
@ -1004,6 +1004,18 @@ class Environment {
|
|||||||
virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
|
virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
// Exception which can be thrown from TestEventListener::OnTestPartResult.
|
||||||
|
class GTEST_API_ AssertionException
|
||||||
|
: public internal::GoogleTestFailureException {
|
||||||
|
public:
|
||||||
|
explicit AssertionException(const TestPartResult& result)
|
||||||
|
: GoogleTestFailureException(result) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_EXCEPTIONS
|
||||||
|
|
||||||
// The interface for tracing execution of tests. The methods are organized in
|
// The interface for tracing execution of tests. The methods are organized in
|
||||||
// the order the corresponding events are fired.
|
// the order the corresponding events are fired.
|
||||||
class TestEventListener {
|
class TestEventListener {
|
||||||
@ -1032,6 +1044,8 @@ class TestEventListener {
|
|||||||
virtual void OnTestStart(const TestInfo& test_info) = 0;
|
virtual void OnTestStart(const TestInfo& test_info) = 0;
|
||||||
|
|
||||||
// Fired after a failed assertion or a SUCCEED() invocation.
|
// Fired after a failed assertion or a SUCCEED() invocation.
|
||||||
|
// If you want to throw an exception from this function to skip to the next
|
||||||
|
// TEST, it must be AssertionException defined above, or inherited from it.
|
||||||
virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
|
virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
|
||||||
|
|
||||||
// Fired after the test ends.
|
// Fired after the test ends.
|
||||||
|
@ -293,7 +293,7 @@ GTEST_DEFINE_bool_(
|
|||||||
internal::BoolFromGTestEnv("throw_on_failure", false),
|
internal::BoolFromGTestEnv("throw_on_failure", false),
|
||||||
"When this flag is specified, a failed assertion will throw an exception "
|
"When this flag is specified, a failed assertion will throw an exception "
|
||||||
"if exceptions are enabled or exit the program with a non-zero code "
|
"if exceptions are enabled or exit the program with a non-zero code "
|
||||||
"otherwise.");
|
"otherwise. For use with an external test framework.");
|
||||||
|
|
||||||
#if GTEST_USE_OWN_FLAGFILE_FLAG_
|
#if GTEST_USE_OWN_FLAGFILE_FLAG_
|
||||||
GTEST_DEFINE_string_(
|
GTEST_DEFINE_string_(
|
||||||
@ -2435,6 +2435,8 @@ Result HandleExceptionsInMethodIfSupported(
|
|||||||
#if GTEST_HAS_EXCEPTIONS
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
try {
|
try {
|
||||||
return HandleSehExceptionsInMethodIfSupported(object, method, location);
|
return HandleSehExceptionsInMethodIfSupported(object, method, location);
|
||||||
|
} catch (const AssertionException&) { // NOLINT
|
||||||
|
// This failure was reported already.
|
||||||
} catch (const internal::GoogleTestFailureException&) { // NOLINT
|
} catch (const internal::GoogleTestFailureException&) { // NOLINT
|
||||||
// This exception type can only be thrown by a failed Google
|
// This exception type can only be thrown by a failed Google
|
||||||
// Test assertion with the intention of letting another testing
|
// Test assertion with the intention of letting another testing
|
||||||
@ -5201,7 +5203,8 @@ static const char kColorEncodedHelpMessage[] =
|
|||||||
" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
|
" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
|
||||||
" Turn assertion failures into debugger break-points.\n"
|
" Turn assertion failures into debugger break-points.\n"
|
||||||
" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
|
" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
|
||||||
" Turn assertion failures into C++ exceptions.\n"
|
" Turn assertion failures into C++ exceptions for use by an external\n"
|
||||||
|
" test framework.\n"
|
||||||
" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
|
" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
|
||||||
" Do not report exceptions as test failures. Instead, allow them\n"
|
" Do not report exceptions as test failures. Instead, allow them\n"
|
||||||
" to crash the program or throw a pop-up (on Windows).\n"
|
" to crash the program or throw a pop-up (on Windows).\n"
|
||||||
|
@ -219,6 +219,13 @@ py_test(
|
|||||||
deps = [":gtest_test_utils"],
|
deps = [":gtest_test_utils"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "gtest_assert_by_exception_test",
|
||||||
|
size = "small",
|
||||||
|
srcs = ["gtest_assert_by_exception_test.cc"],
|
||||||
|
deps = ["//:gtest"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "gtest_throw_on_failure_test_",
|
name = "gtest_throw_on_failure_test_",
|
||||||
testonly = 1,
|
testonly = 1,
|
||||||
|
119
googletest/test/gtest_assert_by_exception_test.cc
Normal file
119
googletest/test/gtest_assert_by_exception_test.cc
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// Copyright 2009, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Tests Google Test's assert-by-exception mode with exceptions enabled.
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
class ThrowListener : public testing::EmptyTestEventListener {
|
||||||
|
void OnTestPartResult(const testing::TestPartResult& result) override {
|
||||||
|
if (result.type() == testing::TestPartResult::kFatalFailure) {
|
||||||
|
throw testing::AssertionException(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prints the given failure message and exits the program with
|
||||||
|
// non-zero. We use this instead of a Google Test assertion to
|
||||||
|
// indicate a failure, as the latter is been tested and cannot be
|
||||||
|
// relied on.
|
||||||
|
void Fail(const char* msg) {
|
||||||
|
printf("FAILURE: %s\n", msg);
|
||||||
|
fflush(stdout);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AssertFalse() {
|
||||||
|
ASSERT_EQ(2, 3) << "Expected failure";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that an assertion failure throws a subclass of
|
||||||
|
// std::runtime_error.
|
||||||
|
TEST(Test, Test) {
|
||||||
|
// A successful assertion shouldn't throw.
|
||||||
|
try {
|
||||||
|
EXPECT_EQ(3, 3);
|
||||||
|
} catch(...) {
|
||||||
|
Fail("A successful assertion wrongfully threw.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// A successful assertion shouldn't throw.
|
||||||
|
try {
|
||||||
|
EXPECT_EQ(3, 4);
|
||||||
|
} catch(...) {
|
||||||
|
Fail("A failed non-fatal assertion wrongfully threw.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// A failed assertion should throw.
|
||||||
|
try {
|
||||||
|
AssertFalse();
|
||||||
|
} catch(const testing::AssertionException& e) {
|
||||||
|
if (strstr(e.what(), "Expected failure") != NULL)
|
||||||
|
throw;
|
||||||
|
|
||||||
|
printf("%s",
|
||||||
|
"A failed assertion did throw an exception of the right type, "
|
||||||
|
"but the message is incorrect. Instead of containing \"Expected "
|
||||||
|
"failure\", it is:\n");
|
||||||
|
Fail(e.what());
|
||||||
|
} catch(...) {
|
||||||
|
Fail("A failed assertion threw the wrong type of exception.");
|
||||||
|
}
|
||||||
|
Fail("A failed assertion should've thrown but didn't.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int kTestForContinuingTest = 0;
|
||||||
|
|
||||||
|
TEST(Test, Test2) {
|
||||||
|
// FIXME(sokolov): how to force Test2 to be after Test?
|
||||||
|
kTestForContinuingTest = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
|
||||||
|
|
||||||
|
int result = RUN_ALL_TESTS();
|
||||||
|
if (result == 0) {
|
||||||
|
printf("RUN_ALL_TESTS returned %d\n", result);
|
||||||
|
Fail("Expected failure instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kTestForContinuingTest == 0) {
|
||||||
|
Fail("Should have continued with other tests, but did not.");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user