# How the AssertionResult Class Enables Custom Predicates with Rich Error Messages in GoogleTest

> Discover how the AssertionResult class in GoogleTest empowers custom predicates with rich error messages. Stream diagnostics seamlessly with EXPECT macros.

- Repository: [Google/googletest](https://github.com/google/googletest)
- Tags: internals
- Published: 2026-08-30

---

**The `testing::AssertionResult` class provides a lightweight success flag coupled with deferred message streaming, allowing user-defined predicate functions to return detailed diagnostics that integrate seamlessly with `EXPECT_TRUE`, `EXPECT_FALSE`, and `EXPECT_PRED_FORMAT*` macros.**

When writing custom validation logic in C++ unit tests, returning a simple boolean provides no context on failure. The **AssertionResult** class in GoogleTest (google/googletest) solves this by enabling **custom predicates with rich error messages** without sacrificing performance on the success path. This mechanism allows developers to write expressive, reusable validation functions that produce detailed failure diagnostics automatically.

## Core Architecture of AssertionResult

### The Success Flag and Boolean Conversion

At its heart, `AssertionResult` stores a minimal `bool success_` member (defined at line 26 in [`googletest/include/gtest/gtest-assertion-result.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest-assertion-result.h)). This flag indicates whether the predicate evaluated to true or false. The class exposes an implicit conversion operator `operator bool()` (line 84) that allows `AssertionResult` objects to be passed directly to macros like `EXPECT_TRUE` and `EXPECT_FALSE`. When the framework evaluates the assertion, it checks this boolean to determine whether the test passed or failed.

### Deferred Message Construction

To keep the success path lightweight, `AssertionResult` employs lazy allocation for error messages. The class holds a `std::unique_ptr<std::string> message_` (lines 22-30) that remains null until an error message is actually needed. When a predicate fails, developers stream text into the object using `operator<<` overloads (lines 101-108). These operators forward content to a private `AppendMessage` method, which allocates the string only when first called. This **deferred, streamable message** strategy ensures that successful assertions incur minimal overhead while failed assertions can capture arbitrarily complex diagnostic data.

## Built-in Support for Predicate Negation

GoogleTest supports logical negation through the `operator!()` overload (line 87). When you write `EXPECT_FALSE(predicate(...))`, the framework applies this operator to flip the `success_` flag while preserving the streamed message content. This enables the same custom predicate to work correctly with both positive and negative assertions without requiring separate implementation logic.

## Factory Functions and Usage Patterns

Rather than constructing `AssertionResult` directly, users rely on two factory helpers: `AssertionSuccess()` and `AssertionFailure()` (lines 52-58). These functions return properly initialized instances—`AssertionSuccess()` creates a result with `success_` set to true and no message, while `AssertionFailure()` initializes `success_` to false with an empty message ready for streaming.

A typical custom predicate returns `AssertionSuccess()` on valid input and chains a diagnostic stream to `AssertionFailure()` on invalid input:

```cpp
testing::AssertionResult IsEven(int n) {
  if (n % 2 == 0) 
    return testing::AssertionSuccess();
  return testing::AssertionFailure() << n << " is odd";
}

```

## Integration with EXPECT_PRED_FORMAT* Macros

For maximum diagnostic detail, the `EXPECT_PRED_FORMAT*` macros pass the stringized expression text to the predicate. When implementing predicates for these macros, the function signature includes `const char* expr` as the first parameter, allowing the predicate to prepend the expression text to the failure message (demonstrated in the documentation at line 119). This integration produces output that shows both the expected expression and the actual value, providing the rich diagnostics GoogleTest is known for.

Example implementation for format macros:

```cpp
testing::AssertionResult IsEven(const char* expr, int n) {
  if (n % 2 == 0) 
    return testing::AssertionSuccess();
  return testing::AssertionFailure()
         << "Expected: " << expr << " is even\n"
         << "  Actual: it's " << n;
}

```

## Complete Working Example

Putting these elements together, you can define reusable predicates that work across different assertion types:

```cpp
// Simple predicate for EXPECT_TRUE/EXPECT_FALSE
testing::AssertionResult IsEven(int n) {
  if (n % 2 == 0) return testing::AssertionSuccess();
  return testing::AssertionFailure() << n << " is odd";
}

// Format-aware predicate for EXPECT_PRED_FORMAT*
testing::AssertionResult IsEvenFormat(const char* expr, int n) {
  if (n % 2 == 0) return testing::AssertionSuccess();
  return testing::AssertionFailure()
         << "Expected: " << expr << " to be even, but got " << n;
}

TEST(NumberTest, EvenCheck) {
  EXPECT_TRUE(IsEven(4));                    // Passes silently
  EXPECT_FALSE(IsEven(5));                   // Prints: "5 is odd"
  EXPECT_PRED_FORMAT1(IsEvenFormat, 7);      // Prints expression info
}

```

The framework processes these through the header [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), which defines the assertion macros that rely on `AssertionResult` for predicate handling, while [`googletest/include/gtest/internal/gtest-internal.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/internal/gtest-internal.h) provides forward declarations used throughout the framework.

## Summary

- `AssertionResult` stores a lightweight `bool success_` flag with an implicit `operator bool()` conversion (line 84) for framework integration.
- Error messages use lazy allocation via `std::unique_ptr<std::string> message_` (lines 22-30), allocated only via `AppendMessage` when `operator<<` is invoked on failure.
- The `operator!()` overload (line 87) enables seamless `EXPECT_FALSE` support by negating the success flag while preserving message content.
- Factory functions `AssertionSuccess()` and `AssertionFailure()` (lines 52-58) provide the standard construction pattern for custom predicates.
- `EXPECT_PRED_FORMAT*` macros leverage the class to pass expression strings into predicates, enabling rich failure diagnostics that include both the expression text and actual values.

## Frequently Asked Questions

### What is the purpose of AssertionResult in GoogleTest?

`AssertionResult` serves as the standard return type for custom predicate functions in GoogleTest. It encapsulates both the boolean outcome of a validation check and an optional error message, allowing the framework to display rich diagnostics when assertions fail while maintaining zero-cost overhead for passing tests.

### How does AssertionResult avoid overhead when predicates succeed?

The class uses a lazy allocation strategy where the `message_` member (a `std::unique_ptr<std::string>` defined at lines 22-30) remains null until a failure occurs. Since successful predicates return via `AssertionSuccess()` without streaming any content, no heap allocation takes place, keeping the success path lightweight.

### Can I use custom predicates without AssertionResult?

While simple predicates can return `bool`, doing so prevents you from providing custom error messages. Without `AssertionResult`, failures will only display generic messages. Using `AssertionResult` is the recommended approach for **custom predicates with rich error messages** as it integrates with all expectation macros including `EXPECT_TRUE`, `EXPECT_FALSE`, and `EXPECT_PRED_FORMAT*`.

### How does EXPECT_PRED_FORMAT1 extract expression text?

The macro stringizes the argument expression and passes it as a `const char*` parameter to your predicate function. When implementing predicates for these macros, you declare this string parameter first (e.g., `const char* expr`), allowing you to embed the original expression text into the failure message streamed into `AssertionFailure()`.