Skip to main content

JUnit XML

TestFly generates a JUnit-compatible XML report at target/surefire-reports/TEST-TestFly.xml. This format is understood by virtually every CI system and test reporting tool.


Report location​

target/
└── surefire-reports/
└── TEST-TestFly.xml

Format​

<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="TestFly" tests="12" failures="1" errors="0" skipped="1" time="34.21">

<testcase classname="LoginTest" name="validLogin" time="2.341"/>

<testcase classname="CheckoutTest" name="checkout_withInvalidCard" time="1.823">
<failure message="Expected [Order confirmed] but found [Payment declined]"
type="org.openqa.selenium.NoSuchElementException">
org.openqa.selenium.NoSuchElementException: no such element
at com.example.tests.CheckoutTest.checkout_withInvalidCard(CheckoutTest.java:42)
...
</failure>
</testcase>

<testcase classname="ProfileTest" name="updateAvatar" time="0.0">
<skipped/>
</testcase>

</testsuite>

Failure messages​

The message attribute on <failure> contains the actual assertion message or exception message from your test — not a generic "Test failed" placeholder.

This means CI tools that display failure summaries (GitHub Actions, Jenkins, Azure Pipelines) show meaningful error descriptions without needing to open the full report.


CI integration​

GitHub Actions — dorny/test-reporter​

- name: Publish test results
uses: dorny/test-reporter@v1
if: always()
with:
name: TestFly Results
path: '**/surefire-reports/TEST-*.xml'
reporter: java-junit
fail-on-empty: false

Jenkins​

post {
always {
junit '**/surefire-reports/TEST-*.xml'
}
}

Azure Pipelines​

- task: PublishTestResults@2
condition: always()
inputs:
testResultsFormat: JUnit
testResultsFiles: '**/surefire-reports/TEST-*.xml'
testRunTitle: 'TestFly'

Maven Surefire XML​

Maven Surefire also generates its own XML files per class in target/surefire-reports/. Both sets of XML files are valid JUnit format and can be published together.

To publish all XML files:

path: 'target/surefire-reports/TEST-*.xml'