Skip to main content

Reporting JUnit XML from any language

How to produce JUnit XML from Playwright, pytest, Maven, Gradle, PHPUnit, .NET, and Go and send it to Qably from CI.

Qably parses any report following the standard <testsuite>/<testcase> structure, deriving test status from <failure>, <error>, or <skipped> elements. Generate the XML file using your framework tooling and transmit it to Qably in your CI pipeline.

JavaScript and TypeScript

Jest and Vitest are covered in step 4 of the quickstart.

Commands by runner

PLAYWRIGHT_JUNIT_OUTPUT_NAME=results.xml npx playwright test --reporter=junit

Notes on each runner

Playwright's built-in JUnit reporter writes to standard output unless a file is specified, either through an environment variable or the config file.

It can also be configured once in playwright.config.ts: reporter: [['junit', { outputFile: 'results.xml' }]].

mvn test writes one report per test class with no extra flag; the Surefire plugin does this by default.

PHPUnit writes the JUnit XML report to the file passed to --log-junit.

Add the JUnitXml.TestLogger NuGet package to the test project, then pass the logger on the command line.

go-junit-report reads the output of go test. Its -set-exit-code flag makes it exit with status 1 when a test fails, so a failing test still fails the CI step.

Case identity and suites

Important: A case is identified by its classname and name together, so two tests named test_login in different classes stay separate cases. When the name already starts with the classname, the name alone is the identity. If two different tests in a suite resolve to the same identity, Qably does not merge them into one case: it reports the collision in the ingest response (caseIdentityCollisions) so you can rename one of them.

pytest writes every test into a single <testsuite name="pytest">, so Qably groups all pytest cases in one suite named pytest. The junit_suite_name option only renames that root suite; it does not split it. To keep suites apart, run pytest once per group of tests (for example, one run per file) and send each report separately, each with its own externalId.