How to Implement User-Defined Assertions with Rich Diagnostic Messages in Google Test
To implement user-defined assertions with rich diagnostic messages in Google Test, create a helper function that returns ::testing::AssertionResult and wrap it with the GTEST_ASSERT_ macro from gtest_pred_impl.h.
The Google Test framework provides extensive built-in assertions, but real-world testing often requires domain-specific checks. By leveraging the same internal machinery that powers ASSERT_EQ and EXPECT_TRUE, you can implement user-defined assertions that automatically generate detailed failure diagnostics showing actual versus expected values.
Core Components for Custom Assertions
The AssertionResult Interface
Located in googletest/include/gtest/internal/gtest-internal.h, the AssertionResult class represents the outcome of a predicate evaluation. Return ::testing::AssertionSuccess() for passing checks, or ::testing::AssertionFailure() coupled with the stream insertion operator to build detailed error messages.
The GTEST_ASSERT_ Macro
The GTEST_ASSERT_ macro, defined at line 77 of googletest/include/gtest/gtest_pred_impl.h, forms the foundation of all fatal assertions. It accepts an expression evaluating to AssertionResult and a failure handler (typically GTEST_FATAL_FAILURE_ for ASSERT_* variants or GTEST_NONFATAL_FAILURE_ for EXPECT_* variants).
Building a User-Defined Assertion
Step 1: Implement the Helper Function
Create a function that performs your custom logic and returns an AssertionResult. On failure, stream diagnostic context into the AssertionFailure object:
#include <gtest/gtest.h>
::testing::AssertionResult IsSorted(const std::vector<int>& v) {
for (size_t i = 1; i < v.size(); ++i) {
if (v[i - 1] > v[i]) {
return ::testing::AssertionFailure()
<< "Elements out of order at index " << i - 1
<< ": " << v[i - 1] << " > " << v[i];
}
}
return ::testing::AssertionSuccess();
}
Step 2: Create the Macro Wrapper
Use GTEST_ASSERT_ to integrate your helper with Google Test's failure reporting infrastructure:
#define ASSERT_IS_SORTED(container) \
GTEST_ASSERT_(IsSorted(container), GTEST_FATAL_FAILURE_)
For non-fatal versions that allow the test to continue, substitute GTEST_NONFATAL_FAILURE_ to create an EXPECT_* style macro instead.
Step 3: Invoke in Test Cases
Use the macro naturally within your test suites. When the assertion fails, Google Test displays the custom diagnostic message alongside the file and line number:
TEST(SortingTest, DetectsUnsortedInput) {
std::vector<int> data = {3, 1, 4, 2};
ASSERT_IS_SORTED(data); // Fails with: Elements out of order at index 0: 3 > 1
}
Reusing Google Test's Comparison Utilities
For assertions comparing two values, delegate to existing helpers in googletest/include/gtest/internal/gtest-internal.h such as CmpHelperEQ, CmpHelperNE, or CmpHelperFloatingPointEQ. As implemented in googletest/include/gtest/gtest.h around lines 2007-2008, CmpHelperFloatingPointEQ formats both operands and the tolerance parameter, producing output identical to the built-in ASSERT_NEAR.
Example implementation:
#define ASSERT_CUSTOM_NEAR(val1, val2, eps) \
GTEST_ASSERT_( \
::testing::internal::CmpHelperFloatingPointEQ( \
#val1, #val2, val1, val2, eps), \
GTEST_FATAL_FAILURE_)
Summary
- User-defined assertions require returning
::testing::AssertionResultfrom helper functions to communicate success or failure. - The
GTEST_ASSERT_macro ingtest_pred_impl.hbridges custom helpers with Google Test's failure reporting. - Use
::testing::AssertionFailure()with stream operators to construct rich diagnostic messages showing actual values and context. - Delegate to internal utilities like
CmpHelperEQorCmpHelperFloatingPointEQwhen comparing values to reuse Google Test's formatting logic. - Choose
GTEST_FATAL_FAILURE_forASSERT_*semantics that halt execution, orGTEST_NONFATAL_FAILURE_forEXPECT_*semantics that continue testing.
Frequently Asked Questions
What is the difference between ASSERT and EXPECT custom assertions?
Fatal custom assertions use GTEST_FATAL_FAILURE_ as the second argument to GTEST_ASSERT_, stopping the current test immediately upon failure. Non-fatal variants use GTEST_NONFATAL_FAILURE_, allowing the test to continue executing subsequent assertions while still recording the failure.
Can I access the built-in value formatting used by ASSERT_EQ?
Yes. The helper functions CmpHelperEQ, CmpHelperNE, and other comparison utilities declared in googletest/include/gtest/internal/gtest-internal.h format operand values automatically. Pass string representations of the variable names (using the # preprocessor operator) along with the actual values to generate diagnostics matching the built-in macros.
How do I add custom context to existing assertions without rewriting them?
Create a predicate function that calls the existing assertion logic and appends context to the message before returning. Alternatively, use ::testing::ScopedTrace to add stack trace context, though for rich value diagnostics, wrapping the assertion in a custom AssertionResult helper provides more control over the output format.
Where are AssertionResult and AssertionFailure defined?
The AssertionResult class and AssertionFailure() function are defined in googletest/include/gtest/internal/gtest-internal.h. These components are part of Google Test's public but internal namespace (::testing::internal), though they remain stable enough for use in custom assertion utilities.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →