# How Google Test's TestEventListeners Work: Internal Design and Custom Implementation

> Discover Google Test's TestEventListeners design. Learn how to implement custom listeners by forwarding callbacks with TestEventRepeater and subclassing TestEventListener.

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

---

**Google Test's TestEventListeners system uses a repeater pattern where TestEventRepeater forwards lifecycle callbacks to registered listeners, allowing you to implement custom behavior by subclassing TestEventListener or EmptyTestEventListener and appending your instance to UnitTest::listeners().**

The `google/googletest` framework exposes the complete lifecycle of test execution through the **TestEventListeners** API. Understanding this internal design enables you to build custom reporters, integrate with CI systems, or capture test metrics without modifying the framework's core. This article examines the three-class architecture behind event propagation and provides a complete implementation guide for custom listeners.

## Core Architecture of the TestEventListeners System

The event notification system in Google Test is built around three cooperating classes defined in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h) and implemented in `googletest/src/gtest.cc`.

### The TestEventListener Interface

**`TestEventListener`** serves as the pure-virtual interface that defines one method for every test-run event. Located at line 2930 of [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), this class declares callbacks for program start/end, test iteration, test suite start/end, individual test start/end, test part results, and environment setup/teardown. To receive notifications, you derive from this class and implement the specific callbacks you need.

### EmptyTestEventListener Convenience Base

**`EmptyTestEventListener`** provides a no-op implementation of every `TestEventListener` method. Found at line 2925 in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), this class allows you to subclass and override only the methods you care about, ignoring the rest. It eliminates boilerplate when you need to monitor just one or two specific events.

### TestEventRepeater Internal Hub

**`TestEventRepeater`** acts as the internal "hub" that holds a vector of concrete listeners. Defined around line 3848 in `googletest/src/gtest.cc`, this class forwards every event to registered listeners in insertion order (or reverse order for teardown events). The repeater is owned by `TestEventListeners` and manages the actual dispatch logic, including a `forwarding_enabled_` flag used to suppress events during death-test child processes.

## How TestEventListeners Dispatch Events

The framework follows a strict workflow when constructing, registering, and invoking listeners:

**1. Singleton Construction**

When `UnitTest::GetInstance()` is first invoked, the singleton creates a `TestEventListeners` object. The constructor, located at lines 5226-5232 in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), instantiates a `TestEventRepeater` and automatically registers the default console printer (`PrettyUnitTestResultPrinter`) and XML generator (`XmlUnitTestResultPrinter`).

**2. Listener Registration**

User code registers listeners by calling `Append()` on the facade returned by `UnitTest::listeners()`. The `TestEventListeners::Append()` method (lines 5232-5235) forwards the pointer to `TestEventRepeater::Append()` (lines 3901-3903 in `gtest.cc`). Ownership transfers immediately to the repeater, which deletes the listener automatically on program exit.

**3. Event Propagation**

During test execution, the framework invokes methods on the repeater (e.g., `OnTestStart()`). The repeater checks `forwarding_enabled_` and iterates over its internal `listeners_` vector, calling the same method on each registered listener. Forward events (startup) dispatch in registration order, while reverse events (teardown) dispatch in reverse order using the `GTEST_REVERSE_REPEATER_METHOD_` macro defined near lines 3816-3824.

**4. Default Listener Management**

The default printers can be replaced or removed via `SetDefaultResultPrinter()` and `SetDefaultXmlGenerator()`, located at lines 5272-5287 in [`gtest.h`](https://github.com/google/googletest/blob/main/gtest.h). These methods handle the special case of the default listeners separately from user-appended ones.

**5. Event Suppression**

`TestEventListeners::SuppressEventForwarding()` toggles the repeater's forwarding state. This is automatically disabled in death-test child processes to prevent duplicate output, implemented at lines 5266-5268 in [`gtest.h`](https://github.com/google/googletest/blob/main/gtest.h) and lines 3858-3860 in `gtest.cc`.

## Implementing a Custom TestEventListener

Follow these steps to create and register a custom listener that logs test starts, failures, and results:

**Step 1:** Derive from `testing::EmptyTestEventListener` to minimize boilerplate.

**Step 2:** Override the relevant callbacks. Common hooks include:
- `OnTestStart(const TestInfo&)` – Called immediately before the test body executes
- `OnTestPartResult(const TestPartResult&)` – Called for each assertion (EXPECT_/ASSERT_)
- `OnTestEnd(const TestInfo&)` – Called after the test completes, including cleanup

**Step 3:** Register the listener in `main()` before calling `RUN_ALL_TESTS()`.

```cpp
// my_listener.h
#include <gtest/gtest.h>
#include <iostream>

class MyListener : public testing::EmptyTestEventListener {
 public:
  void OnTestStart(const testing::TestInfo& test_info) override {
    std::cout << "[MyListener] Starting: " 
              << test_info.test_suite_name() << "." 
              << test_info.name() << "\n";
  }

  void OnTestPartResult(const testing::TestPartResult& result) override {
    if (result.type() == testing::TestPartResult::kSuccess) return;
    std::cerr << "[MyListener] Failure at " << result.file_name() 
              << ":" << result.line_number() << " - " 
              << result.summary() << "\n";
  }

  void OnTestEnd(const testing::TestInfo& test_info) override {
    std::cout << "[MyListener] Finished: " 
              << test_info.test_suite_name() << "." 
              << test_info.name()
              << (test_info.result()->Passed() ? " [PASS]" : " [FAIL]")
              << "\n";
  }
};

```

```cpp
// main.cpp
#include <gtest/gtest.h>
#include "my_listener.h"

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  
  // Append the custom listener before running tests
  ::testing::TestEventListeners& listeners = 
      ::testing::UnitTest::GetInstance()->listeners();
  listeners.Append(new MyListener);  // Ownership transferred to Google Test
  
  return RUN_ALL_TESTS();
}

```

## Managing Default Listeners and Suppression

The **TestEventListeners** facade controls whether the default console and XML output is generated. Call `listeners.Release(listeners.default_result_printer())` to remove console output entirely, or use `SetDefaultResultPrinter(nullptr)` to disable it while keeping the XML generator.

When writing death tests, note that `SuppressEventForwarding(true)` is automatically invoked in the child process. This prevents your custom listener from receiving events from the death-test subprocess, avoiding stale output or double-logging.

## Summary

- **TestEventListener** is the pure-virtual interface defining all lifecycle callbacks, located in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h) (line 2930).
- **EmptyTestEventListener** provides no-op implementations so you can override selectively (line 2925).
- **TestEventRepeater** is the internal dispatcher that forwards events to all registered listeners in `googletest/src/gtest.cc` (line 3848).
- Register custom listeners via `UnitTest::GetInstance()->listeners().Append()` before `RUN_ALL_TESTS()`; ownership transfers to the framework.
- The repeater respects `forwarding_enabled_`, which is automatically disabled during death tests to prevent duplicate output.

## Frequently Asked Questions

### When should I register a custom TestEventListener?

Register your listener after calling `::testing::InitGoogleTest()` but before `RUN_ALL_TESTS()` in your `main()` function. Appending listeners during test execution (for example, inside a test body) is unsupported and may result in missed events or undefined behavior.

### Can I remove or replace the default console printer?

Yes. Use `listeners.Release(listeners.default_result_printer())` to remove the console output entirely, or call `listeners.SetDefaultResultPrinter(new MyPrinter)` to substitute your own implementation. The old printer is returned and becomes your responsibility to delete unless you passed `nullptr`.

### Is the TestEventListeners system thread-safe?

The `TestEventRepeater` does not perform internal locking when dispatching events. In environments using `gtest-parallel` or custom thread pools, your listener implementation must handle its own synchronization if it accesses shared state. The framework guarantees that a single test's events (start, part results, end) are dispatched sequentially on the same thread.

### Who owns the listener memory after calling Append?

Ownership transfers immediately to the `TestEventRepeater`. The repeater stores the pointer in its internal `listeners_` vector and deletes all registered listeners in its destructor. Do not delete the listener yourself after appending it, and ensure listeners are allocated with `new`, not on the stack.