Result Upload
The CLI ships three result-upload commands that share a single workflow:
qasphere junit-upload [options] <files..>
qasphere playwright-json-upload [options] <files..>
qasphere allure-upload [options] <directories..>
All three match test results to existing QA Sphere test cases using markers in the test name (or framework-specific annotations) and upload them as a new or existing test run.
For language- and framework-specific setup, see the per-framework guides:
- Playwright Integration
- Cypress Integration
- Python / pytest Integration
- WebdriverIO Integration
- Auto-create test cases with Playwright
Supported report formats and framework coverage
The CLI is language- and framework-agnostic. It speaks three report formats, with JUnit XML acting as the universal lingua franca:
- JUnit XML (
junit-upload) — supported by virtually every test framework across every language. If your tool can produce JUnit-style XML, the CLI can upload it. - Playwright JSON (
playwright-json-upload) — Playwright's native JSON report. Adds support for test annotations as a more reliable matching method than markers in test names. - Allure (
allure-upload) — Allure results directories (*-result.json). Adds TMS link matching for test case linking.
The CLI itself ships as an npm package, but it does not require your project to be JavaScript:
| Language | Frameworks / tools |
|---|---|
| JavaScript / TypeScript | Playwright, Cypress, Jest, Mocha, WebdriverIO, Vitest |
| Python | pytest, unittest, Robot Framework |
| Java / Kotlin | JUnit 4/5, TestNG, Selenium, Appium |
| Go | go test (with -v and go-junit-report) |
| C# / .NET | NUnit, xUnit, MSTest |
| Rust | cargo test (with cargo2junit) |
| Ruby | RSpec, Minitest |
| PHP | PHPUnit |
If your stack isn't listed but can emit JUnit XML, Playwright JSON, or Allure results, it works.
Upload modes
Each command supports two modes:
- Upload into an existing run — pass
-r, --run-url <url>pointing at a QA Sphere run. The project code and run ID are extracted from the URL. - Create a new run — omit
--run-url. Use--project-code,--run-name, and--create-tcasesto control how the run is created.
# Upload into an existing run
qasphere junit-upload -r https://qas.eu1.qasphere.com/project/PRJ/run/23 ./test-results.xml
# Create a new run automatically
qasphere junit-upload ./test-results.xml
# Create a new run with explicit project and run name
qasphere junit-upload --project-code PRJ --run-name "v1.4.4-rc5" ./test-results.xml
Options
All three upload commands share the same option surface.
| Option | Description |
|---|---|
-r, --run-url <url> | URL of an existing test run to upload into. Project code and run ID are extracted from the URL. |
--project-code <code> | Project code for creating a new run (when --run-url is not set). Can be auto-detected from markers, but explicit is recommended. |
--run-name <template> | Name template for the new test run. Supports {env:VAR} and date placeholders. Default: "Automated test run - {MMM} {DD}, {YYYY}, {hh}:{mm}:{ss} {AMPM}" |
--create-tcases | Create new test cases in QA Sphere for results that have no valid marker. Generates a mapping file (qasphere-automapping-YYYYMMDD-HHmmss.txt). Only applies when creating a new run. |
--attachments | Detect and upload file attachments (screenshots, videos, traces) alongside each result. |
--force | Ignore API request errors, invalid test case mappings, or attachment problems and continue uploading. |
--ignore-unmatched | Suppress individual unmatched-test messages; show a summary count only. |
--skip-report-stdout <when> | When to skip stdout from test results. Choices: on-success, never (default). |
--skip-report-stderr <when> | When to skip stderr from test results. Choices: on-success, never (default). |
--verbose | Show full stack traces on errors. |
-h, --help | Show command help. |
Run-name template placeholders
The --run-name option supports the following placeholders. It is only honored when creating a new run (i.e. when --run-url is not set).
| Placeholder | Description |
|---|---|
{env:VAR_NAME} | Environment variable value |
{YYYY}, {YY} | 4-digit / 2-digit year |
{MMM} | 3-letter month (Jan, Feb, …) |
{MM} | 2-digit month |
{DD} | 2-digit day |
{HH} | 2-digit hour, 24-hour format |
{hh} | 2-digit hour, 12-hour format |
{mm}, {ss} | Minutes / seconds |
{AMPM} | AM/PM indicator |
Example:
qasphere junit-upload \
--project-code PRJ \
--run-name "CI Build {env:BUILD_NUMBER} - {YYYY}-{MM}-{DD}" \
./test-results.xml
With BUILD_NUMBER=v1.4.4-rc5 on 2026-01-01, this produces a run named CI Build v1.4.4-rc5 - 2026-01-01.
Test case matching
Results are linked to QA Sphere test cases via markers. The CLI checks them in the order shown below and falls back to the next format if a result doesn't match.
JUnit XML
JUnit XML supports three marker styles, checked in order:
-
Hyphenated marker (all languages):
PROJECT-SEQUENCEanywhere in the test name.PROJECTis your project code;SEQUENCEis the test case number (minimum 3 digits, zero-padded if needed). Matched case-insensitively.PRJ-002: Login with valid credentialsLogin with invalid credentials: PRJ-1312
-
Underscore-separated hyphenless marker (pytest, Go, Rust, …): for languages where hyphens aren't allowed in test names. The test name must start with
test(case-insensitive).test_prj002_login_with_valid_credentialstest_login_with_invalid_credentials_prj1312
-
CamelCase hyphenless marker (Go, Java): detected at the start (after the
Testprefix) or end of the name. The test name must start withTest(case-insensitive).TestPrj002LoginWithValidCredentialsTestLoginWithValidCredentialsPrj1312
Playwright JSON
Playwright JSON supports two methods, checked in order:
-
Test annotations (recommended) — add a Playwright test annotation with
type: "test case"(case-insensitive) and the full QA Sphere test case URL asdescription:test(
'user login',
{
annotation: {
type: 'test case',
description: 'https://qas.eu1.qasphere.com/project/PRJ/tcase/123',
},
},
async ({ page }) => {
// test code
}
) -
Hyphenated marker in the test name — same
PROJECT-SEQUENCEformat as JUnit. Hyphenless markers are not supported for Playwright JSON.
Allure
Allure results use one *-result.json file per test in a results directory. allure-upload matches via:
- TMS links (recommended) —
links[]entries with:type: "tms"url: QA Sphere test case URL, e.g.https://qas.eu1.qasphere.com/project/PRJ/tcase/123
- TMS link name fallback — if
urlis not a QA Sphere URL, the marker inlinks[].nameis used (e.g.PRJ-123) - Marker in
name— samePROJECT-SEQUENCEformat as JUnit
Only Allure JSON result files (*-result.json) are supported. Legacy Allure 1 XML files are ignored.
If markers are missing, the upload fails by default. Use --create-tcases to automatically create test cases in QA Sphere for unmatched results, or --ignore-unmatched / --force to bypass the mismatch without creating them.
Run-level logs
The CLI automatically detects global or suite-level failures (typically setup/teardown issues that aren't tied to a specific test case) and uploads them as run-level logs:
- JUnit XML — suite-level
<system-err>elements and empty-name<testcase>entries with<error>or<failure>(e.g. Maven Surefire's synthetic entries for setup/teardown failures). - Playwright JSON — top-level
errors[]entries (global setup/teardown failures). - Allure — failed or broken
befores/aftersfixtures in*-container.jsonfiles (e.g. pytest session/module-level setup/teardown failures).
Common examples
# Upload with attachments
qasphere junit-upload --attachments ./test1.xml
# Force upload even with missing test cases or attachments
qasphere junit-upload --force ./test-results.xml
# Suppress per-test unmatched messages (gradual test-case linking)
qasphere junit-upload --ignore-unmatched ./test-results.xml
# Skip stdout for passed tests to reduce payload size
qasphere junit-upload --skip-report-stdout on-success ./test-results.xml
# Allure upload into an existing run
qasphere allure-upload -r https://qas.eu1.qasphere.com/project/P1/run/23 ./allure-results
# Continue Allure upload when some *-result.json files are malformed
qasphere allure-upload --force -r https://qas.eu1.qasphere.com/project/P1/run/23 ./allure-results