# How to Generate XML Test Reports with GoogleTest

> Easily generate XML test reports with GoogleTest using the --gtest_output=xml flag. Learn how to get JUnit-compatible reports for your C++ projects and improve your testing workflow.

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

---

**GoogleTest generates JUnit-compatible XML reports via the `--gtest_output=xml` flag, which triggers the internal `XmlUnitTestResultPrinter` listener to serialize test results to disk.**

GoogleTest (the `google/googletest` repository) provides built-in support for exporting detailed XML test reports without requiring third-party tools. This functionality is implemented directly in the core framework through a specialized test event listener that captures results and writes them to a JUnit-compatible schema.

## Enabling XML Output via the `--gtest_output` Flag

The primary mechanism to generate XML test reports is the **`--gtest_output`** command-line flag. You can also set the **`GTEST_OUTPUT`** environment variable to achieve the same result.

When you append `:xml` to the flag, GoogleTest instantiates an `XmlUnitTestResultPrinter` (defined in `googletest/src/gtest.cc` around line 3983) and registers it as the default XML generator in the `TestEventListeners` collection.

Run your test binary with one of the following patterns:

```bash

# Generate XML in the default file (test_detail.xml in the working directory)

./my_test --gtest_output=xml

# Specify a custom file path

./my_test --gtest_output=xml:/path/to/report.xml

# Output to a directory (filename derived from test binary name)

./my_test --gtest_output=xml:/tmp/test_reports/

```

## The XML Generation Architecture

The XML reporting system centers on the **`XmlUnitTestResultPrinter`** class. According to the source code in `googletest/src/gtest.cc`, this listener implements the `OnTestIterationEnd` callback, which executes after all tests complete.

The printer is stored as the `default_xml_generator` within the global `UnitTest` instance (see [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h) line 1178). At runtime, GoogleTest populates `TestResult` objects for each test case, then delegates serialization to the printer's static helper methods including `EscapeXml`, `OutputXmlAttribute`, and `OutputXmlTestSuiteForTestResult`.

### The Serialization Pipeline

The XML generation follows a four-stage pipeline:

1. **Listener Creation**: The constructor `XmlUnitTestTestResultPrinter::XmlUnitTestResultPrinter` (line 3985 in `googletest/src/gtest.cc`) receives the output path derived from the flag value.

2. **Result Collection**: As tests execute, GoogleTest populates `TestResult` objects. You can augment these with custom data via `TestResult::RecordProperty` (declared in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h) line 1082).

3. **XML Serialization**: When the test run ends, `OnTestIterationEnd` (line 4087 in `googletest/src/gtest.cc`) opens the target file using `OpenFileForWriting`, builds the XML buffer using escape and formatting utilities, and writes the output.

4. **File Naming**: If you specify a directory rather than a file, `GetOutputFile` (in [`googletest/include/gtest/internal/gtest-filepath.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/internal/gtest-filepath.h) line 98) derives the filename from the test binary name and appends a numeric suffix (`_1`, `_2`, etc.) to prevent overwrites.

## Customizing XML Output

### Adding Custom Properties with `RecordProperty`

You can inject custom XML attributes into individual test cases using the **`RecordProperty`** API. These properties appear as XML attributes on the `<testcase>` element.

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

TEST(Foo, Bar) {
  // Add custom metadata that appears in the XML output
  ::testing::TestResult* result = ::testing::UnitTest::GetInstance()
                                      ->current_test_info()
                                      ->result();
  result->RecordProperty("custom_key", "custom_value");
  
  EXPECT_TRUE(true);
}

```

### Implementing Custom XML Listeners

For advanced use cases, you can replace the default XML generator with a custom implementation by manipulating the `TestEventListeners` collection. Retrieve the current default via `Release`, then register your replacement using `SetDefaultXmlGenerator`.

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

class MyXmlListener : public testing::EmptyTestEventListener {
 public:
  void OnTestIterationEnd(const testing::UnitTest& unit_test, int) override {
    // Implement custom XML generation logic here
  }
};

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  
  // Access the listeners collection
  testing::TestEventListeners& listeners = 
      ::testing::UnitTest::GetInstance()->listeners();
  
  // Remove and delete the default XML generator
  testing::TestEventListener* old = 
      listeners.Release(listeners.default_xml_generator());
  delete old;
  
  // Install custom listener
  listeners.SetDefaultXmlGenerator(new MyXmlListener);
  
  return RUN_ALL_TESTS();
}

```

## XML Format and Schema Compatibility

The generated XML adheres to the JUnit schema, using the `<testsuites>` root element containing nested `<testsuite>` and `<testcase>` elements. Failed assertions generate `<failure>` nodes with detailed message attributes, while `RecordProperty` data appears as custom attributes on test cases.

This format is compatible with continuous integration systems like Jenkins, GitLab CI, and Azure DevOps, which can ingest the reports for test visualization and trend analysis.

## Summary

- **Enable XML output** using `--gtest_output=xml:path/to/file.xml` or the `GTEST_OUTPUT` environment variable.
- **Core implementation** lives in `googletest/src/gtest.cc` within the `XmlUnitTestResultPrinter` class.
- **Customize attributes** by calling `TestResult::RecordProperty` during test execution for metadata inclusion.
- **Replace the generator** by releasing `default_xml_generator` from `TestEventListeners` and installing a custom listener.
- **Automatic file naming** handles directory inputs via `GetOutputFile` in [`gtest-filepath.h`](https://github.com/google/googletest/blob/main/gtest-filepath.h), appending numeric suffixes to avoid collisions.

## Frequently Asked Questions

### How do I generate XML test reports using the GoogleTest command line?

Pass the `--gtest_output=xml` flag followed by an optional path. For example, `./test_binary --gtest_output=xml:results.xml` writes a JUnit-compatible XML file to [`results.xml`](https://github.com/google/googletest/blob/main/results.xml). If you omit the path, GoogleTest creates [`test_detail.xml`](https://github.com/google/googletest/blob/main/test_detail.xml) in the working directory.

### What XML schema does GoogleTest use?

GoogleTest generates JUnit-compatible XML using a `<testsuites>` root element containing `<testsuite>` and `<testcase>` nodes. The schema supports standard elements like `<failure>` for assertion failures and allows custom attributes via the `RecordProperty` API.

### Can I customize the XML output file name dynamically?

Yes. When `--gtest_output=xml` points to a directory, GoogleTest automatically generates filenames based on the test binary name using the `GetOutputFile` utility in [`gtest-filepath.h`](https://github.com/google/googletest/blob/main/gtest-filepath.h). The logic appends incremental numeric suffixes (`_1`, `_2`) to prevent overwriting existing files.

### How do I add custom metadata to GoogleTest XML output?

Call `RecordProperty` on the current test result during test execution. Access the result via `::testing::UnitTest::GetInstance()->current_test_info()->result()`, then invoke `RecordProperty(key, value)`. These key-value pairs appear as XML attributes on the corresponding `<testcase>` element in the final report.