GoogleTest XML Output Format: How It Works and What It Captures for CI Integration
GoogleTest outputs JUnit-compatible XML through the XmlUnitTestResultPrinter class, enabling CI systems to parse test results, failures, timestamps, and custom properties from a standardized report file.
The GoogleTest XML output format provides a machine-readable report of test execution results that integrates seamlessly with Jenkins, GitHub Actions, CircleCI, and other continuous integration platforms. When you invoke the --gtest_output=xml:<path> flag or set the XML_OUTPUT_FILE environment variable, the framework emits a structured document that mirrors the internal UnitTest hierarchy. This format captures everything from execution times and source file locations to detailed failure messages and user-defined properties.
How GoogleTest Generates XML Reports
The XML generation logic resides in the XmlUnitTestResultPrinter class, implemented in googletest/src/gtest.cc. When the test run completes, the method OnTestIterationEnd opens the destination file specified by the user and serializes the entire test hierarchy into XML.
The printer traverses three nested levels:
<testsuites>– Represents the completeUnitTestobject (the entire test program).<testsuite>– Maps to eachTestSuite(previously called test case in older terminology).<testcase>– Represents individualTestInfoobjects (specific test functions).
This hierarchy ensures that CI tools can aggregate statistics at the suite level while still accessing granular details for individual test failures.
XML Structure and Reserved Attributes
GoogleTest defines specific attribute sets to maintain JUnit compatibility and provide comprehensive metadata.
The testsuites Root Element
The root <testsuites> element uses attributes defined in kReservedTestSuitesAttributes to summarize the entire test execution:
tests– Total test countfailures– Number of failed testsdisabled– Count of disabled testserrors– Fatal errorstime– Total execution durationtimestamp– ISO 8601 timestamp of the runrandom_seed– When test sharding is active
Test Suite Elements
Each <testsuite> element inherits the above attributes and adds kReservedTestSuiteAttributes, specifically the skipped attribute indicating how many tests were skipped in that suite.
Test Case Elements
Individual <testcase> elements carry kReservedTestCaseAttributes:
classname– Fully qualified test suite namename– Specific test namestatus–runornotruntime– Execution duration for this specific testtype_param– Type parameter for typed testsvalue_param– Value parameter for parameterized testsfileandline– Source code location
Data Sanitization and XML Safety
Before writing to disk, XmlUnitTestResultPrinter sanitizes all content through three specific methods in gtest.cc:
EscapeXml– Replaces reserved XML characters (<,>,&,',") with their corresponding entities (<,>,&,',").RemoveInvalidXmlCharacters– Strips characters that are illegal in XML 1.0 (control characters below0x20except tab, newline, and carriage return).IsNormalizableWhitespace– Normalizes whitespace within attribute values to prevent formatting issues.
These validations ensure that failure messages containing code snippets or binary data cannot corrupt the XML structure, maintaining parseability for CI parsers.
Capturing Test Failures and Custom Properties
Failure Details
When a test fails, OutputXmlTestCaseForTestResult appends a <failure> child element to the <testcase>. This element includes:
- The failure message and type (e.g.,
fatal) - Optional
fileandlineattributes pointing to the assertion location - Full stack traces or failure details wrapped in CDATA sections to preserve formatting and special characters
Custom Properties
Tests can inject metadata using RecordProperty:
TEST(MySuite, MyTest) {
RecordProperty("category", "integration");
RecordProperty("ticket", "JIRA-123");
EXPECT_EQ(1, 1);
}
The printer's OutputXmlTestProperties method validates these names against reserved attributes and writes them as <property name="..." value="..."/> elements inside the <testcase> node. This allows CI dashboards to filter or categorize tests based on custom metadata.
Configuring XML Output for CI Pipelines
GoogleTest supports two primary mechanisms for specifying the output destination:
Command-line flag:
./my_test_binary --gtest_output=xml:report.xml
# Or use xml: alone for default filename test_detail.xml in current directory
Environment variable:
export XML_OUTPUT_FILE=/path/to/report.xml
./my_test_binary
The environment variable is parsed in googletest/src/gtest-port.cc, making it ideal for Bazel-based builds or containerized CI environments where flags might be harder to inject.
Sharding Considerations
When running tests with sharding across multiple workers or machines, each shard writes its own XML file. The timestamp attribute allows CI systems to aggregate results chronologically. Most CI platforms (Jenkins with JUnit plugin, GitHub Actions with test reporters) automatically merge multiple XML files into a unified test report.
Code Examples for CI Integration
GitHub Actions workflow:
steps:
- name: Run tests with XML output
run: ./my_test_binary --gtest_output=xml:test_report.xml
- name: Upload test results
uses: actions/upload-artifact@v3
with:
name: test-results
path: test_report.xml
- name: Publish Test Report
uses: dorny/test-reporter@v1
if: always()
with:
name: GoogleTest Results
path: test_report.xml
reporter: jest-junit
Adding searchable metadata:
TEST_F(DatabaseTest, ConnectionTimeout) {
RecordProperty("component", "database");
RecordProperty("priority", "high");
// Test implementation
}
Verification and Testing
GoogleTest's own suite validates XML generation in googletest/test/gtest_xml_output_unittest_.cc, while the Python harness [gtest_xml_test_utils.py](https://github.com/google/googletest/blob/main/googletest/test/gtest_xml_test_utils.py) provides normalization utilities to compare generated XML against golden files. These tests verify:
- Proper escaping of special characters in failure messages
- Correct attribute presence for empty vs. populated test suites
- Behavior when output listeners are disabled or filters are applied
- File handling for multiple output files and custom naming conventions
Additional file handling tests reside in [googletest/test/gtest_xml_outfiles_test.py](https://github.com/google/googletest/blob/main/googletest/test/gtest_xml_outfiles_test.py), ensuring reliability when CI systems specify output directories or unique filenames.
Summary
- The
XmlUnitTestResultPrinterclass ingoogletest/src/gtest.ccgenerates JUnit-compatible XML when triggered by--gtest_output=xmlor theXML_OUTPUT_FILEenvironment variable. - The format captures hierarchical data through
<testsuites>,<testsuite>, and<testcase>elements with reserved attributes defined inkReservedTestSuitesAttributes,kReservedTestSuiteAttributes, andkReservedTestCaseAttributes. - Output sanitization occurs via
EscapeXmlandRemoveInvalidXmlCharactersto ensure well-formed XML regardless of test failure content. <failure>elements contain detailed error messages in CDATA sections, while<properties>elements store custom metadata added viaRecordProperty.- CI systems can consume these reports directly for test result visualization, trend analysis, and build pass/fail determination.
Frequently Asked Questions
What is the difference between <testsuite> and <testcase> in GoogleTest XML?
A <testsuite> represents a C++ test class or parameterized test fixture, aggregating statistics like total tests and failures for that group. A <testcase> represents a single test method (individual TEST or TEST_F function). The suite contains multiple test cases, and each test case contains its own timing, status, and optional failure details.
How do I prevent GoogleTest XML output from containing invalid characters?
GoogleTest automatically sanitizes output through internal helper methods. The EscapeXml function converts HTML/XML entities, while RemoveInvalidXmlCharacters strips illegal control characters. You do not need manual sanitization; the framework guarantees valid XML even when tests output binary data or crash logs.
Can I generate XML output without using command-line flags?
Yes. Set the XML_OUTPUT_FILE environment variable to your desired path before running the test binary. The framework reads this variable in gtest-port.cc and triggers the XML printer automatically. This approach is particularly useful in Bazel test environments where flags are managed by the build system rather than the user.
Does GoogleTest XML support parallel test execution reports?
Yes. When using test sharding (dividing tests across multiple processes or machines), each shard generates its own XML file with a unique timestamp. CI systems can aggregate these files using the timestamp attribute. The tests and failures counts in each file reflect only that shard's execution, allowing proper consolidation in the CI dashboard.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →