# How to Write Death Tests in GoogleTest to Verify Crashes and Exits

> Learn to write GoogleTest death tests that verify code crashes and exits. This guide shows how to validate child process exit status and stderr output for robust error checking.

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

---

**Death tests in GoogleTest verify that code terminates abnormally by launching the statement in a child process and validating its exit status and standard error output against regular expression matchers.**

The GoogleTest framework (google/googletest) provides a dedicated API for asserting that functions crash, abort, or exit with specific codes. These tests are essential for validating error-handling paths that must terminate the program, such as failed invariant checks or fatal signal handlers.

## Core Death Test Macros

The public death-testing API is declared in [`googletest/include/gtest/gtest-death-test.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest-death-test.h). Four primary macros cover most use cases:

- **`ASSERT_DEATH(statement, matcher)`** – Fails the test immediately if the statement does not terminate abnormally.
- **`EXPECT_DEATH(statement, matcher)`** – Continues the test after reporting a failure if the statement does not die.
- **`ASSERT_EXIT(statement, predicate, matcher)`** – Allows custom validation of the exit status code via a predicate function.
- **`EXPECT_EXIT(statement, predicate, matcher)`** – Non-fatal version of `ASSERT_EXIT`.

For debug-only checks, the header also defines `ASSERT_DEBUG_DEATH` and `EXPECT_DEBUG_DEATH`, which execute the statement only when `NDEBUG` is not defined.

## Architecture and Process Model

All death-test macros expand to the internal macro `GTEST_DEATH_TEST_` defined in [`googletest/include/gtest/internal/gtest-death-test-internal.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/internal/gtest-death-test-internal.h). This macro implements a fork-and-check pattern:

1. **Role Determination** – The macro calls `testing::internal::DeathTest::Create` to obtain a platform-specific `DeathTest` object. The current process assumes either an "oversee" role (parent) or "execute" role (child).
2. **Child Execution** – In the execute role, the macro runs the user-provided statement. If the statement returns normally, the child aborts with `TEST_DID_NOT_DIE`.
3. **Parent Validation** – In the oversee role, the parent waits for the child process to exit, retrieves its exit status via `Wait()`, and validates it using `Passed(bool)`. The abstract `DeathTest` class encapsulates this lifecycle with methods `AssumeRole()`, `Abort(AbortReason)`, and status checking utilities.

The implementation in `googletest/src/gtest-death-test.cc` handles platform-specific child-process creation using `fork()`, `clone()`, or process spawning depending on the operating system.

## Validating Exit Status with Predicates

When using `ASSERT_EXIT` or `EXPECT_EXIT`, you must supply a predicate that evaluates the exit code. The framework provides two built-in predicates in [`gtest-death-test.h`](https://github.com/google/googletest/blob/main/gtest-death-test.h):

- **`testing::ExitedWithCode(int)`** – Returns true if the program exited normally with the specified status code.
- **`testing::KilledBySignal(int)`** – Returns true if the process terminated due to the specified signal (POSIX only).

```cpp
TEST(ProcessTest, CleanExit) {
  auto func = []() { std::exit(42); };
  EXPECT_EXIT(func(), ::testing::ExitedWithCode(42), ".*");
}

#if !defined(GTEST_OS_WINDOWS)
TEST(ProcessTest, SignalTermination) {
  auto func = []() { raise(SIGTERM); };
  EXPECT_EXIT(func(), ::testing::KilledBySignal(SIGTERM), ".*");
}
#endif

```

## Matching Standard Error Output

The `matcher` argument validates the child process's `stderr` output. If you provide a plain string literal, `MakeDeathTestMatcher` (defined in [`gtest-death-test-internal.h`](https://github.com/google/googletest/blob/main/gtest-death-test-internal.h)) implicitly converts it to a regular expression. The framework supports a subset of POSIX regular expression syntax documented in the internal headers.

```cpp
TEST(CrashTest, SpecificErrorMessage) {
  ASSERT_DEATH({
    LOG(FATAL) << "Disk full";
  }, "Disk full");
}

```

## Debug-Only Death Tests

Use `EXPECT_DEBUG_DEATH` or `ASSERT_DEBUG_DEATH` when a fatal assertion should only trigger in debug builds. These macros compile to no-ops when `NDEBUG` is defined, allowing you to test `assert()` statements and debug-only `CHECK` macros without affecting release builds.

```cpp
#ifndef NDEBUG
TEST(DebugTest, AssertFailure) {
  EXPECT_DEBUGdeath({
    assert(false && "Invariant failed");
  }, "Invariant failed");
}
#endif

```

## Practical Examples

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

// Verify null pointer dereference causes SIGSEGV
TEST(FooTest, CrashOnBadInput) {
  ASSERT_DEATH({
    int* p = nullptr;
    *p = 42;
  }, "Segmentation fault|SIGSEGV");
}

// Verify specific exit code
TEST(FooTest, ExitWithCodeZero) {
  auto exit_func = []() { std::exit(0); };
  ASSERT_EXIT(exit_func(), ::testing::ExitedWithCode(0), ".*");
}

// Verify abort signal (POSIX only)
#if !defined(GTEST_OS_WINDOWS)
TEST(FooTest, AbortSignal) {
  auto abort_func = []() { std::abort(); };
  EXPECT_DEATH(abort_func(), "Aborted");
}
#endif

// Debug-only crash test
#ifndef NDEBUG
TEST(FooTest, DebugDeath) {
  EXPECT_DEBUG_DEATH(LOG(DFATAL) << "die now", "die now");
}
#endif

```

## Summary

- Death tests spawn code in a **separate child process** to safely capture crashes without terminating the test runner.
- Use **`ASSERT_DEATH`** and **`EXPECT_DEATH`** for general crash validation via the public API in [`gtest/gtest-death-test.h`](https://github.com/google/googletest/blob/main/gtest/gtest-death-test.h).
- Use **`ASSERT_EXIT`** with **`ExitedWithCode`** or **`KilledBySignal`** to validate specific termination conditions.
- The **`matcher`** string performs regex matching against `stderr`; plain strings are implicitly converted via `MakeDeathTestMatcher`.
- **`ASSERT_DEBUG_DEATH`** skips execution in release builds, making it ideal for testing `assert()` statements.

## Frequently Asked Questions

### What is the difference between `ASSERT_DEATH` and `ASSERT_EXIT`?

`ASSERT_DEATH` asserts that a statement terminates abnormally (non-zero exit or signal) and matches the stderr output against a regex. `ASSERT_EXIT` provides additional control by accepting a predicate function that inspects the exact exit code, such as `ExitedWithCode(0)` for successful exits or `KilledBySignal(SIGABRT)` for specific signals.

### Why does my death test hang when the code doesn't crash?

If the statement passed to a death test macro returns normally, the child process aborts with a special `TEST_DID_NOT_DIE` status. However, if the code enters an infinite loop or waits on I/O, the parent process will hang at the `Wait()` call. Ensure the statement always terminates, either via `exit()`, `abort()`, a signal, or a failed assertion.

### How do death tests work on Windows versus POSIX?

On POSIX systems, death tests use `fork()` or `clone()` to create the child process and support signal-based predicates like `KilledBySignal`. On Windows, the implementation in `gtest-death-test.cc` uses process spawning instead of forking, and signal-related predicates are unavailable. The `GTEST_DEATH_TEST_STYLE` environment variable (`threadsafe` or `fast`) controls the spawning strategy on each platform.

### Can I use death tests to check for C++ exceptions?

No. Death tests only capture process termination via `exit()`, signals, or `abort()`. If your code throws an exception that is not caught, the process may terminate, but this behavior is implementation-defined. For exception testing, use `ASSERT_THROW` or `EXPECT_THROW` from the standard GoogleTest assertion macros instead.