# How to Generate XML Test Reports with GoogleTest

> Easily generate XML test reports with GoogleTest using the --gtest_output=xml flag or GTEST_OUTPUT environment variable for seamless CI integration.

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

---

**GoogleTest generates JUnit-compatible XML reports natively by passing the `--gtest_output=xml` flag or setting the `GTEST_OUTPUT` environment variable, which triggers the `XmlUnitTestResultPrinter` listener to serialize test results at the end of execution.**

The GoogleTest framework (google/googletest) provides built-in support for generating machine-readable XML test reports without requiring external tools. This functionality centers around the **`XmlUnitTestResultPrinter`** class, which captures test execution data and serializes it into a standard JUnit-compatible format. Understanding how to generate XML test reports with GoogleTest enables seamless integration with CI/CD pipelines and test analytics platforms.

## Enabling XML Output via Command Line

The simplest way to generate XML test reports is through the **`--gtest_output`** command-line flag. When set to `xml`, GoogleTest automatically instantiates an `XmlUnitTestResultPrinter` and registers it as the default XML generator in the `TestEventListeners` collection.

Generate a report with the default filename ([`test_detail.xml`](https://github.com/google/googletest/blob/main/test_detail.xml)):

```bash
./my_test --gtest_output=xml

```

Specify a custom file path:

```bash
./my_test --gtest_output=xml:/tmp/custom_report.xml

```

Alternatively, use the **`GTEST_OUTPUT`** environment variable:

```bash
export GTEST_OUTPUT="xml:./test_reports/"
./my_test

```

When a directory is provided, GoogleTest derives the filename from the test binary name and appends a numeric suffix (`_1`, `__2`, etc.) to avoid overwriting existing files.

## How the XML Generator Works Internally

The XML generation pipeline is implemented in `googletest/src/gtest.cc` and orchestrated through three core components:

### XmlUnitTestResultPrinter Construction

When the `--gtest_output=xml` flag is detected, GoogleTest creates an instance of **`XmlUnitTestResultPrinter`** (see line 3983 in `googletest/src/gtest.cc`). The constructor receives the output path and initializes the listener. This object is stored as the `default_xml_generator` in the global `TestEventListeners` collection (defined at line 1178 in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h)).

### Result Collection During Execution

As tests execute, each `TestResult` object accumulates data including pass/fail status, execution time, and any custom properties added via **`TestResult::RecordProperty`** (declared at line 1082 in [`googletest/include/gtest/gtest.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/gtest.h)). The XML printer observes these results through the test event listener interface.

### Serialization and File Writing

At the end of the test run, the **`OnTestIterationEnd`** method (line 4087 in `googletest/src/gtest.cc`) handles the actual XML generation. This method:

1. Opens the target file via `OpenFileForWriting`
2. Builds the XML document using static helper functions including `EscapeXml`, `OutputXmlAttribute`, and `OutputXmlTestSuiteForTestResult`
3. Writes the complete buffer to disk

The resulting XML follows the JUnit schema with `<testsuites>`, `<testsuite>`, `<testcase>`, and `<failure>` elements.

## Customizing XML Report Content

### Adding Custom Properties with RecordProperty

You can inject custom metadata into the XML output using **`RecordProperty`**, which adds attributes to the `<testcase>` element:

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

TEST(Database, Connection) {
  // Record custom properties that appear as XML attributes
  ::testing::TestResult* result = ::testing::UnitTest::GetInstance()
                                      ->current_test_info()
                                      ->result();
  result->RecordProperty("hostname", "server01");
  result->RecordProperty("build_id", "2024.1.2");
  
  EXPECT_TRUE(ConnectToDatabase());
}

```

These properties appear as `<testcase hostname="server01" build_id="2024.1.2" ... />` in the final XML.

### Replacing the Default XML Generator

For advanced use cases, replace the built-in XML generator with a custom listener by manipulating the `TestEventListeners` registry:

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

class CustomXmlListener : public testing::EmptyTestEventListener {
 public:
  void OnTestIterationEnd(const testing::UnitTest& unit_test, int) override {
    std::ofstream xml_file("custom_output.xml");
    xml_file << "<?xml version=\"1.0\"?>\n<testsuites>\n";
    // Custom serialization logic here
    xml_file << "</testsuites>\n";
  }
};

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

```

## XML File Naming and Output Locations

When specifying a directory rather than a file path, GoogleTest uses the **`GetOutputFile`** helper (defined at line 98 in [`googletest/include/gtest/internal/gtest-filepath.h`](https://github.com/google/googletest/blob/main/googletest/include/gtest/internal/gtest-filepath.h)) to construct the output filename. The algorithm:

1. Extracts the binary name from `argv[0]`
2. Appends `.xml` extension
3. Checks for existing files and appends numeric suffixes (`_1`, `_2`) to prevent overwrites

This ensures that multiple test runs in the same directory preserve historical results rather than clobbering previous XML files.

## Summary

- **Enable XML output** using `--gtest_output=xml` or the `GTEST_OUTPUT` environment variable to trigger the built-in `XmlUnitTestResultPrinter`.
- **Customize metadata** by calling `TestResult::RecordProperty` within test bodies to inject custom XML attributes.
- **Replace the generator** via `TestEventListeners::Release` and `SetDefaultXmlGenerator` for complete control over XML formatting.
- **File naming** automatically handles directory paths and collision avoidance through the `GetOutputFile` implementation in [`gtest-filepath.h`](https://github.com/google/googletest/blob/main/gtest-filepath.h).

## Frequently Asked Questions

### What XML format does GoogleTest use?

GoogleTest produces **JUnit-compatible XML** following the standard `testsuites` schema. The output includes `<testsuite>` elements containing `<testcase>` entries with attributes for execution time, status, and failure messages, making it compatible with Jenkins, GitLab CI, and other JUnit-consuming tools.

### How do I specify a custom output directory for XML reports?

Pass a directory path to the `--gtest_output` flag: `./test --gtest_output=xml:./reports/`. GoogleTest automatically names the file based on the test binary name (e.g., [`test_suite_1.xml`](https://github.com/google/googletest/blob/main/test_suite_1.xml)) and places it in the specified directory, incrementing the numeric suffix if files already exist.

### Can I add custom metadata to GoogleTest XML output?

Yes. Within any test case, call **`RecordProperty(key, value)`** on the current test result. These key-value pairs appear as XML attributes on the `<testcase>` element, allowing you to annotate tests with build numbers, environment details, or categorization tags.

### Is it possible to disable the default XML generator in GoogleTest?

Yes. Obtain the `TestEventListeners` instance from `UnitTest::GetInstance()->listeners()`, call **`Release(listeners.default_xml_generator())`** to remove the default printer, and optionally install a custom listener via **`SetDefaultXmlGenerator`**. This is useful when you need to suppress XML output or replace it with an alternative format entirely.