# How to Implement a Custom Test Event Listener in GoogleTest: A Complete Guide

> Learn how to implement a custom test event listener in GoogleTest. Follow this guide to derive from EmptyTestEventListener, override callbacks, and register your listener for enhanced test control.

- Repository: [Google/googletest](https://github.com/google/googletest)
- Tags: how-to-guide
- Published: 2026-08-31

---

**To create a custom test event listener in GoogleTest, derive from `::testing::EmptyTestEventListener`, override the specific callback methods you need, and register the instance via `::testing::UnitTest::GetInstance()->listeners().Append()` before invoking `RUN_ALL_TESTS()`.**

Implementing a custom test event listener allows you to intercept and react to every phase of test execution within the GoogleTest framework. The `TestEventListener` interface, defined in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), provides pure-virtual callbacks for events ranging from individual test failures to complete program termination. This article demonstrates the exact implementation pattern used in the GoogleTest source code, including registration mechanics and memory ownership semantics.

## Understanding the TestEventListener Architecture

GoogleTest exposes two primary mechanisms for building listeners: the abstract `TestEventListener` interface and the `EmptyTestEventListener` convenience base class. Understanding the distinction between these components is essential for writing maintainable hook code.

### The TestEventListener Abstract Base Class

The `TestEventListener` interface declares pure-virtual methods that the framework invokes during test execution. Located in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), this class defines callbacks such as `OnTestProgramStart`, `OnTestStart`, `OnTestPartResult`, `OnTestEnd`, and `OnTestProgramEnd`. Each method receives a reference to a context object—such as `UnitTest`, `TestSuite`, or `TestInfo`—allowing inspection of test names, failure details, and timing data.

### The EmptyTestEventListener Convenience Class

Rather than implementing every pure-virtual method yourself, you should inherit from `::testing::EmptyTestEventListener`. Also defined in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), this class provides no-op implementations for all callbacks. By deriving from `EmptyTestEventListener`, you only override the methods relevant to your use case, significantly reducing boilerplate code.

## Step-by-Step Implementation

Creating a functional custom test event listener requires three distinct steps: class definition, method implementation, and global registration.

1.  **Derive from `EmptyTestEventListener`** and declare your overrides.
2.  **Implement the callbacks** to capture the data you need.
3.  **Register the listener** with the global `TestEventListeners` container before `RUN_ALL_TESTS()` executes.

The framework assumes ownership of the listener pointer passed to `Append()` and automatically deletes it during program shutdown.

## Registering Your Listener

Registration occurs through the `TestEventListeners` object returned by `UnitTest::GetInstance()->listeners()`. The `TestEventListeners` class, defined in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), manages the lifetime and invocation order of all registered observers.

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

class MyListener : public ::testing::EmptyTestEventListener {
  // ... implementation ...
};

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  
  ::testing::TestEventListeners& listeners = 
      ::testing::UnitTest::GetInstance()->listeners();
  
  listeners.Append(new MyListener);  // GoogleTest takes ownership
  
  return RUN_ALL_TESTS();
}

```

The `listeners()` accessor is implemented in [`googletest/src/gtest-internal-inl.h`](https://github.com/google/googletest/blob/main/googletest/src/gtest-internal-inl.h), providing the entry point to the global listeners collection.

## Practical Implementation Examples

The following patterns demonstrate common use cases for custom test event listeners, from simple logging to complex output formatting.

### Logging Test Lifecycle Events

This minimal example logs when each test starts and finishes, reporting the pass/fail status upon completion.

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

class SimpleLogger : public ::testing::EmptyTestEventListener {
 public:
  void OnTestStart(const ::testing::TestInfo& info) override {
    std::cout << "[START] " << info.test_suite_name() << '.' 
              << info.name() << '\n';
  }

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

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  ::testing::UnitTest::GetInstance()->listeners().Append(new SimpleLogger);
  return RUN_ALL_TESTS();
}

```

### Measuring Test Suite Execution Time

To collect performance metrics, override `OnTestSuiteStart` and `OnTestSuiteEnd`. This example uses `std::chrono` to calculate wall-clock duration for each suite.

```cpp
#include <gtest/gtest.h>
#include <chrono>
#include <map>
#include <string>
#include <iostream>

class TimingListener : public ::testing::EmptyTestEventListener {
  using Clock = std::chrono::high_resolution_clock;
  std::map<std::string, Clock::time_point> start_times_;

 public:
  void OnTestSuiteStart(const ::testing::TestSuite& suite) override {
    start_times_[suite.name()] = Clock::now();
  }

  void OnTestSuiteEnd(const ::testing::TestSuite& suite) override {
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
        Clock::now() - start_times_[suite.name()]);
    std::cout << "[TIMING] Suite " << suite.name() 
              << " ran in " << elapsed.count() << " ms\n";
  }
};

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  ::testing::UnitTest::GetInstance()->listeners().Append(new TimingListener);
  return RUN_ALL_TESTS();
}

```

### Generating Custom JSON Reports

For CI/CD integration, you may want to replace the default console output entirely. This example generates a JSON summary and suppresses the standard printer.

```cpp
#include <gtest/gtest.h>
#include <iostream>
#include <nlohmann/json.hpp>

class JsonReporter : public ::testing::EmptyTestEventListener {
  nlohmann::json report_;

 public:
  void OnTestProgramStart(const ::testing::UnitTest&) override {
    report_["tests"] = nlohmann::json::array();
  }

  void OnTestEnd(const ::testing::TestInfo& info) override {
    nlohmann::json entry;
    entry["suite"] = info.test_suite_name();
    entry["name"] = info.name();
    entry["passed"] = info.result()->Passed();
    entry["duration_ms"] = 
        std::chrono::duration_cast<std::chrono::milliseconds>(
            info.result()->elapsed_time()).count();
    report_["tests"].push_back(entry);
  }

  void OnTestProgramEnd(const ::testing::UnitTest&) override {
    std::cout << report_.dump(2) << std::endl;
  }
};

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  auto& listeners = ::testing::UnitTest::GetInstance()->listeners();
  
  // Remove default console printer to prevent duplicate output
  listeners.Release(listeners.default_result_printer());
  
  listeners.Append(new JsonReporter);
  return RUN_ALL_TESTS();
}

```

## Replacing the Default Result Printer

If your custom test event listener implements its own output logic, you should remove the built-in console printer to avoid mixed formatting. Call `listeners.Release(listeners.default_result_printer())` before appending your custom listener. The `Release` method removes the listener from the container without deleting it, whereas `Append` transfers ownership to GoogleTest.

## Summary

-   **Inherit from `EmptyTestEventListener`** (defined in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h)) to avoid implementing all virtual methods.
-   **Override specific callbacks** such as `OnTestStart`, `OnTestEnd`, or `OnTestSuiteEnd` to hook into execution phases.
-   **Register via `listeners().Append()`** before `RUN_ALL_TESTS()`; GoogleTest takes ownership of the pointer.
-   **Remove the default printer** using `listeners.Release(listeners.default_result_printer())` when implementing custom output formats.

## Frequently Asked Questions

### How do I access the test name inside a listener callback?

The `TestInfo` object passed to callbacks like `OnTestStart` contains `test_suite_name()` and `name()` methods. According to the GoogleTest source in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h), these methods return the C-string names of the current suite and test case, respectively.

### Can I have multiple custom test event listeners active simultaneously?

Yes. The `TestEventListeners` container supports multiple registered observers. Simply call `listeners.Append()` for each new instance. The framework invokes callbacks in the order in which listeners were appended.

### Who is responsible for deleting the listener object?

GoogleTest assumes ownership when you pass a pointer to `Append()`. The framework deletes all registered listeners during the `UnitTest` destruction phase. You must not delete the object manually after registration.

### How do I prevent the default console output from appearing?

Call `listeners.Release(listeners.default_result_printer())` before adding your custom listener. This removes the default `PrettyUnitTestResultPrinter` from the event chain, allowing your custom test event listener to control all output.