Skip to main content

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:

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:

LanguageFrameworks / tools
JavaScript / TypeScriptPlaywright, Cypress, Jest, Mocha, WebdriverIO, Vitest
Pythonpytest, unittest, Robot Framework
Java / KotlinJUnit 4/5, TestNG, Selenium, Appium
Gogo test (with -v and go-junit-report)
C# / .NETNUnit, xUnit, MSTest
Rustcargo test (with cargo2junit)
RubyRSpec, Minitest
PHPPHPUnit

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-tcases to 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.

OptionDescription
-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-tcasesCreate 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.
--attachmentsDetect and upload file attachments (screenshots, videos, traces) alongside each result.
--forceIgnore API request errors, invalid test case mappings, or attachment problems and continue uploading.
--ignore-unmatchedSuppress 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).
--verboseShow full stack traces on errors.
-h, --helpShow 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).

PlaceholderDescription
{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:

  1. Hyphenated marker (all languages): PROJECT-SEQUENCE anywhere in the test name. PROJECT is your project code; SEQUENCE is the test case number (minimum 3 digits, zero-padded if needed). Matched case-insensitively.

    • PRJ-002: Login with valid credentials
    • Login with invalid credentials: PRJ-1312
  2. 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_credentials
    • test_login_with_invalid_credentials_prj1312
  3. CamelCase hyphenless marker (Go, Java): detected at the start (after the Test prefix) or end of the name. The test name must start with Test (case-insensitive).

    • TestPrj002LoginWithValidCredentials
    • TestLoginWithValidCredentialsPrj1312

Playwright JSON

Playwright JSON supports two methods, checked in order:

  1. Test annotations (recommended) — add a Playwright test annotation with type: "test case" (case-insensitive) and the full QA Sphere test case URL as description:

    test(
    'user login',
    {
    annotation: {
    type: 'test case',
    description: 'https://qas.eu1.qasphere.com/project/PRJ/tcase/123',
    },
    },
    async ({ page }) => {
    // test code
    }
    )
  2. Hyphenated marker in the test name — same PROJECT-SEQUENCE format 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:

  1. 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
  2. TMS link name fallback — if url is not a QA Sphere URL, the marker in links[].name is used (e.g. PRJ-123)
  3. Marker in name — same PROJECT-SEQUENCE format as JUnit

Only Allure JSON result files (*-result.json) are supported. Legacy Allure 1 XML files are ignored.

If a result has no marker

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 / afters fixtures in *-container.json files (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