`)
* `src` - Media source URL (http/https URLs only)
* `width` - Element width
### Tables (``, ` `)
* `colspan` - Column span
* `rowspan` - Row span
### Tables (``, ` `)
* `style` - Limited to `min-width` property only
## Fields That Support HTML
The following API request fields accept HTML content and are automatically sanitized:
* **Create Result**: Result `comment`
* **Create Run**: Run `description`
* **Clone Run**: Run `description`
* **Update Test Case**: Test case `comment` field and `description`/`expected` fields of individual steps
## Examples
### Basic Text Formatting
```html
This test case requires careful attention to the
user interface elements.
```
### Lists and Structure
```html
Test prerequisites:
User must be logged in
Account must have admin privileges
Database must be in test mode
```
### Links and References
```html
For more information, see the
API documentation .
```
### Tables
```html
Test Results Summary
Passed
25
Failed
3
```
### Removed Content
```html
paragraph with click handler
normal div
paragraph with class
paragraph with click handler
normal div
paragraph with class
```
**Malformed HTML Behavior**
When HTML content is malformed (such as missing opening/closing tags or unmatched quotes), the sanitization process may produce unexpected results:
* **Missing closing tags**: Content may be restructured or truncated
* **Unmatched quotes**: Attributes may be removed entirely
* **Invalid nesting**: Elements may be reordered or removed
* **Unknown elements**: Completely stripped from output
Always validate your HTML structure before sending it to the API to ensure predictable results.
---
# Agent Skill
URL: /docs/cli/agent-skill
The qas-cli repository ships a [SKILL.md](https://github.com/Hypersequent/qas-cli/blob/main/skills/qas-cli/SKILL.md) — a condensed reference written for AI coding agents (Claude Code, Cursor, and any other agent that supports the [skills](https://github.com/vercel-labs/skills) format). Once the skill is registered, the agent can drive QA Sphere on your behalf — listing projects, authoring test cases, opening and closing runs, posting results, and pulling reports — without you scripting any of it.
## Install the skill
```bash
npx skills add Hypersequent/qas-cli
```
The command writes the skill into your agent's local skill registry. Re-run it to update the skill in place.
Each agent has its own way of activating registered skills. See the [Vercel skills registry](https://github.com/vercel-labs/skills) for the current per-agent install instructions and supported runtimes.
## Prerequisites
* qas-cli installed (`npm install -g qas-cli` or available via `npx qas-cli`). See [Overview](https://qasphere.com/docs/cli).
* Authenticated session (`qasphere auth login`) or `QAS_TOKEN` + `QAS_URL` configured. See [Auth](https://qasphere.com/docs/cli/auth).
The skill reads the same `qasphere -h` output a human would, so it stays current with the installed CLI — there's nothing for you to keep in sync.
## What the agent can do
With the skill loaded, you can describe the outcome you want in natural language and the agent composes the right `qasphere api ...` calls. The CLI prints JSON; the agent renders it however the conversation needs — Markdown tables, matplotlib/Plotly charts, SVG, HTML, CSV exports.
A few examples that work out of the box:
* *"Plot the pass rate of the last 20 closed runs in project PRJ as a line chart."* → the agent calls `qasphere api runs list --project-code PRJ --closed true`, computes `passed / all` per run from `statusCounts`, renders a chart.
* *"Which folders in PRJ have the most failing tests this week?"* → combines `runs list`, `runs test-cases list`, and `folders list` to aggregate failures by folder.
* *"Generate a Markdown summary of run 42 with the pass/fail breakdown and a list of failing test case titles."* → calls `runs test-cases list --project-code PRJ --run-id 42` and formats the output.
* *"Create a folder structure for the Authentication area with Login, OAuth, and MFA subfolders, then scaffold five test cases under Login."* → calls `folders bulk-create` followed by `test-cases create`.
You don't need to pre-script anything — describe the report or change you want, and let the agent compose the API calls.
## Further reading
* Source: [`skills/qas-cli/SKILL.md`](https://github.com/Hypersequent/qas-cli/blob/main/skills/qas-cli/SKILL.md) in the qas-cli repository — the canonical reference the agent reads.
* Skill format: [vercel-labs/skills](https://github.com/vercel-labs/skills).
* Underlying commands: [Public API](https://qasphere.com/docs/cli/public-api) and [Result Upload](https://qasphere.com/docs/integrations/result-upload).
---
# Auth
URL: /docs/cli/auth
The CLI needs to know which QA Sphere instance to talk to and how to authenticate. Two methods are supported: interactive OAuth login (recommended) and an API token in environment or config files.
## OAuth login (recommended)
```bash
qasphere auth login
```
This prompts for your team name, opens a browser for authorization, and stores OAuth tokens persistently. The flow requires an interactive terminal (TTY) — it isn't suitable for headless CI.
OAuth sessions are valid for 90 days, with the window resetting on every CLI use. As long as you keep running `qasphere` commands, you won't need to re-authenticate. Tokens are refreshed automatically when within 5 minutes of expiry.
Other auth commands:
```bash
qasphere auth status # Show currently active credential and verify the server is reachable
qasphere auth logout # Clear stored credentials
```
### Where credentials are stored
OAuth tokens are written to the operating system keyring (under the `qasphere-cli` service) when one is available. If the keyring is unavailable, the CLI falls back to `~/.config/qasphere/credentials.json` with file mode `0600`.
## API token
For CI/CD pipelines and any non-interactive environment, configure an API token instead. Set:
* `QAS_TOKEN` — your QA Sphere API token (see the [API Authentication](/docs/api/authentication) guide for how to generate one)
* `QAS_URL` — base URL of your QA Sphere instance, e.g. `https://qas.eu1.qasphere.com`
These variables can be defined as environment variables, in a `.env` file, or in a `.qaspherecli` file in the current directory or any parent.
```sh
# .qaspherecli (or .env)
QAS_TOKEN=your_token
QAS_URL=https://qas.eu1.qasphere.com
```
Never commit `.env` or `.qaspherecli` files containing real tokens. Use your CI provider's secret store (GitHub Actions Secrets, GitLab CI/CD Variables, Bitbucket Repository Variables) instead.
## Credential resolution order
When the CLI needs credentials, it resolves them in the following order (first match wins):
1. `QAS_TOKEN` and `QAS_URL` environment variables
2. `.env` file in the current working directory
3. System keyring (set by `qasphere auth login`)
4. `~/.config/qasphere/credentials.json` (fallback when keyring is unavailable)
5. `.qaspherecli` file in the current directory or any parent directory
If no source resolves, the CLI prints a setup guide to stderr and exits with status `1`.
## Generating an API token
API tokens are created in the QA Sphere web UI:
1. Click the gear icon in the top right corner.
2. Click **API Keys**.
3. Click **Create API Key** and save the generated value — you won't see it again.
The same token is used for raw REST calls — see [API Authentication](/docs/api/authentication) for details on scopes and rotation.
---
# Overview
URL: /docs/cli
The QA Sphere CLI (`qasphere`, published as the [`qas-cli`](https://www.npmjs.com/package/qas-cli) npm package) is the official command-line interface for QA Sphere. It exposes the full public API and supports four primary workflows:
* **Ad-hoc terminal use** — run `qasphere api ` commands to inspect or change QA Sphere state. Every command prints JSON to stdout for easy piping into tools like `jq`. See [Public API](https://qasphere.com/docs/cli/public-api).
* **Scripts and CI/CD automation** — orchestrate projects, folders, test cases, milestones, runs, and results from shell scripts and pipelines. See [CI/CD Integrations](https://qasphere.com/docs/integrations/ci-cd).
* **Test result uploads** — push JUnit XML, Playwright JSON, and Allure result directories at the end of an automated run. See [Result Upload](https://qasphere.com/docs/integrations/result-upload).
* **AI coding agents** — a bundled skill lets Claude Code, Cursor, and similar agents drive QA Sphere through the CLI in natural language. See [Agent Skill](https://qasphere.com/docs/cli/agent-skill).
qas-cli is open source:
[github.com/Hypersequent/qas-cli](https://github.com/Hypersequent/qas-cli).
Track development, report issues, and contribute on GitHub.
## Installation
### Requirements
Node.js 22.0.0 or higher. No other runtime is needed — the CLI works alongside Python, Go, Java, or any other test stack.
If you don't already have Node.js, install it via your system package manager:
* macOS: `brew install node`
* Ubuntu/Debian: `sudo apt install nodejs npm`
* Windows / other: download from [nodejs.org](https://nodejs.org/)
### Via npm (global)
```bash
npm install -g qas-cli
```
Verify:
```bash
qasphere --version
```
Update later with:
```bash
npm update -g qas-cli
```
### Via npx
```bash
npx qas-cli
```
On first use you'll be prompted to download the package. `npx qas-cli` works in every context the `qasphere` command does.
Verify:
```bash
npx qas-cli --version
```
npx caches packages. To force the latest version, run `npx clear-npx-cache`
(or pin a specific version, e.g. `npx qas-cli@0.5.0`).
## Shell completion
The CLI ships with tab completion for commands and options. Append the completion script to your shell profile:
**Zsh:**
```bash
qasphere completion >> ~/.zshrc
```
**Bash:**
```bash
qasphere completion >> ~/.bashrc
```
Restart your shell (or `source` the profile) and pressing `Tab` will autocomplete commands and flags.
## Rate limits
The QA Sphere API allows **20 requests per second per user**, shared across all of that user's
API keys and OAuth authorizations. Exceeding it returns `429 Too Many Requests`. See
[API Rate Limiting](/docs/api/api_intro#rate-limiting) for the full set of limits.
The CLI handles this for you. On a `429` it waits and retries automatically, honoring the
`Retry-After` header the API sends and otherwise backing off exponentially — up to 5 retries
over roughly 30 seconds. Result uploads are also deliberately paced: attachments upload at most
3 batches at a time, and results are posted in sequential batches rather than all at once. A
normal upload, even one with thousands of results, stays well under the limit.
Automatic retry on `429` was added in **v0.8.0**. On v0.7.0 and earlier the CLI fails
immediately when rate limited, which typically shows up as a failed upload step in CI. Check
your version with `qasphere --version` and upgrade with `npm update -g qas-cli`.
If you still hit rate limits on a current version, the usual cause is several CI jobs running
concurrently under the same QA Sphere user. Because the limit is per user rather than per API
key, adding more API keys will not help — give the parallel jobs separate user accounts instead.
## Where to next
* [Auth](https://qasphere.com/docs/cli/auth) — log in via OAuth or configure an API key.
* [Public API](https://qasphere.com/docs/cli/public-api) — call the full QA Sphere REST API from the terminal.
* [Result Upload](https://qasphere.com/docs/integrations/result-upload) — upload JUnit XML, Playwright JSON, or Allure results into a run. Framework guides and CI/CD examples live in the [Integrations](https://qasphere.com/docs/integrations-intro) section.
* [Agent Skill](https://qasphere.com/docs/cli/agent-skill) — register the CLI with Claude Code, Cursor, and other coding agents.
* [CI/CD Integrations](https://qasphere.com/docs/integrations/ci-cd) — wire the CLI into GitHub Actions, GitLab CI/CD, or Bitbucket Pipelines.
---
# Public API
URL: /docs/cli/public-api
The `qasphere api` command exposes the full QA Sphere public API as terminal commands. Every command prints JSON to stdout (errors to stderr) for clean piping into `jq`, scripts, and CI pipelines.
```bash
qasphere api [options]
```
Exit code is `0` on success, `1` on failure. Pass `-h` to any subcommand for its full signature, options, examples, and a link to the matching REST endpoint reference.
## Command tree
```
qasphere api
├── audit-logs
│ └── list # List audit log entries
├── custom-fields
│ └── list --project-code # List custom fields
├── files
│ └── upload --file # Upload a file attachment
├── folders
│ ├── list --project-code # List folders
│ └── bulk-create --project-code --folders # Create/update folders
├── milestones
│ ├── list --project-code # List milestones
│ └── create --project-code --title # Create milestone
├── projects
│ ├── list # List all projects
│ ├── get --project-code # Get project by code
│ └── create --code --title # Create project
├── requirements
│ └── list --project-code # List requirements
├── results
│ ├── create --project-code --run-id --tcase-id --status # Create result
│ └── batch-create --project-code --run-id --items # Batch create results
├── runs
│ ├── create --project-code --title --type --query-plans # Create run
│ ├── list --project-code # List runs
│ ├── clone --project-code --run-id --title # Clone run
│ ├── close --project-code --run-id # Close run
│ ├── test-cases
│ │ ├── list --project-code --run-id # List test cases in run
│ │ └── get --project-code --run-id --tcase-id # Get test case in run
│ └── logs
│ └── create --project-code --run-id --comment # Create run log
├── settings
│ ├── list-statuses # List result statuses
│ └── update-statuses --statuses # Update custom statuses
├── shared-preconditions
│ ├── list --project-code # List shared preconditions
│ └── get --project-code --id # Get shared precondition
├── shared-steps
│ ├── list --project-code # List shared steps
│ └── get --project-code --id # Get shared step
├── tags
│ └── list --project-code # List tags
├── test-cases
│ ├── list --project-code # List test cases
│ ├── get --project-code --tcase-id # Get test case
│ ├── count --project-code # Count test cases
│ ├── create --project-code --body # Create test case
│ └── update --project-code --tcase-id --body # Update test case
├── test-plans
│ └── create --project-code --body # Create test plan
└── users
└── list # List all users
```
`qasphere api files upload --file ...` uses the public batch upload endpoint internally and returns the first uploaded file from that response.
For per-endpoint request/response details, see the [REST API Endpoints reference](/docs/api/api_intro).
## Pagination
List commands support pagination via:
* `--page ` and `--limit ` — offset-based pagination
* `--sort-field ` and `--sort-order ` — sorting (where supported)
`audit-logs list` uses cursor-based pagination instead:
* `--after ` — continuation cursor from the previous page
* `--count ` — page size
## Passing JSON bodies
Commands that mutate complex resources (`runs create`, `test-cases create`/`update`, `test-plans create`, `results create`/`batch-create`, `folders bulk-create`, `settings update-statuses`) accept their payload three ways:
* `--body ''` — inline JSON string
* `--body-file ` — path to a JSON file
* Individual field flags — e.g. `--title`, `--status`, `--comment`
Field flags merge into `--body` / `--body-file` with field flags taking precedence. The combined body must always be valid JSON.
## Workflow examples
The examples below assume `QAS_TOKEN` and `QAS_URL` are configured (see [Auth](https://qasphere.com/docs/cli/auth)) and use [`jq`](https://stedolan.github.io/jq/) for JSON parsing.
### 1. Open a run, post results, and close it
Useful when results come from a tool that doesn't produce JUnit/Playwright/Allure output:
```bash
RUN_ID=$(qasphere api runs create --project-code PRJ \
--title "Smoke $(date +%Y-%m-%d)" --type static \
--query-plans '[{"tcaseIds": ["abc123", "def456"]}]' | jq -r '.id')
qasphere api results batch-create --project-code PRJ --run-id "$RUN_ID" \
--items '[{"tcaseId": "abc123", "status": "passed"}, {"tcaseId": "def456", "status": "failed", "comment": "timeout on /cart"}]'
qasphere api runs close --project-code PRJ --run-id "$RUN_ID"
```
### 2. Run-progress report
List open runs with their pass/fail/open counts:
```bash
qasphere api runs list --project-code PRJ --closed false \
| jq '.[] | {title, passed: .statusCounts.passed, failed: .statusCounts.failed, open: .statusCounts.open, total: .statusCounts.all}'
```
### 3. Pre-create a run, then upload automation results into it
```bash
RUN_ID=$(qasphere api runs create --project-code PRJ \
--title "CI build $BUILD_NUMBER" --type static \
--query-plans '[{"tcaseIds": ["abc123"]}]' \
--milestone-id 7 | jq -r '.id')
qasphere junit-upload -r "$QAS_URL/project/PRJ/run/$RUN_ID" ./test-results.xml
```
### 4. Bulk-create folders and test cases
```bash
qasphere api folders bulk-create \
--project-code PRJ \
--folders '[{"path": ["Authentication", "Login"]}, {"path": ["Authentication", "OAuth"]}]'
qasphere api test-cases create \
--project-code PRJ \
--body '{"title": "Login with valid credentials", "type": "standalone", "folderId": 1, "priority": "high"}'
```
## Error handling
* **Missing credentials** — the CLI prints a setup guide to stderr and exits with code `1`. See [Auth](https://qasphere.com/docs/cli/auth).
* **Validation errors** — invalid CLI arguments or API validation failures are reported to stderr with the offending option name.
* **HTTP errors** — formatted and printed to stderr. Use `--verbose` for full stack traces.
---
# Export
URL: /docs/export
QA Sphere allows exporting test case library in CSV (Comma-Separated Values) format. To do that:
1. Open a project and go to **Test Cases** tab
2. Click
3. Select **Export**
A new CSV file with the project abbreviation in the name will be saved under the browser's downloads.
The structure of the exported CSV file columns are as follows:
### Static Columns:
* **Folder**: The complete folder path to the test case
* **Type**: The type of test case - `standalone` or `template`
* **Name**: Title of the test case
* **Legacy ID**: Test case ID from previous test management system
* **Draft**: Whether the test case is a draft (`true` or `false`)
* **Priority**: Test case priority - `low`, `medium`, or `high`
* **Tags**: Comma-separated tags
* **Requirements**: Comma-separated requirements in format `[Title](URL)`
* **Links**: Comma-separated links in format `[Title](URL)`
* **Files**: JSON array containing file information with properties: `fileName`, `id`, `url`, `mimeType`, `size`
* **Preconditions**: Test case preconditions or description (in Markdown format)
* **Parameter Values**: JSON array for template test cases containing parameter sets
* **Template Suffix Params**: Comma-separated parameter names used in filled test case naming
### Dynamic Columns:
After the static columns, there are dynamic columns for:
#### Steps
* **Step 1**, **Expected 1**
* **Step 2**, **Expected 2**
* ... (continues based on the maximum number of steps in any test case)
#### Custom Fields
Custom fields appear after step columns with the format:
* `custom_field_text_{systemName}` for text fields
* `custom_field_richtext_{systemName}` for rich text fields
* `custom_field_dropdown_{systemName}` for dropdown fields
* `custom_field_checkbox_{systemName}` for checkbox fields
Custom field values are exported as JSON objects containing:
* `value`: The field value
* `isDefault`: Whether this is the default value (if applicable)
## Export Format Details
### Column Organization:
* The number of "Step" and "Expected" columns is determined by the test case with the most steps
* All rows are padded with empty values to match the maximum number of steps
* Custom field columns are included only if custom fields exist in the project
* Rows are sorted first by Folder name, then by test case Title within each folder
### Data Formatting:
* **HTML to Markdown**: Content in preconditions and steps is converted to Markdown format
* **Template Test Cases**: Exported with their parameter values and template configuration
* **File Attachments**: Exported as JSON with complete metadata for re-import
* **Custom Fields**: Exported with their current values and default status
### Template Test Cases in Export:
When exporting template test cases:
* The template definition is exported with `Type` set to `template`
* Parameter values are included in the `Parameter Values` column
* Template suffix parameters are preserved for consistent naming on re-import
* Filled test cases generated from templates are exported separately as standalone test cases
This comprehensive structure allows for:
* Complete backup of test case libraries including custom fields and templates
* Migration between QA Sphere projects
* Integration with external tools that support CSV format
* Preservation of all test case metadata and relationships
---
# Import with AI
URL: /docs/import-with-ai
QA Sphere's Bulk Write with AI feature can parse your existing spreadsheets and automatically generate test cases from them. This is useful when your data doesn't match QA Sphere's exact CSV format or when migrating from other tools.
## When to Use
This method works well for:
* Spreadsheets with up to a few hundred test cases
* Files that don't follow QA Sphere's standard CSV structure
* Quick migrations where you want AI to interpret and structure your data
For larger imports or when you need precise control over the import, use the standard [CSV import](/docs/import) instead.
## How to Import with AI
1. Open your project and go to the **Test Cases** tab
2. Click **Create** → **Bulk Test Cases with AI**
3. Attach your CSV or Excel file
4. In the "Ask AI" prompt, enter:
```
Parse attached CSV file and generate test cases based on its data.
```
5. Review the generated test cases and make any adjustments
6. Save the test cases to your project
The AI will interpret your file structure and suggest test cases based on the content. Some variation may occur depending on how your data is organized.
Generated cases that duplicate test cases already in the project are highlighted during review, so re-running an import does not quietly double your library. A confirmation dialog also appears if you navigate away with a batch still in progress. See [AI Features](/docs/tms/ai-features) for more on duplicate detection and AI rules.
## Tips
* Include clear column headers in your spreadsheet to help the AI understand the data
* Review the generated test cases before saving, as the AI may interpret ambiguous data differently than expected
* For complex spreadsheets, you can provide additional context in the prompt to guide the AI
---
# Import
URL: /docs/import
QA Sphere offers several ways to import your test cases:
1. **Import from another test management system** - Built-in importers for Qase, Testomat, and Zebrunner (described below)
2. **Self-service CSV import** - Format your file using QA Sphere's CSV structure and import it directly (described below)
3. **[Import with AI](/docs/import-with-ai)** - Use the Bulk Write with AI feature to parse and import your existing spreadsheets
4. **Assisted import** - Send your spreadsheet to our team and we'll handle the import for you - [contact support](https://qasphere.com/contact)
## Importing from Another Test Management System
QA Sphere has built-in importers for other test management systems, so migrating does not require reshaping your data into QA Sphere's CSV format first. Currently supported sources:
* **Qase**
* **Testomat**
* **Zebrunner**
Open a project, go to the **Test Cases** tab, click and select **Import**, then choose your source system instead of CSV.
More source systems are added over time. If you are migrating from a TMS that is not listed, [contact our support team](https://qasphere.com/contact) — we can often handle the migration for you, and export-to-CSV followed by the CSV import below works for most tools.
## CSV Import
QA Sphere allows importing test case library in CSV format. To do that:
1. Open a project and go to **Test Cases** tab
2. Click
3. Select **Import**
4. A CSV Import form will pop up. Select separator, directory to import into, and pick a file.
Here's a description of the import process and structure:
## Test Case Structure:
Each test case in the CSV table should have the following column structure:
### Static Columns (Required):
* **Folder**: The complete folder path to the test case (e.g., "Integration/API")
* **Name**: The title of the test case (max 511 characters)
### Optional columns:
* **Type**: The type of test case - `standalone` (default) or `template`
* **Draft**: Whether the test case is work in progress (`true` or `false`)
* **Tags**: Comma-separated tags for grouping and filtering test cases
* **Requirements**: Comma-separated requirements in format `[Title](URL)`
* **Links**: Comma-separated links in format `[Title](URL)`
* **Files**: JSON array of file objects with properties: `fileName`, `id`, `url`, `mimeType`, `size`
* **Preconditions**: Test case preconditions or description (supports Markdown)
* **Priority**: Test case priority - `low`, `medium`, or `high` (Default: `medium`)
* **Legacy ID**: Test case ID from existing test management system (optional, max 255 characters)
* **Parameter Values**: JSON array for template test cases (see Template Test Cases section)
* **Template Suffix Params**: Comma-separated parameter names for filled test case naming
* **Folder Comment**: A comment to set on the test case's folder. The value is applied to the folder named in the **Folder** column, so it only needs to be filled on one row per folder.
### Dynamic Columns:
After the static columns, there are dynamic columns for:
#### Steps
* **Step 1**, **Expected 1**
* **Step 2**, **Expected 2**
* ... (continues based on the maximum number of steps in any test case)
Both Step and Expected columns support Markdown formatting.
#### Custom Fields
Custom fields appear after step columns with the format:
* `custom_field_text_{systemName}` for text fields
* `custom_field_richtext_{systemName}` for rich text fields
* `custom_field_dropdown_{systemName}` for dropdown fields
* `custom_field_checkbox_{systemName}` for checkbox fields
For **dropdown** and **checkbox** fields, the value must match one of the options defined on the field
exactly (case-sensitive). Checkbox fields are defined with one or two options, where the first option is
the checked value and the second, if present, is the unchecked value — a one-option checkbox is left
unchecked by supplying an empty value. See the
[Test Case Custom Fields API](/docs/api/tcases_custom_fields) for how to read a project's field
definitions and their exact option values.
Custom field values are JSON objects with properties:
* `value`: The field value (max 255 characters)
* `isDefault`: Whether this is the default value (optional, boolean)
## Template Test Cases
Template test cases allow you to create test case templates with placeholders that can be filled with different parameter values. This is useful for testing the same scenario with different data sets.
### How Templates Work:
1. Create a template test case with `Type` set to `template`
2. Use placeholders in the format `${parameter_name}` in these test case fields - title, preconditions, steps
3. Provide parameter values in the `Parameter Values` column as a JSON array
4. QA Sphere generates filled test cases for each parameter set
### Parameter Values Format:
```json
[
{
"priority": "high",
"values": {
"username": "admin",
"password": "admin123"
}
},
{
"priority": "medium",
"values": {
"username": "user",
"password": "user456"
}
}
]
```
### Template Suffix Params:
Use the `Template Suffix Params` column to specify which parameters should appear in the generated test case title. For example, if you set `username,password` and your template is titled "Login Test", the generated test cases will be:
* Login Test (username=admin, password=admin123)
* Login Test (username=user, password=user456)
Alternatively, you can declare title as Login Test for user "$\{user} with password "$\{password}" and skip Template Suffix Params
Parameters that are present in the title will be ignored if set in `Template Suffix Params`.
Since they are already part of the title we don't allow showing them twice.
## File Attachments
Files referenced in the CSV must first be uploaded to QA Sphere via the API. The `Files` column should contain a JSON array with file metadata:
```json
[
{
"fileName": "screenshot.png",
"id": "file-123",
"url": "https://qasphere.com/files/file-123",
"mimeType": "image/png",
"size": 102400
}
]
```
See the [API documentation](/docs/api/upload_file) for uploading files.
## Additional Features:
* **Validation**: Each test case is validated for correct formatting, field lengths, and required fields
* **Custom Fields**: Must be pre-defined in the project before import
* **Folder Structure**: Folders are created automatically based on the paths specified
* **Author Assignment**: The import process automatically assigns the importing user as the author
* **Contributor Management**: After a successful import, it creates the importing user as a contributor to the project
Reference: [example CSV](/docs-attachments/example.csv)
---
# GitHub Integration
URL: /docs/github
QA Sphere seamlessly integrates with GitHub, allowing you to create GitHub issues directly while going through test cases in a test run. This integration streamlines your workflow and ensures efficient issue tracking.
## Configuring GitHub Issues Integration
To integrate GitHub Issues into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **GitHub** from the list of available integrations.
5. Install the [QA Sphere app](https://github.com/apps/qasphere-bot) in your GitHub account.
6. Provide your GitHub account URL for integration.
7. Once the connection is established, select or create a GitHub project for QA Sphere to add issues to.
## Using GitHub Issues Integration
To create a GitHub issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add GitHub Issue**.
A new GitHub issue will be created under the assigned GitHub project. All issues created for the test case will be saved under the **Action History** for this test run, providing a clear trail of documentation.
## Disable GitHub Integration
To detach GitHub project from QA Sphere follow the steps below:
1. Go to **Settings**
2. Select **Issue Trackers**
3. Click the trash can icon next to the project with the integration you want to remove.
4. Agree to the integration deletion.
Note: The GitHub account can be further reused for another integration or you can choose to delete the saved account when adding new GitHub integration.
## Benefits of GitHub Integration
* **Streamlined Workflow**: Create issues without leaving QA Sphere.
* **Consistency**: Ensure all issues are properly documented and tracked.
* **Traceability**: Easily link test cases to specific GitHub issues.
* **Efficiency**: Reduce time spent switching between tools.
By leveraging this integration, your team can maintain a more cohesive and efficient testing and issue management process.
---
# Overview
URL: /docs/integrations-intro
In software development and quality assurance, effective bug tracking and management are crucial for delivering high-quality products. This is where issue trackers come into play, serving as the central nervous system for managing software defects, feature requests, and other project-related tasks.
In the following sections, we'll dive deeper into how to set up and use issue tracker integrations in QA Sphere, ensuring that your team can leverage these powerful tools to their full potential in your quality assurance processes.
* [GitHub](https://qasphere.com/docs/github)
* [Jira](https://qasphere.com/docs/jira)
* [GitLab](https://qasphere.com/docs/gitlab)
* [Linear](https://qasphere.com/docs/linear)
* [Notion](https://qasphere.com/docs/notion)
Beyond issue trackers, QA Sphere also integrates with:
* [Slack](https://qasphere.com/docs/slack): test run and result notifications in your channels, plus `/qasphere` slash commands.
* [MCP Server](https://qasphere.com/docs/integrations/mcp): connect Claude, Cursor, and other AI clients to your test cases, runs, and results.
* [Webhooks](/docs/webhooks): send events to any HTTP endpoint.
For test automation, the [QA Sphere CLI](/docs/cli) connects your test frameworks and pipelines to QA Sphere:
* [Result Upload](https://qasphere.com/docs/integrations/result-upload): upload results from Playwright, Cypress, pytest, WebdriverIO, or any framework that produces JUnit XML, Playwright JSON, or Allure results.
* [CI/CD Integrations](https://qasphere.com/docs/integrations/ci-cd): automate uploads from GitHub Actions, GitLab CI/CD, and Bitbucket Pipelines.
## What is an Issue Tracker?
An issue tracker, also known as a bug tracker or ticket system, is a software tool that helps development and QA teams manage and maintain a list of issues (bugs, feature requests, tasks) as they are identified through the software development lifecycle. These tools allow teams to:
* Record and describe issues in detail
* Assign issues to specific team members
* Set priorities and deadlines
* Track the status and resolution of each issue
* Facilitate communication between team members about specific issues
Popular issue trackers include Jira, GitHub Issues, Bugzilla, and Trello, among others.
## Why Use an Issue Tracker?
1. **Centralized Information**: All issues are stored in one place, making it easier to track and manage them.
2. **Improved Collaboration**: Team members can easily communicate about specific issues, share updates, and coordinate their efforts.
3. **Prioritization**: Issues can be categorized and prioritized, ensuring that critical bugs or important features are addressed first.
4. **Accountability**: By assigning issues to specific team members, it's clear who is responsible for each task.
5. **Historical Record**: Issue trackers maintain a history of all reported issues, which can be valuable for analysis and future reference.
6. **Workflow Management**: Many issue trackers support custom workflows, helping teams standardize their processes for handling different types of issues.
## Integrating Issue Trackers with QA Sphere
QA Sphere recognizes the importance of seamless issue management in the QA process. By integrating popular issue trackers directly into the QA Sphere platform, we provide several key benefits:
1. **Streamlined Workflow**: QA testers can create issues directly from within QA Sphere during test runs, eliminating the need to switch between multiple tools.
2. **Context Preservation**: When creating an issue from a test case, relevant information is automatically included, providing developers with crucial context.
3. **Traceability**: Issues created through QA Sphere are linked to specific test cases, making it easier to track the relationship between tests and reported bugs.
4. **Real-time Updates**: The status of linked issues can be updated in real-time, giving QA teams immediate visibility into bug fixes and resolutions.
5. **Comprehensive Reporting**: By connecting test results with issue data, QA Sphere can provide more insightful reports on product quality and team performance.
---
# Jira Integration
URL: /docs/jira
QA Sphere seamlessly integrates with Atlassian Jira, allowing you to create Jira issues directly while going through test cases in a test run. This integration streamlines your workflow and ensures efficient issue tracking within your Jira projects.
## Configuring Jira Issues Integration
To integrate Jira Issues into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Jira** from the list of available integrations.
5. Next provide your Jira account subdomain and the email used for registration.
6. Navigate to [https://id.atlassian.com/manage-profile/security/api-tokens](https://id.atlassian.com/manage-profile/security/api-tokens) to generate API token
7. Use new token in the form and click **Add**
8. Choose a project for new issues to be created in.
### Using a Jira Service Account
The credentials above belong to whichever Atlassian account generated the API token, which makes the integration dependent on that person. If they leave, or their token is revoked, the integration stops working for the whole project.
QA Sphere supports **Jira service accounts** for this reason. Configure the integration with a dedicated service account rather than a team member's personal account so that:
* The integration survives staff changes
* The token's permissions can be scoped to exactly the Jira projects QA Sphere should write to
* Issue creation is clearly attributable to the integration in Jira's own history
If the integration suddenly starts failing, an expired or suspended token is the usual cause. QA Sphere reports this explicitly in the integration's error message, so check **Settings → Issue Trackers** before digging further.
## Linking Your Personal Jira Account
By default, issues created from QA Sphere are reported by the account that configured the integration. Individual users can instead **link their own Jira account**, so issues they create from QA Sphere show *them* as the reporter in Jira.
This is worth doing on any team where it matters who found a bug: Jira notifications, dashboards, and reporter-based filters all then reflect the actual tester instead of a shared integration account. Linking is per user and does not change the project-level integration.
## Using Jira Issues Integration
Once configured, the Jira Integration allows you to link existing issues or create new ones directly from QA Sphere while adding test case results. To create or link a Jira issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Jira Issues** and select one of the following options:
1. **Link existing issue** - Add a link to an existing Jira issue.
2. **Create new** - Enter details by selecting the **Issue Type** and either manually entering the **Summary** and **Description** or using AI to auto-generate the information based on test case details and result comments. A new Jira issue will be created in the assigned Jira project.
All issues linked or created for the test case will be saved under the **Action History** for this test run, providing a clear trail of documentation.
* AI issue generation may fail if there is insufficient context from the test case details and result comments to accurately determine the issue observed during testing.
* AI issue generation is not available when batch-adding results for multiple test cases simultaneously.
### Finding an Existing Issue
When linking an existing issue, you can search by:
* The full Jira issue URL, pasted straight from your browser
* Part of the issue key, without typing it in full
### Required Fields on Create
If your Jira project marks fields as required on the issue-creation screen, QA Sphere respects them: the required fields appear in the **Create new** form so the issue is accepted by Jira on the first attempt instead of failing and needing a manual fix.
The following required field types are supported:
* Text field and text area
* Select (single-option dropdown)
* Labels (autocomplete array)
* Multi-checkboxes (multi-select)
Required-field support is partial. A Jira project that requires a field type outside the list above — a cascading select or a custom field from a third-party Jira app, for example — may still reject the issue. If issue creation fails for a project like that, make the field optional in Jira or supply a default value in the Jira field configuration.
## Importing Requirements from Jira
Beyond bug reporting, Jira issues can serve as **requirements** for traceability. In the **Edit Requirements** modal on a test case, use the **Import from Jira** option to pick the issues that the test case validates. Imported requirements appear in the [Traceability Report](/docs/reports/traceability-report) with their issue keys, linking coverage analysis back to the tracker where your requirements already live.
## Benefits of Jira Integration
* **Seamless Workflow**: Create issues in Jira without leaving QA Sphere.
* **Consistency**: Ensure all issues are properly documented and tracked in your Jira project.
* **Traceability**: Easily link test cases to specific Jira issues for better tracking.
* **Efficiency**: Reduce time spent switching between QA Sphere and Jira.
* **Team Collaboration**: Improve communication between QA and development teams by centralizing issue reporting.
By leveraging this integration, your team can maintain a more cohesive and efficient testing and issue management process across QA Sphere and Jira.
---
# Linear Integration
URL: /docs/linear
QA Sphere seamlessly integrates with Linear, allowing you to create Linear issues directly while going through test cases in a test run. This integration streamlines your workflow and ensures efficient issue tracking within your Linear projects.
## Configuring Linear Issues Integration
To integrate Linear Issues into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Linear** from the list of available integrations.
5. Next, authorize Linear integration with your account credentials.
6. Choose a linear team for new issues to be created in.
## Using Linear Issues Integration
Once configured, the Linear Integration allows you to link existing issues or create new ones directly from QA Sphere while adding test case results. To create or link a Linear issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Attach Linear Issues** and select one of the following options:
* **Link existing issue** - Add a link to an existing Linear issue.
* **Create new** - Enter details by either manually entering the **Title** and **Description** or using AI to auto-generate the information based on test case details and result comments. A new Linear issue will be created in the assigned Linear project.
All issues linked or created for the test case will be saved under the **Action History** for this test run, providing a clear trail of documentation.
* AI issue generation may fail if there is insufficient context from the test case details and result comments to accurately determine the issue observed during testing.
* AI issue generation is not available when batch-adding results for multiple test cases simultaneously.
## Bidirectional Linking
When you attach a Linear issue to a QA Sphere test case, a direct link back to the test case will automatically be added to the Linear issue description. This creates a seamless bidirectional connection between your test cases and issues, allowing team members to easily navigate between QA Sphere and Linear to access relevant context and information.
## Benefits of Linear Integration
* **Seamless Workflow**: Create issues in Linear without leaving QA Sphere.
* **Consistency**: Ensure all issues are properly documented and tracked in your Linear project.
* **Traceability**: Easily link test cases to specific Linear issues for better tracking.
* **Efficiency**: Reduce time spent switching between QA Sphere and Linear.
* **Team Collaboration**: Improve communication between QA and development teams by centralizing issue reporting.
By leveraging this integration, your team can maintain a more cohesive and efficient testing and issue management process across QA Sphere and Linear.
---
# MCP Server
URL: /docs/integrations/mcp
The [Model Context Protocol](https://modelcontextprotocol.io) (MCP) is an open standard for giving AI assistants access to external systems. QA Sphere serves an MCP server directly, so an assistant can read and work with your test cases, runs, and results instead of you copying data into a chat window.
Typical uses:
* "Which test cases cover the checkout flow?" answered from your real library, inside your editor
* Referencing a specific QA Sphere test case while writing the automated test for it
* Summarizing what failed in the latest run without leaving your IDE
* Drafting new test cases from a spec and creating them in QA Sphere
MCP access is included on every plan, and nothing needs to be installed locally.
## Setting It Up
Open **Settings → MCP Server** in QA Sphere. The page asks you to pick your assistant and an access level, walks through adding an API key, and then shows the exact setup instructions and configuration for that client:
* Claude Code
* Codex
* Gemini CLI
* VS Code
* Cursor
Copy the configuration it generates and paste it where your client keeps its MCP settings. Because the configuration embeds your workspace URL and API key, take it from this page rather than assembling it by hand.
The hosted server stays current with the QA Sphere API and exposes the full set of tools allowed by your role — 27 in total.
## Access Levels
Two access levels are available, chosen when you set the server up:
* **Standard** — read and write. The assistant can create and update test cases, runs, and results.
* **Read-Only** — the assistant can query and summarize, but cannot change anything in your workspace.
Start with **Read-Only**. It covers the most common uses (search, summarize, explain coverage) and removes any risk of an assistant mutating your library while you are still building trust in it. Move to Standard when you actually want the assistant to write back.
Your role also constrains what the server can reach: the tools exposed are those your account is permitted to use. See [Users and Permissions](/docs/users-permissions).
## Keeping It Safe
An MCP configuration contains a live API key. Treat it like any other credential: never commit it to a repository, and never paste it into a shared document or a chat.
A few habits worth adopting:
* **Scope the key to the least you need.** An API key inherits the role of the user who created it, and the public API is per-user rate limited at 20 requests per second. A Read-Only setup or a lower-privileged user account limits the blast radius of a confused assistant.
* **Use a dedicated key.** A key created specifically for MCP can be revoked without disrupting your CI pipelines or the CLI.
* **Review writes.** With Standard access an assistant can create and modify test cases. Read what it proposes before accepting, the same as you would with generated code.
## Retired: the Standalone `qasphere-mcp` Package
Before QA Sphere served MCP directly, a standalone server was published as the `qasphere-mcp` npm package and run locally through `npx`.
**No longer maintained**
The [`qasphere-mcp`](https://github.com/Hypersequent/qasphere-mcp) package is retired and its repository is archived. It receives no updates and will fall behind the QA Sphere API. Use **Settings → MCP Server** instead, as described above.
If you still have it configured, migrate: remove the `qasphere-mcp` entry from your client's MCP configuration, then follow the setup instructions on the **Settings → MCP Server** page. The hosted server needs no local install, so there is nothing left to uninstall beyond that configuration block. While the standalone server is running it prints a migration notice once per session.
## MCP, the CLI, and the API
Three ways to reach the same data, suited to different jobs:
| Tool | Best for |
| ----------------------------------- | ------------------------------------------------------ |
| **MCP** | Conversational, exploratory work inside an AI client |
| **[CLI](/docs/cli)** | Scripts, CI/CD pipelines, and deterministic automation |
| **[REST API](/docs/api/api_intro)** | Custom integrations and services you build yourself |
If you want an AI coding agent to drive QA Sphere through the CLI rather than over MCP, the CLI ships a skill for exactly that — see [Agent Skill](/docs/cli/agent-skill).
## Troubleshooting
| Symptom | Likely cause |
| ------------------------------- | ---------------------------------------------------------------------------------------------- |
| Client shows no QA Sphere tools | The configuration was not picked up. Most clients need a restart after the MCP config changes. |
| `401` or authentication errors | The API key is wrong, revoked, or belongs to a suspended user. Generate a fresh key. |
| Writes are rejected | The setup is Read-Only, or the API key's user lacks permission for the action. |
| Fewer tools than expected | The tools exposed are limited to what your role permits. |
| `429 Too Many Requests` | The per-user rate limit was hit. See [Rate Limiting](/docs/api/api_intro#rate-limiting). |
Still stuck? Contact us at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Slack Integration
URL: /docs/slack
QA Sphere integrates natively with Slack to keep your team informed without leaving their conversations. Once connected, QA Sphere can:
* **Post channel notifications** when test runs, test plans, milestones, and test results change
* **Respond to slash commands** (`/qasphere`) for managing subscriptions directly from Slack
* **Expand QA Sphere links** pasted in Slack into rich preview cards
Connecting or disconnecting the Slack workspace requires the [Owner or Admin role](/docs/users-permissions) in QA Sphere. One Slack workspace can be connected to one QA Sphere workspace at a time.
## Connecting Your Slack Workspace
1. Navigate to **Settings > Integrations** and click **Connect** on the **Slack Workspace** row (alternatively, click **Create** and select **Slack**).
2. A Slack authorization window opens. If you are not signed in to Slack in your browser, Slack will first ask you to sign in to your workspace.
3. Review the requested permissions, make sure the correct workspace is selected in the workspace picker, and click **Allow**.
4. The window closes automatically and QA Sphere confirms with a "Slack connected successfully." message. The Slack Workspace row now shows a **Connected** badge along with your workspace name.
## Linking Your Slack Account
Individual users link their Slack identity to their QA Sphere account. Linking is required to subscribe channels to projects and to see link previews for QA Sphere URLs.
* The user who connects the workspace is **linked automatically**.
* Everyone else can run `/qasphere link` in any channel or DM with the QA Sphere app. The bot replies with a personal link that opens QA Sphere, where you confirm the connection. The link expires after 15 minutes.
A Slack account can be linked to only one QA Sphere account.
## Subscribing a Channel to a Project
In the Slack channel that should receive notifications, run:
```
/qasphere subscribe project events all
```
Replace `` with your QA Sphere project code (for example, `BD`). The bot joins the channel automatically and confirms the subscription.
The QA Sphere bot can join public channels on its own. For **private channels**, invite it first with `/invite @QA Sphere`.
You can subscribe a channel to multiple projects, and a project to multiple channels. Subscribing requires access to the project in QA Sphere — Owners and Admins can subscribe to any project, while other roles need to be members of it.
### Slash Commands
| Command | Description |
| ----------------------------------------------------------------- | --------------------------------------------------------- |
| `/qasphere subscribe project events ` | Subscribe the channel to project notifications |
| `/qasphere unsubscribe project events ` | Unsubscribe from some or all of a project's notifications |
| `/qasphere list` | List the active subscriptions in this channel |
| `/qasphere link` | Link your Slack account to QA Sphere |
| `/qasphere` | Show help |
### Event Categories
Subscriptions are configured per event category:
| Category | Covers |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `runs` | Test runs created, updated, closed, reopened, or deleted; test plans created, closed, reopened, or deleted; milestones closed or deleted |
| `results` | Test results recorded, updated, or deleted (batch operations are summarized in a single message) |
| `all` | Both of the above |
## Notifications
Once subscribed, the QA Sphere bot posts a message to the channel whenever a matching event occurs. Each notification links back to the entity in QA Sphere and includes key details such as the project code, state, and the user who performed the action.
## Link Previews
When a linked user pastes a QA Sphere URL — a test run or a test case — into Slack, the bot expands it into a preview card with the entity's key details and an **Open in QA Sphere** link.
Previews are shown only for links to your own QA Sphere workspace, and only when the user who posted the link has access to the project.
## Managing the Integration
On **Settings > Integrations**, the connected Slack Workspace row offers:
* **Reconnect** — re-runs the Slack authorization. Useful if the connection stops working or permissions change. Disconnecting first is not required.
* **Disconnect** — stops all notifications and disables the app in your workspace. Channel subscriptions are kept, so reconnecting later restores notifications without re-subscribing each channel.
Uninstalling the QA Sphere app from within Slack also disables the integration.
All connection, account linking, and subscription changes are recorded in the QA Sphere audit log (**Settings > Audit Log**).
If you need more control over message formatting or want to notify systems other than Slack, use [Webhooks](/docs/webhooks) — they support custom payload templates, including Slack's Block Kit format.
**Need Help?**
Contact [support](mailto:sorted@qasphere.com) for assistance with the Slack integration.
---
# January '26: 26W02
URL: /docs/26W02
This release brings enhanced security controls for enterprise teams, custom webhook payloads, and expanded API capabilities for automation workflows.
## New Features
* **Custom webhook payload support**
You can configure custom webhook payloads from Integrations → Webhooks, allowing dynamic data to be sent to external systems. See the [Webhooks documentation](/docs/webhooks) for setup details.
* **Enforce two-factor authentication**
Admins on the Business plan can enforce two-factor authentication (2FA) for all users in the workspace. When enabled, users without 2FA are logged out and must complete 2FA setup on next login.
* **IP allow list for workspace access**
Admins on the Business plan can restrict workspace access to a predefined list of allowed IP addresses or CIDR ranges, adding an extra layer of security for enterprise environments.
* **Insights for parameterized test cases**
Added ability to view Insights for filled/parameterized test cases directly from the test case listing.
* **Preview modal on the Resources page**
Test cases opened from the Resources page now appear in a modal preview, reducing unnecessary navigation.
* **"All time" filter for test case insights**
An "All time" option has been added to the insights date filter, making it easier to view the complete execution history of a test case.
* **"Create template" action moved to Create dropdown**
The Create template test case action has been moved into the main Create dropdown, making the interface cleaner and test case creation more consistent.
* **Improved theme mode control**
The theme switch in the profile menu has been updated for a better experience.
* **Jira "Create Issue" required fields support (partial)**
Required fields are now respected when creating Jira issues from QA Sphere, reducing failed issue creation and manual fixes. Supported field types:
* Text field / text area
* Select (single option dropdown)
* Labels (autocomplete array)
* Multi-checkboxes (multi-select)
* **Improved Jira integration error handling**
Jira integration now provides clearer error messages for expired or suspended tokens.
* **Linear OAuth refresh token support**
Linear integration has been updated to support refresh tokens, preventing authentication issues caused by upcoming OAuth changes.
* **Improved CSV import and export**
CSV workflows are now more reliable, with improved support for identifiers, empty folders, and complex folder structures.
* **Reliable backup restore for shared preconditions**
Backup import/export now correctly recreates shared resources across projects. The export format includes titles and import reuses existing shared resources when present instead of duplicating.
* **Expanded public API for automation**
Public API has been expanded with new endpoints for bulk test case creation, project creation, and listing project requirements. This enables better automation workflows.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed Audit Log upgrade flow so users selecting a locked filter are redirected back to the Audit Log after completing billing
* Fixed extra leading and trailing whitespace being saved in shared step substeps when editing shared steps
* Fixed folder tree copy to preserve the original hierarchy
* Fixed Google sign-up to require accepting Terms of Service and Privacy Policy before continuing
* Fixed an issue where non-admin users could not access the Personal Settings page
* Fixed an issue where archived projects appeared in the Create Custom Field modal
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# February '26: 26W06
URL: /docs/26W06
This release brings major usability improvements to Test Runs and test case management, new import sources, enhanced billing and authentication controls, and a public Audit Logs API.
## New Features
* **Improved usability and visual design of Test Runs**
Added pagination with a "Load more" flow (10 items loaded by default) to avoid loading all Test Runs at once. The layout has been made more compact, Test Plan names are now visually highlighted.
* **Improved "Add test cases to test run" dialog**
Now you can resize the sidebar in the "Add test cases to test run" dialog, search for test cases, and work with a larger modal layout for better visibility.
* **Improved folder tree navigation and bulk operations**
Now you can use the new "All Folders" root item to quickly return to the full test case list. You can also select one or more folders and apply bulk property updates to all test cases within them.
* **Add test case counters for all folders**
Now you can toggle and view the number of test cases in every folder (not only the selected one). The counters can be enabled via hotkeys and are automatically hidden when leaving the page.
* **Import from Qase, Testomat, and Zebrunner**
Now you can import test cases from Qase, Testomat and Zebrunner. CSV import also supports a "folder comment" column to set folder comments during import.
* **Improved Expected Result label detection in test steps**
Now the "Expected Result" label is automatically shown for steps containing images, line breaks, or multiple paragraphs—improving readability for more complex step formatting.
* **Trial subscription updates**
Now you can modify subscription settings (e.g., user count) while on a trial plan.
* **Improved Billing UI**
You can now add your full billing address directly in the billing contact form. The phone field automatically detects and pre-fills the country code for a smoother checkout experience.
* **Google Sign-In domain restrictions**
Now you can limit Google Sign-In to approved email domains using a configurable allowlist.
* **Public Audit Logs API with dedicated SIEM access keys**
Now you can access audit logs via a public API and create API keys specifically limited to the audit logs endpoint. If an API key name starts with SIEM-LOG-ONLY, it will only work for the audit logs endpoint.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed Jira required fields not loading correctly when opening the modal
* Fixed visual indication for inactive "Auth methods" on the Security page
* Fixed typo in the "Bulk write with AI" page banner title
* Fixed Create/Edit test case UI where "Update shared step" became unavailable after undoing a shared step update, allowing subsequent updates as expected
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# March '26: 26W10
URL: /docs/26W10
## New Features
* **Main page onboarding widget**
New users now see an onboarding widget on the main page with guided videos, helpful links, and a contact form to quickly learn the product and get support.
* **New Help & Feedback page**
The Support section has been renamed to Help & Feedback and now includes a built-in form to submit bug reports, feature requests, and questions directly from the app.
* **Global AI rules**
Now you can create global AI rules and apply them across multiple projects or all projects. You can manage them in Workspace Settings.
* **Checkbox custom field for test cases**
Now you can create Checkbox-type custom fields for test cases. This field behaves similarly to a dropdown but allows simple true/false or limited option selection with checkbox-style interaction.
* **Run logs on Test Run page**
The Test Run page now shows automation logs in an info block above test cases, allowing you to expand, collapse, and view full details.
* **Automation icon for API test runs**
Test runs created via the public API are now marked with a special automation icon in the Test Runs list.
* **Updated Resources navigation**
Navigation to the Resources page has been separated from Workspace Settings. The Gear icon now opens Workspace Settings, while a new project-level icon provides direct access to Resources.
* **Members sidebar improvements**
Added a close button to the Members edit sidebar for easier navigation.
* **Sorting in Members settings**
Now you can sort users in Settings → Members by Name/Email, Role, 2FA, and Access. Sorting works with a three-state cycle (asc/desc/reset), and keeps indicators always visible.
* **Improved Test Run and Test Plan sorting**
Test Runs and Test Plans now update their activity time only when results are added. Until then, sorting is based on creation time, ensuring more accurate ordering.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed project permissions selection in the Webhook modal
* Fixed slow test case list loading for large datasets
* Fixed the "+ Attach Jira Issue" dropdown not opening in Firefox due to panel width and scroll interaction issues
* Fixed duplicate submissions in the custom field modal by disabling the Create button after submission starts
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# April '26: 26W14
URL: /docs/26W14
## New Features
* **AI Duplicate Detection for Bulk Test Generation**
AI now detects duplicate test cases during bulk generation and highlights them so you can review before adding.
* **Extended CLI with Full Public API Support**
You can now use the QA Sphere CLI to work with projects, test cases, runs, and more via the public API.
* **Requirements Badges in Test Case List**
Requirement badges now appear alongside tags in the test case list. Issue keys (e.g., `PROJ-123`) are shown as badges with full text on hover. This can be toggled in Settings > Customization.
* **Default Custom Fields: Description & Goal for Test Cases**
Added built-in Description and Goal fields for test cases, available to enable when needed.
* **Linked Bugs in Test Case Insights**
Test case insights now include linked bugs for better visibility and context.
* **Linear Integration for Requirements & Traceability**
Easily connect Linear requirements to test cases and track coverage with built-in traceability reports.
* **Improved Visibility for Jira Import**
The "Import from Jira" option is now always visible in the Edit Requirements modal for better usability.
* **Attach Files in Help & Feedback**
You can now include file attachments when submitting Help & Feedback requests.
* **Suspend and Restore User Access**
Admins can now suspend and unsuspend users, preventing access without deleting.
* **Navigation Confirmation in Bulk AI Generation**
A confirmation dialog now appears when navigating away from the bulk AI generation page, helping prevent accidental loss of in-progress work.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed CSV import validation so default true is ignored for non-default custom fields
* Fixed test case creation failures with checkbox fields
* Fixed tag label dark mode styling in the search modal
* Fixed "navigation aborted" on undo after deleting a selected test case
* Fixed sidebar resize range by widening it to 100–700px for more flexible layout control
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# May '26: 26W17
URL: /docs/26W17
## New Features
* **AI Duplicate Detection & Merge for Test Cases**
AI can now identify duplicate test cases within a project, helping teams review similar cases and merge them into a single test case to keep test suites cleaner.
Temporarily limited to projects with 500 or fewer test cases.
* **Convert Published Test Cases Back to Draft**
Added support for reverting published test cases back to draft status, including both single and bulk actions, with validation to prevent reverting test cases that are already linked to runs.
* **Slack Workspace Integration**
Connect QA Sphere directly with Slack to receive run notifications, subscribe projects to channels, use /qasphere slash commands, and preview QA Sphere links directly inside Slack conversations.
* **OAuth Device Login for CLI & Non-Browser Clients**
Added OAuth 2.0 Device Authorization support for CLI tools and other non-browser clients, enabling secure login flows without manually creating API tokens.
* **API Key Validation Endpoint for CLI Authentication**
Added a public `/auth/me` endpoint for API key validation, allowing CLI tools and integrations to verify authentication status and retrieve the current user's account information securely.
## Fixes
This release also includes targeted improvements across the app.
* Fixed an issue where expired Linear refresh tokens could cause unclear integration errors and force users to reconnect the integration.
* Fixed multiple issues affecting subscription management and billing updates.
* Fixed inconsistencies in how linked bugs are displayed between the Overview and Insights tabs.
* Fixed an issue where the Update button could remain disabled when editing Shared Step content without changing the step name.
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# June '26: 26W22
URL: /docs/26W22
## New Features
* **Improved Effort by Team Member Report**
The Effort by Team Member report now includes pie charts, making it easier to understand workload distribution and time spent across team members.
* **Improved Report Sorting**
You can now sort data in more reports, helping you quickly find and compare the information that matters most.
* **Improved Test Run Progress Visibility**
Status counts are now displayed directly in Test Run progress bars for quicker visibility.
* **Save Published Test Cases as Drafts While Editing**
You can now convert published test cases back to Draft directly from the editor.
* **Improved Duplicate Detection for Copied Test Cases**
Improved AI duplicate detection to recognize copied test cases and folders more accurately.
* **Improved AI Usage Tracking**
AI usage limits are now shown as percentages, with clearer visibility into remaining usage and reset timing.
* **Added New Slack Run Notification Triggers**
Added new Slack notification events for test runs, test plans, and milestones to improve visibility into testing progress and status changes.
* **Added Jira Service Account Support**
QA Sphere now supports Jira service accounts, providing more flexibility when configuring Jira integrations.
* **Improved Audit Logs for Integrations and Webhooks**
Added more detailed audit log entries for integrations and webhooks.
* **Subscription Reactivation**
You can now restore a canceled subscription directly from the Billing page without having to select a plan again.
* **Extended SAML 2.0 SSO Support**
Added user-facing configuration for SAML 2.0 SSO, enabling Enterprise customers to manually configure SAML SSO for easier, more visible management.
* **SCIM 2.0 Support**
Added SCIM 2.0 support for automated user provisioning, user updates, and account lifecycle management.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed incorrect Git project counts displayed on the Integrations page.
* Fixed loader alignment on the Bulk Write with AI page.
* Fixed an issue where subscription changes were not displayed immediately after an update.
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# July '26: 26W28
URL: /docs/26W28
## New Features
* **AI Test Case Assistant**
Added an AI assistant to the Test Cases page that can search, filter, summarize, and answer questions about test cases through a conversational interface.
* **Multiplayer Test Runs**
Introduced multiplayer test runs with real-time result synchronization, participant presence, and live updates, enabling multiple testers to work in the same test run simultaneously.
* **Detailed Results Report**
Added a new Detailed Results report that provides a comprehensive view of test run results, including tester comments, attachments, and linked issues.
* **Overview Reports**
Added a new Overview section to the Reports page with built-in charts for key testing metrics, a date range filter, and expandable/collapsible charts.
* **Template Filtering**
Added a filter for test case templates, allowing you to quickly include or exclude templates from test case lists.
* **Custom Integration**
Added support for project-specific parameters in custom integration templates, enabling different projects to use different URLs or project keys within the same integration.
* **Jira Personal Account Linking**
Added support for linking personal Jira accounts, allowing issues created from QA Sphere to use the linked user as the reporter.
* **Improved Jira Issue Search**
You can now find Jira issues using a full issue URL or just part of the issue key.
* **Improved Test Case Search**
Search is now consistent across the Test Cases and Test Run pages, with support for filters and folder name search.
* **Improved Notification Retention**
Read notifications are now automatically removed after 60 days.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed duplicate review stability in large projects.
* Fixed PDF export for test runs and reports.
* Fixed timer icon visibility in Dark Theme.
* Fixed missing linked issues in Traceability Report.
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# August '26: 26W32
URL: /docs/26W32
## New Features
* **Data Field for Test Case Steps**
You can now add step-specific test data, such as credentials, payloads, sample values, links, and file attachments, directly to test case steps. The Data field can be enabled or disabled in Settings.
* **Visual Folder Highlight in Test Runs**
Target folders are now easier to spot after navigating in Test Runs. The selected folder is automatically highlighted after navigation from the Drawer or Search modal.
* **Added MCP Setup Page**
Added an MCP setup page in Settings with API key instructions. You can now connect to QA Sphere through the native MCP server using API key authentication, with 27 tools, Standard and Read-Only access levels, and ready-to-use configurations for Claude Code, Codex, Gemini CLI, VS Code, and Cursor.
* **Improved Profile Avatar Interaction**
The profile avatar now has a clear visual highlight when hovered or when the account dropdown is open.
* **Authentication Failure Audit Logs**
You can now see rejected authentication attempts in audit logs and filter them for easier investigation.
* **Public API Support for Test Case Edit History**
You can now access test case edit history through the Public API, including editor details, changes, timestamps, legacy or sequence ID lookup, and pagination.
* **SAML Documentation**
SAML setup and usage information is now available in the documentation.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed backend validation for shared precondition titles, including the 255-character limit and validation during imports and other workflows.
* Fixed password reset tokens to expire after 1 hour instead of remaining valid for an extended period.
* Fixed radio styling to match checkboxes in light and dark modes, including background and border appearance.
* Fixed inconsistent image and video sizing in the Test Case History modal.
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# Overview
URL: /docs/release-notes
Stay up to date with the latest changes, improvements, and fixes in QA Sphere. Release notes are organized by year, with the most recent updates listed first.
## 2026
* [August '26: 26W32](/docs/26W32)
* [July '26: 26W28](/docs/26W28)
* [June '26: 26W22](/docs/26W22)
* [May '26: 26W17](/docs/26W17)
* [April '26: 26W14](/docs/26W14)
* [March '26: 26W10](/docs/26W10)
* [February '26: 26W06](/docs/26W06)
* [January '26: 26W02](/docs/26W02)
## Previous Years
* [2025 Release Notes](/docs/release-notes/2025)
* [2024 Release Notes](/docs/release-notes/2024)
---
# Automation Coverage
URL: /docs/reports/automation-coverage-report
The Automation Coverage report tracks the automation status of test cases to measure automation progress, identify manual testing gaps, and prioritize automation efforts. This report is essential for planning automation roadmaps, justifying automation investments, and tracking automation initiatives.
## What This Report Shows

The Automation Coverage report displays:
1. **Overall Automation Coverage**: Pie chart showing the percentage of test cases by automation status
2. **Automation Status Breakdown**: Count and percentage of Automated, In Progress, Planned, and unassigned test cases
3. **Coverage by Section**: Automation coverage for different sections/folders of your test suite
4. **Not Automated Metrics**: Count and percentage of tests not yet automated per section
## When to Use This Report
Use the Automation Coverage report when you need to:
* **Track automation progress** against goals and targets
* **Plan automation roadmap** by identifying high-value manual tests
* **Justify automation investments** with data on current manual testing effort
* **Identify automation gaps** in critical features or workflows
* **Measure ROI** of automation initiatives over time
* **Communicate automation status** to stakeholders
* **Prioritize automation work** based on test frequency, duration, and criticality
## Prerequisites
This report requires the **Automation** custom field to be enabled in your project. To enable it:

1. Navigate to **Settings** → **Custom Fields**
2. Locate the **Automation** field
3. Ensure it is enabled for your project
Once enabled, you can assign one of the following automation statuses to each test case:
* **Automated** — Test case is fully automated
* **In Progress** — Automation is currently being developed
* **Planned** — Test case is scheduled for automation
* **Cannot be Automated** — Test case is not suitable for automation
* **Broken** — Automated test is currently broken and needs fixing
The report will display coverage based on these values.
Test cases without an automation status assigned will appear as "(No Value)" in the report.
## Understanding the Report
### Automation Coverage Summary
At the top of the report, you'll see a pie chart with overall automation metrics showing the distribution of test cases by automation status.
### Automation Status Categories
**Automated**:
* Test cases that are fully automated
* Execute without manual intervention
* Included in CI/CD pipelines
**In Progress**:
* Test cases where automation is currently being developed
* Transitional state between manual and automated
**Planned**:
* Test cases identified for future automation
* Scheduled for automation but not yet started
**Cannot be Automated**:
* Test cases that are not suitable for automation
* Examples: exploratory testing, usability testing, manual verification
**Broken**:
* Automated tests that are currently failing due to test issues
* Require maintenance or fixing before they can be used reliably
**(No Value)**:
* Test cases without an automation status assigned
* May require review to determine automation feasibility
### Coverage by Section
The table provides a detailed breakdown showing automation status by section hierarchy:
| Column | Description |
| --------------------- | ------------------------------------------------------ |
| **Section Hierarchy** | The folder path in your test case structure |
| **Not Automated** | Count of test cases not yet automated |
| **Not Automated %** | Percentage of test cases not automated in this section |
| **(No Value)** | Test cases without automation status assigned |
| **In Progress** | Test cases with automation in development |
| **Planned** | Test cases scheduled for automation |
| **Automated** | Test cases that are fully automated |
**Example report**:
| Section Hierarchy | Not Automated | Not Automated % | (No Value) | In Progress | Planned | Automated |
| -------------------------------------------------- | ------------- | --------------- | ---------- | ----------- | ------- | --------- |
| Bistro Delivery > About us | 3 | 100% | 3 | 0 | 0 | 0 |
| Bistro Delivery > Authentication Security | 0 | 0% | 0 | 0 | 0 | 10 |
| Bistro Delivery > Authentication Security Measures | 10 | 100% | 5 | 0 | 0 | 0 |
| Bistro Delivery > Automated | 2 | 33.33% | 2 | 0 | 0 | 4 |
| Bistro Delivery > Cart | 12 | 100% | 12 | 0 | 0 | 0 |
**Insights from Example**:
* Authentication Security section has 100% automation (10 automated tests)
* Automated section has 33.33% not automated (4 automated, 2 without status)
* About us, Authentication Security Measures, and Cart sections need automation attention (100% not automated)
## Generating the Report

1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Select **Automation Coverage**
4. Click **Next**
5. Choose the folders to include in the report
6. Click **Build report**
## Export Options
**Export XLSX**:
* Raw data export for further analysis
* Open in Excel, Google Sheets, or BI tools
* Click ... and then **Export XLSX** button
**Export PDF**:
* Full report with charts and tables
* Professional formatting for stakeholder distribution
* Click ... and then **Export PDF** button
**Print**:
* Direct print for physical documentation
* Formatted for standard paper sizes
* Click ... and then **Print** button
## Interpreting Results
### Strong Automation Coverage
```
Total: 500 test cases
Automated: 425 (85%)
Manual: 50 (10%)
Pending: 25 (5%)
By Area:
Core Features: 95% automated
Integration Tests: 80% automated
UI Tests: 75% automated
API Tests: 90% automated
```
**Interpretation**: Excellent automation coverage with most areas well-automated. The 10% manual testing is likely exploratory or edge cases.
**Action**: Maintain current automation, focus on completing pending 5%.
### Moderate Automation Coverage
```
Total: 500 test cases
Automated: 300 (60%)
Manual: 175 (35%)
Pending: 25 (5%)
By Area:
Core Features: 80% automated
Integration Tests: 50% automated
UI Tests: 40% automated
API Tests: 85% automated
```
**Interpretation**: Moderate coverage with significant manual testing remaining. UI tests are underautomated.
**Action**: Prioritize UI test automation, particularly for high-frequency tests.
### Poor Automation Coverage
```
Total: 500 test cases
Automated: 150 (30%)
Manual: 325 (65%)
Pending: 25 (5%)
By Area:
Core Features: 45% automated
Integration Tests: 25% automated
UI Tests: 15% automated
API Tests: 60% automated
```
**Interpretation**: Low automation coverage requires significant investment. Most testing is manual, consuming substantial resources.
**Action**: Urgent automation initiative needed. Start with high-ROI tests (frequent, time-consuming, stable).
## Best Practices
### 1. Set Realistic Automation Targets
**Industry Benchmarks**:
* **Good**: 70-80% automation coverage
* **Excellent**: 80-90% automation coverage
* **Exceptional**: 90%+ automation coverage
**Not All Tests Should Be Automated**:
* Exploratory testing: Manual
* Usability testing: Manual
* One-time tests: Manual (low ROI)
* Rapidly changing features: Manual (until stabilized)
**Example Target**:
```
Realistic Goal: 75% automation coverage
- 75% fully automated (high-frequency, stable tests)
- 15% manual (exploratory, usability, edge cases)
- 10% pending/not applicable
```
### 2. Prioritize by ROI
**High ROI Automation**:
```
✓ Regression tests (run frequently)
✓ Time-consuming manual tests
✓ Stable, well-defined tests
✓ Critical business workflows
✓ Cross-browser/device tests
```
**Low ROI Automation**:
```
✗ One-time or rarely run tests
✗ Tests that change frequently
✗ Tests requiring complex setup
✗ Exploratory or creative testing
```
**ROI Calculation Formula**:
```
ROI Score = (Test Frequency × Manual Execution Time × Stability) / Automation Effort
Example:
Test A: (52 runs/year × 15 min × 0.9 stability) / 2 hours effort = 351 points
Test B: (4 runs/year × 5 min × 0.6 stability) / 4 hours effort = 3 points
Priority: Automate Test A first
```
### 3. Track Automation Velocity
**Measure Progress**:
* Tests automated per sprint
* Automation coverage increase per quarter
* Time from test creation to automation
**Example Metrics**:
```
Sprint Velocity:
Sprint 20: +8 automated tests
Sprint 21: +12 automated tests
Sprint 22: +10 automated tests
Average: 10 tests/sprint
Quarterly Progress:
Q1: 60% → 65% (+5%)
Q2: 65% → 72% (+7%)
Q3: 72% → 80% (+8%)
Trend: Accelerating ✅
```
### 4. Prevent Manual Test Backlog Growth
**Challenge**: New manual tests added faster than automation
**Solution**:
```
Policy: Automate-First Approach
- New features must include automated tests
- Manual tests only for exploratory/usability
- Automate within same sprint as test creation
- Track "automation debt" like technical debt
Metric to Track:
Manual Test Growth Rate vs Automation Rate
Good: Automation Rate > Manual Growth Rate
Bad: Manual tests accumulating faster than automation
```
### 5. Celebrate Automation Milestones
**Team Recognition**:
* 70% coverage milestone: Team lunch
* 80% coverage milestone: Team outing
* Individual contributors: Recognition in team meetings
**Business Communication**:
* Quarterly automation reports to leadership
* Highlight time/cost savings
* Show impact on release velocity
**Example Communication**:
```
Q2 Automation Success:
✅ Increased coverage from 65% to 72%
✅ Automated 42 high-priority tests
✅ Reduced regression testing time by 30%
✅ Saved estimated 300 manual testing hours
✅ Improved release confidence
Team Recognition: Thank you to Alice, Bob, and Carol!
```
### 6. Maintain Automated Tests
**Automation Isn't "Set and Forget"**:
* Automated tests require maintenance
* Budget 15-20% of time for test updates
* Monitor automated test reliability
* Refactor brittle or flaky tests
**Maintenance Metrics**:
```
Healthy Automation:
- <5% tests failing due to test issues (not real bugs)
- <10% tests requiring updates per sprint
- >95% test reliability
Warning Signs:
- >15% tests frequently failing
- >25% tests requiring constant updates
- Flaky tests quarantined from CI/CD
```
## Related Reports
* **Test Case Duration**: Identify time-consuming manual tests worth automating
* **Test Case Success Rate**: Find stable tests good for automation
* **View Results**: See impact of automation on testing efficiency
## Getting Help
For assistance with this report:
1. Verify test cases have automation status set
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Review automation status categories and definitions
4. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Quick Summary**: The Automation Coverage report tracks your automation progress. Set realistic targets (70-80% coverage), prioritize high-ROI tests, track velocity, and maintain your automated tests. Use for roadmap planning, justifying investments, and celebrating milestones. Remember: not all tests should be automated.
---
# Detailed Results
URL: /docs/reports/detailed-results-report
The Detailed Results report gives you the complete record of what happened in a test run. Where [View Results](https://qasphere.com/docs/reports/view-results-report) answers "what is the current status?", Detailed Results answers "what exactly did the tester see, and what did they attach?" — every comment, every screenshot, and every linked issue, in one document.
## What This Report Shows
For each test case in the selected run, the report includes:
1. **Result status** — one of the five default statuses (Passed, Failed, Blocked, Open, Skipped) or any of the up to four custom statuses configured for your workspace
2. **Tester comments** — the notes the tester wrote when recording the result
3. **Attachments** — screenshots, videos, logs, and other files attached to the result
4. **Linked issues** — bugs created or linked from the result, shown as clickable tags into your issue tracker
5. **Who and when** — the tester who recorded the result and the time it was recorded
## When to Use This Report
Use Detailed Results when the status alone is not enough:
* **Defect triage** — hand developers the failure evidence without asking them to click through the app
* **Handover between shifts or teams** — one document that carries the full context of a run
* **Audit and compliance evidence** — a durable record of what was executed, by whom, and what was observed
* **Retrospectives** — review how failures were described and whether the reporting was actionable
* **Customer or stakeholder reporting** — share the substance of a test cycle, not just a pass rate
The report shows whichever status was actually recorded, so a workspace using custom statuses will see those here under their configured labels. Custom statuses are configured per workspace and appear in the API as `custom1` through `custom4` — see [Settings](/docs/api/settings).
Detailed Results is scoped to a test run, so it is at its most useful right after a run closes, while the evidence still matters. For trends across many runs, use [Test Case Success Rate](https://qasphere.com/docs/reports/test-case-success-rate-report) or [Run Scorecard](https://qasphere.com/docs/reports/run-scorecard-report) instead.
## Generating the Report
1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Click **Build report**
4. Select **Detailed Results** and click **Next**
5. Choose the test run to report on
6. Click **Build report**
## Export Options
Like the other reports, Detailed Results can be exported from the **...** menu:
* **Export PDF** — the full report with comments and inline attachments, suited to release documentation and audit trails
* **Export XLSX** — the underlying rows for analysis in Excel, Google Sheets, or a BI tool
* **Print** — direct print, formatted for standard paper sizes
Attachments are embedded as images in the PDF export where the file type allows it. Large videos and archives are referenced rather than embedded, so keep the run available in QA Sphere if the attachments themselves need to be retrievable later.
## Getting the Most Out of It
**Write comments the report can carry.** The value of this report is bounded by the quality of the comments testers leave. A comment like "broken" produces a useless row; "Checkout fails with 500 after applying a expired promo code, see attached HAR" produces an actionable one.
**Attach evidence at the moment of failure.** Attachments are captured per result, so a screenshot taken while the failure is on screen ends up in the right row automatically. Automated runs can push attachments too — see [Result Upload](/docs/integrations/result-upload) and use the `--attachments` flag.
**Link the issue from the result, not afterwards.** Issues created from the result view are linked to that specific result, which is what makes them appear here. Issues filed separately in Jira or GitHub will not show up in this report even if they describe the same bug.
## Related Reports
* [View Results](https://qasphere.com/docs/reports/view-results-report) — the latest result per test case across one or more runs
* [Run Scorecard](https://qasphere.com/docs/reports/run-scorecard-report) — compare several runs side by side
* [Traceability](https://qasphere.com/docs/reports/traceability-report) — map results back to requirements
## Getting Help
For assistance with this report:
1. Review the report parameters to ensure correct configuration
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
---
# Effort by Team Member
URL: /docs/reports/effort-by-team-member-report
The Effort by Team Member report analyzes the effort spent by individual team members on testing activities, providing insights into workload distribution, productivity, and resource utilization. This report helps identify bottlenecks, balance workloads, and plan resource allocation effectively.
## What This Report Shows

The Effort by Team Member report displays:
1. **Total Effort per Team Member**: Aggregate effort spent by each team member
2. **Test Cases Executed**: Number of test cases executed by each team member
3. **Time Tracked**: Total time spent on testing activities by each team member
4. **Issues Created**: Number of bugs or issues reported by each team member
## When to Use This Report
Use the Effort by Team Member report when you need to:
* **Balance workloads** across the testing team
* **Identify resource bottlenecks** where team members are overloaded
* **Plan sprint capacity** based on historical team member effort
* **Track productivity** and contribution of individual team members
* **Justify resource needs** with data on current team capacity and workload
* **Conduct performance reviews** with objective effort metrics
* **Optimize team structure** by understanding work distribution patterns
## Understanding the Report
### Team Member Effort Summary
The report displays a table or visualization showing effort metrics for each team member:
| Team Member | Test Cases Executed | Time Spent | Issues Created |
| ----------- | ------------------- | ---------- | -------------- |
| Alice Smith | 45 | 32h 15m | 12 |
| Bob Johnson | 38 | 28h 45m | 8 |
| Carol Davis | 52 | 36h 30m | 15 |
| David Lee | 25 | 17h 20m | 5 |
**Interpretation Example**:
* Carol Davis has the highest workload (32% of total effort, 52 test cases)
* David Lee has the lowest workload (15% of total effort, 25 test cases)
* Workload distribution shows some imbalance that may need attention
### Effort Metrics Explained
**Test Cases Executed**:
* Total number of test cases run by the team member
* Includes both manual and automated test execution
* Higher numbers indicate more test execution volume
**Time Spent**:
* Total time tracked for testing activities
* Includes test execution, bug investigation, and retesting logged by the team
* Measured in hours and minutes
**Issues Created**:
* Number of bugs, defects, or issues logged by the team member
* Indicates testing effectiveness (finding bugs)
* Should be considered alongside test cases executed
## Generating the Report

1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Select **Effort by Team Member**
4. Click **Next**
5. Choose the way to select test cases for the report: by **Milestone**, **Test Run** or time **Period**
6. Click **Build report**
## Export Options
**Export XLSX**:
* Raw data export for further analysis
* Open in Excel, Google Sheets, or BI tools
* Click ... and then **Export XLSX** button
**Export PDF**:
* Full report with charts and tables
* Professional formatting for stakeholder distribution
* Click ... and then **Export PDF** button
**Print**:
* Direct print for physical documentation
* Formatted for standard paper sizes
* Click ... and then **Print** button
## Best Practices
### 1. Track Effort Consistently
**Establish Standards**:
* All team members track time in same way
* Use same categories for activities
* Track daily, not retrospectively
* Include all testing-related activities
**What to Track**:
* Test execution time
* Test creation time
* Bug investigation time
* Retesting time
* Test maintenance time
* Environment setup time
* Meetings and planning time (if applicable)
### 2. Set Realistic Capacity Targets
**Consider Individual Factors**:
* Experience level (junior vs senior)
* Specialization areas
* Part-time vs full-time
* Non-testing responsibilities
* Training and development time
**Example Targets**:
```
Senior QA (5+ years): 35-40h testing/week
Mid-level QA (2-5 years): 30-35h testing/week
Junior QA (<2 years): 25-30h testing/week
Note: Accounts for meetings, training, planning
```
### 3. Regular Workload Reviews
**Review Cadence**:
* **Weekly**: Quick check for severe imbalances
* **Sprint**: Comprehensive effort review
* **Monthly**: Long-term workload trends
* **Quarterly**: Capacity planning
**Review Checklist**:
* [ ] Workload distribution within 20% variance
* [ ] No team member consistently overloaded
* [ ] Junior team members getting appropriate work
* [ ] Specialized skills utilized effectively
* [ ] Team capacity aligned with project needs
### 4. Balance Efficiency with Quality
**Don't Over-Optimize**:
* High test case count ≠ High quality
* Finding fewer bugs may indicate good software, not poor testing
* Some tests legitimately take longer
* Training and mentoring reduces immediate output but builds capacity
**Quality Indicators to Track**:
* Bug escape rate (bugs found in production)
* Bug severity distribution
* Test coverage metrics
* Customer satisfaction
### 5. Use for Development, Not Punishment
**Healthy Use**:
* Identify training needs
* Balance workloads
* Recognize contributions
* Plan capacity
* Remove blockers
**Unhealthy Use**:
* Ranking team members
* Punitive measures for low numbers
* Ignoring context (complexity, blockers)
* Creating competition vs collaboration
### 6. Consider Context Always
**Factors Affecting Effort**:
* Test complexity (API vs UI vs manual)
* Learning curve (new features, new tools)
* Environment issues and blockers
* Unplanned work and interruptions
* Cross-functional collaboration time
**Example Context**:
```
Bob: 20 test cases in 40 hours
Reason: Working on complex security testing requiring deep investigation
Action: Recognize expertise, not penalize low count
Alice: 80 test cases in 40 hours
Reason: Automated smoke tests, quick execution
Action: Recognize efficiency, but ensure depth of testing
```
## Troubleshooting
### Issue: Effort Data Missing or Incomplete
**Symptoms**: Some team members show no effort data
**Possible Causes**:
1. Time tracking not enabled
2. Team members not logging time
3. Date range excludes their work
4. Permissions issue
**Solutions**:
1. Ensure time tracking is enabled in project settings
2. Train team on time tracking process
3. Verify date range includes their activity period
4. Check user permissions allow time tracking
### Issue: Effort Numbers Seem Inaccurate
**Symptoms**: Reported effort doesn't match expected workload
**Possible Causes**:
1. Inconsistent time tracking practices
2. Activities not categorized correctly
3. Includes/excludes non-testing time incorrectly
**Solutions**:
1. Standardize time tracking across team
2. Review activity categorization guidelines
3. Clarify what should/shouldn't be tracked
4. Audit sample of time entries for accuracy
### Issue: Can't Compare Team Members Fairly
**Symptoms**: Metrics vary too much due to different work types
**Possible Causes**:
1. Team members work on different test types
2. Different specializations and complexity
3. Part-time vs full-time team members
**Solutions**:
1. Normalize by FTE (full-time equivalent)
2. Group by work type for fair comparison
3. Consider complexity weighting
4. Compare trends over time, not absolute numbers
## Related Reports
* **View Results**: See what effort produced in terms of test results
* **Test Case Duration**: Understand time requirements of specific tests
* **Test Runs Scorecard**: Compare test run outcomes by team member
## Getting Help
For assistance with this report:
1. Verify time tracking is configured and enabled
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Review team time tracking practices
4. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Quick Summary**: The Effort by Team Member report helps you understand workload distribution and team productivity. Use it for sprint planning, workload balancing, and identifying resource needs. Track effort consistently, set realistic targets, and always consider context when interpreting metrics. Use for development and planning, not for punitive measures.
---
# Reports Overview
URL: /docs/reports-overview
QA Sphere provides powerful reporting capabilities that transform your test data into actionable insights. Reports help you track quality trends, identify bottlenecks, analyze test effectiveness, and make data-driven decisions about your testing strategy.
## Available Reports

The Reports page has two parts: an **Overview** section with ready-made charts you can read at a glance, and eight **built reports** you configure and generate on demand.
### Overview Charts
The Overview section at the top of the Reports page shows built-in charts for key testing metrics across the project, with a date range filter. Charts expand and collapse individually, so you can focus on the metric you care about. Nothing to configure — open the Reports tab and the Overview is already populated.
Use the Overview for a quick pulse check, and build one of the reports below when you need a specific slice of data, a shareable artifact, or a PDF export.
### Test Run Reports
Reports that analyze test run executions and results:
**1. View Results** - Comprehensive overview of test case execution results
**2. Detailed Results** - Full result detail for a test run, including tester comments, attachments, and linked issues
**3. Run Scorecard** - Compare multiple test runs across configurations
**4. Traceability Report** - Map test cases to requirements for coverage analysis
**5. Effort by Team Member** - Track individual team member testing effort and productivity
**6. Test Case Duration** - Analyze execution times to optimize test suites
**7. Test Case Success Rate** - Identify unreliable tests across multiple executions
### Test Case Reports
Reports that analyze individual test case performance:
**8. Automation Coverage** - Track automation status and helps identify manual testing gaps
## How to Create a Report
Follow these steps to generate any report in QA Sphere:
1. **Navigate to Reports** - Switch to the **Reports** tab in your project

2. **Start Building** - Click the **Build report** button

3. **Select Report Type** - Choose the report you want to generate and click **Next**
4. **Configure Report** - Fill in the required information on the configuration form (options vary by report type)
5. **Generate** - Click **Build report** to create your report
## Quick Reference Guide
| Report | Best For | Key Question Answered |
| ---------------------- | --------------------------------------- | ---------------------------------------- |
| View Results | Daily standups, sprint reviews | "What's our current test status?" |
| Detailed Results | Handover, defect triage, audit evidence | "What exactly happened in this run?" |
| Run Scorecard | Cross-browser/environment comparison | "How do Chrome vs Safari tests compare?" |
| Traceability Report | Release readiness, compliance | "Are all requirements covered by tests?" |
| Effort by Team Member | Resource planning, workload balancing | "How is testing effort distributed?" |
| Test Case Duration | CI/CD optimization | "Which tests are slowing us down?" |
| Test Case Success Rate | Test maintenance prioritization | "Which tests are unreliable?" |
| Automation Coverage | Automation strategy | "What's our automation progress?" |
For detailed information about each report, see the individual report documentation pages listed above.
***
**Next Steps**: Explore individual report types to understand their specific capabilities. Start with View Results for a quick snapshot of your testing status.
---
# Test Runs Scorecard
URL: /docs/reports/run-scorecard-report
The Test Runs Scorecard report provides a comparative analysis of multiple test runs, enabling you to understand testing efficiency, identify configuration-specific issues, and track quality trends across different environments, browsers, or time periods.
## What This Report Shows
The Test Runs Scorecard displays:
1. **Aggregate Status Metrics**: Overall status distribution across all selected test runs
2. **Test Run Comparison Table**: Side-by-side comparison of test run performance
3. **Configuration Analysis**: Performance breakdown by browser, environment, or configuration
4. **Trend Identification**: Patterns across multiple test executions
5. **Statistical Summary**: Total, passed, failed, and skipped counts per test run
## When to Use This Report
Use the Test Runs Scorecard when you need to:
* **Compare test performance** across different configurations (browsers, environments)
* **Identify configuration-specific issues** (Safari failures vs Chrome successes)
* **Track quality trends** over multiple test runs or sprints
* **Analyze testing efficiency** across different test suites
* **Verify environment parity** (staging vs production)
* **Evaluate sprint improvements** by comparing sprint-over-sprint performance
## Understanding the Report
### Aggregate Status Visualization
At the top of the report, you'll see an overall status breakdown across all selected test runs:

**Status Summary Shows**:
* **Passed** (Green): Overall percentage and count of successful tests
* **Failed** (Red): Overall percentage and count of failed tests
* **Open** (Blue): Overall percentage and count of unexecuted tests
* **Blocked** (Orange): Overall percentage and count of blocked tests
* **Skipped** (Gray): Overall percentage and count of skipped tests
**How to Read the Aggregate**:
* These are combined metrics from all selected test runs
* If a test case passed in one run and failed in another, both results are counted
* Use this for high-level understanding before drilling into specifics
### Test Run Comparison Table
Below the visualization, you'll find a detailed comparison table:
| Column | Description |
| ----------- | ---------------------------------------- |
| **Name** | Test run name with configuration info |
| **Total** | Total number of test cases in this run |
| **Open** | Percentage and count of unexecuted tests |
| **Passed** | Percentage and count of successful tests |
| **Failed** | Percentage and count of failed tests |
| **Skipped** | Percentage and count of skipped tests |
| **Blocked** | Percentage and count of blocked tests |
**Example Table**:
```
Name Total Open Passed Failed Skipped Blocked
UI Testing (Safari) 24 0% (0) 75% (18) 12.5% (3) 4.1% (1) 8.3% (2)
Functional Testing (Chrome) 26 23% (6) 46.1% (12) 15.3% (4) 3.8% (1) 11.5% (3)
```
**Key Insights from Example**:
* Safari run has better execution coverage (0% Open vs Chrome's 23% Open)
* Chrome has lower pass rate (46.1% vs Safari's 75%)
* Both configurations have blocked tests that need attention
## Generating the Report

1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Select **Run Scorecard**
4. Click **Next**
5. Choose the way to select test cases for the report: by **Milestone**, **Test Run** or time **Period**
6. Click **Build report**
## Export Options
**Export XLSX**:
* Raw data export for further analysis
* Open in Excel, Google Sheets, or BI tools
* Click ... and then **Export XLSX** button
**Export PDF**:
* Full report with charts and tables
* Professional formatting for stakeholder distribution
* Click ... and then **Export PDF** button
**Print**:
* Direct print for physical documentation
* Formatted for standard paper sizes
* Click ... and then **Print** button
## Interpreting Results
### Cross-Browser Performance
**Healthy Pattern**:
```
Chrome: Total 50, Passed 90%, Failed 8%, Open 2%
Firefox: Total 50, Passed 88%, Failed 10%, Open 2%
Safari: Total 50, Passed 85%, Failed 12%, Open 3%
```
**Interpretation**: Consistent performance across browsers with minor variations expected.
**Problem Pattern**:
```
Chrome: Total 50, Passed 90%, Failed 8%, Open 2%
Firefox: Total 50, Passed 88%, Failed 10%, Open 2%
Safari: Total 50, Passed 60%, Failed 35%, Open 5% ← Major issue!
```
**Interpretation**: Safari-specific failures require immediate investigation. Tests that pass on Chrome/Firefox are failing on Safari.
**Action Items**:
1. Review Safari-specific test failures
2. Check for browser compatibility issues
3. Update WebDriver or test framework
4. Consider CSS/JavaScript compatibility
### Environment Parity
**Healthy Pattern**:
```
Staging: Total 100, Passed 95%, Failed 5%
Production: Total 100, Passed 93%, Failed 7%
```
**Interpretation**: Minor difference is acceptable - production may have additional edge cases.
**Problem Pattern**:
```
Staging: Total 100, Passed 95%, Failed 5%
Production: Total 100, Passed 70%, Failed 30% ← Critical issue!
```
**Interpretation**: Production environment has significant issues not present in staging.
**Action Items**:
1. Verify environment configurations match
2. Check for production-specific data issues
3. Review deployment process
4. Investigate infrastructure differences
### Sprint-over-Sprint Trends
**Improving Trend** (Good):
```
Sprint 23: Total 80, Passed 75%, Failed 20%, Blocked 5%
Sprint 24: Total 85, Passed 82%, Failed 13%, Blocked 5%
Sprint 25: Total 90, Passed 88%, Failed 9%, Blocked 3%
```
**Interpretation**: Quality is improving - higher pass rates, fewer failures, fewer blocked tests.
**Declining Trend** (Bad):
```
Sprint 23: Total 80, Passed 88%, Failed 10%, Blocked 2%
Sprint 24: Total 80, Passed 82%, Failed 15%, Blocked 3%
Sprint 25: Total 80, Passed 75%, Failed 20%, Blocked 5% ← Declining!
```
**Interpretation**: Quality is degrading - increasing failures and blocked tests indicate accumulating technical debt or insufficient test maintenance.
**Action Items**:
1. Review test case reliability
2. Prioritize bug fixes
3. Allocate time for test maintenance
4. Address root causes of failures
### Execution Coverage
**Complete Execution**:
```
Test Run A: Total 100, Open 0%, Passed 85%, Failed 15%
Test Run B: Total 100, Open 0%, Passed 87%, Failed 13%
Test Run C: Total 100, Open 0%, Passed 84%, Failed 16%
```
**Interpretation**: All test runs executed completely - good coverage.
**Incomplete Execution**:
```
Test Run A: Total 100, Open 0%, Passed 85%, Failed 15%
Test Run B: Total 100, Open 25%, Passed 60%, Failed 15% ← Incomplete!
Test Run C: Total 100, Open 30%, Passed 55%, Failed 15% ← Incomplete!
```
**Interpretation**: Some test runs didn't execute all test cases - gaps in coverage.
**Action Items**:
1. Identify why tests weren't executed
2. Check for time constraints
3. Review test selection criteria
4. Allocate more resources if needed
## Common Use Cases
### Use Case 1: Cross-Browser Validation
**Scenario**: QA team needs to verify application works across all supported browsers
**Steps**:
1. Execute test suite on Chrome, Firefox, and Safari
2. Generate scorecard comparing all three test runs
3. Identify browser-specific failures
4. Prioritize fixes based on browser market share
**Report Configuration**:
* Test Runs: Latest test runs for each browser
* Comparison: Side-by-side browser results
**Expected Outcome**:
* Pass rates within 5% across browsers
* Browser-specific failures documented
* Action plan for compatibility fixes
**Real Example**:
```
Chrome (60% market share): Passed 92%, Failed 8% ✓ Good
Firefox (5% market share): Passed 89%, Failed 11% ✓ Acceptable
Safari (20% market share): Passed 75%, Failed 25% ✗ Must fix!
Edge (10% market share): Passed 88%, Failed 12% ✓ Acceptable
```
**Action**: Prioritize Safari fixes due to high market share and high failure rate.
### Use Case 2: Sprint Retrospective
**Scenario**: Team reviews testing quality and efficiency during sprint retrospective
**Steps**:
1. Generate scorecard for last 3 sprints
2. Compare pass rates and failure trends
3. Discuss improvements or regressions
4. Set goals for next sprint
**Report Configuration**:
* Test Runs: One regression run per sprint
* Comparison: Sprint-over-sprint trends
**Discussion Points**:
* "Why did our pass rate drop from 90% to 80%?"
* "Blocked tests increased - what's causing this?"
* "We reduced failures from 15% to 8% - what did we do right?"
**Outcome**: Data-driven retrospective with clear quality metrics and improvement goals.
### Use Case 3: Release Qualification
**Scenario**: Release manager needs to verify application is ready for production deployment
**Steps**:
1. Execute test suite in staging environment
2. Deploy to production
3. Execute same test suite in production
4. Generate scorecard comparing staging vs production
5. Make go/no-go decision
**Report Configuration**:
* Test Runs: Staging run and Production run
* Comparison: Environment parity check
**Go Criteria**:
* ✅ Production pass rate within 5% of staging
* ✅ No new failures in production
* ✅ Critical paths passing in production
* ✅ No blocked tests in production
**Example Decision**:
```
Staging: Passed 95%, Failed 5%
Production: Passed 94%, Failed 6% ✓ GO - Within tolerance
```
### Use Case 4: CI/CD Pipeline Optimization
**Scenario**: DevOps team wants to optimize test execution across pipeline stages
**Steps**:
1. Compare test runs from different pipeline stages
2. Identify redundant test execution
3. Analyze failure patterns by stage
4. Optimize test distribution
**Report Configuration**:
* Test Runs: Smoke tests, Unit tests, Integration tests, E2E tests
* Comparison: Execution efficiency by stage
**Optimization Insights**:
```
Smoke Tests: Total 20, Duration 5min, Passed 95% ✓ Fast & reliable
Unit Tests: Total 500, Duration 10min, Passed 98% ✓ Fast & reliable
Integration Tests: Total 100, Duration 30min, Passed 85% ~ Needs improvement
E2E Tests: Total 50, Duration 60min, Passed 70% ✗ Slow & unreliable
```
**Actions**:
1. Invest in fixing unreliable E2E tests
2. Parallelize integration tests
3. Move some E2E tests to integration layer
## Best Practices
### 1. Compare Apples to Apples
**Good Comparisons**:
* Same test suite, different browsers
* Same test suite, different environments
* Same test suite, different time periods
**Poor Comparisons**:
* Different test suites (smoke vs full regression)
* Different application versions (v1.0 vs v2.0)
* Different test data sets
**Why It Matters**: Valid comparisons require consistent test scope.
### 2. Use Consistent Naming
Name test runs to clearly indicate their purpose:
**Good Names**:
* "Sprint 24 - Chrome - Full Regression"
* "Release 2.5 - Staging - Smoke Tests"
* "Feature ABC - Integration Tests"
**Poor Names**:
* "Test Run 42"
* "Friday tests"
* "Bob's run"
**Why It Matters**: Clear names make the scorecard immediately understandable.
### 3. Set Baseline Metrics
Before tracking trends, establish baselines:
**Baseline Metrics to Track**:
* Average pass rate: \_\_%
* Average execution time: \_\_ minutes
* Average test count: \_\_
* Typical failure rate: \_\_%
**How to Use**:
* Compare future runs against baseline
* Identify significant deviations
* Track long-term trends
**Example**:
```
Baseline (Sprint 20): Passed 85%, Failed 12%, Blocked 3%
Current (Sprint 25): Passed 90%, Failed 8%, Blocked 2%
Trend: Improving! Pass rate +5%, Failures -4%, Blocked -1%
```
### 4. Look for Patterns
Don't focus on single data points - identify patterns:
**Pattern Types**:
* **Consistent failures**: Same test failing across all runs
* **Configuration-specific**: Failures only on specific browsers/environments
* **Time-based**: Failures increasing over time
* **Intermittent**: Test passing some runs, failing others
**Example Pattern Analysis**:
```
Test: "User Login"
Chrome: Pass Pass Pass Pass Pass ✓ Stable
Firefox: Pass Pass Pass Pass Pass ✓ Stable
Safari: Pass Fail Pass Fail Pass ⚠ Flaky!
```
**Action**: Investigate Safari-specific flakiness - timing issue or browser bug?
### 5. Act on Outliers
When one test run shows significantly different results:
**Outlier Example**:
```
Run 1: Passed 90%, Failed 10%
Run 2: Passed 88%, Failed 12%
Run 3: Passed 50%, Failed 50% ← Outlier!
Run 4: Passed 89%, Failed 11%
```
**Investigation Steps**:
1. Was test data corrupted?
2. Was environment unstable?
3. Was a different version tested?
4. Did test suite change?
**Don't Ignore**: Outliers often reveal important issues.
### 6. Share with Stakeholders
Different audiences need different views:
**For Developers**:
* Browser-specific failures
* Environment parity issues
* Test reliability trends
**For QA Managers**:
* Sprint-over-sprint improvements
* Resource allocation efficiency
* Testing bottlenecks
**For Product Managers**:
* Release readiness comparison
* Feature coverage by configuration
* Risk assessment
**For Executives**:
* High-level pass rate trends
* Quality improvement metrics
* Release confidence scores
### 7. Regular Scorecard Reviews
**Recommended Cadence**:
* **Weekly**: Compare last 2 weeks
* **Sprint End**: Compare last 3 sprints
* **Monthly**: Compare monthly trends
* **Release**: Compare staging vs production
**Benefits**:
* Early detection of quality regressions
* Continuous improvement tracking
* Team accountability for quality
## Related Reports
* **Test Cases Results Overview**: Detailed view of individual test case results
* **Test Case Success Rate Analysis**: Identify unreliable tests across multiple runs
* **Test Case Duration Analysis**: Compare execution times across test runs
* **Testing Effort Analysis**: Compare time spent across different test runs
## Getting Help
For assistance with this report:
1. Review the report parameters to ensure correct test run selection
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Verify test runs executed successfully before comparing
4. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Quick Summary**: The Test Runs Scorecard is your tool for comparative analysis. Use it to compare browsers, environments, or time periods. Look for patterns, not just individual numbers. Act quickly on outliers and regressions. Regular scorecard reviews drive continuous quality improvement.
---
# Test Case Duration
URL: /docs/reports/test-case-duration-report
The Test Case Duration report analyzes test execution times to help you identify slow tests, optimize test suites, and improve CI/CD pipeline performance. This report is essential for maintaining efficient testing processes and reducing feedback loops.
## What This Report Shows
The Test Case Duration report displays:
1. **Summary Metrics**: Average, minimum, and maximum execution times
2. **Test Case Duration Details**: Individual test execution times and counts
3. **Duration Trends**: Execution time patterns across multiple runs
4. **Folder Organization**: Test cases grouped by folder for focused analysis
5. **Execution Frequency**: How many times each test has been executed
## When to Use This Report
Use the Test Case Duration report when you need to:
* **Optimize CI/CD pipelines** by identifying and improving slow tests
* **Reduce test execution time** to provide faster feedback
* **Identify performance regressions** in test execution
* **Plan test parallelization** by understanding test duration distribution
* **Estimate testing effort** for sprint or release planning
* **Balance test suites** for efficient resource utilization
## Understanding the Report
### Summary Metrics
At the top of the report, you'll see three key duration metrics:

**Summary Circles Display**:
* **Average Time**: Mean execution time across all tests
* **Min Time**: Fastest test execution time
* **Max Time**: Slowest test execution time
**Example Summary**:
```
Average time: 2m 24s
Min time: 1m 20s
Max time: 4m
```
**Interpretation**:
* **Average (2m 24s)**: Typical test takes \~2.5 minutes
* **Min (1m 20s)**: Fastest test is relatively quick
* **Max (4m)**: Slowest test takes nearly twice the average - candidate for optimization
### Duration Table
Below the summary, you'll find detailed test case information:
| Column | Description |
| ------------------- | -------------------------------------- |
| **Name** | Test case name and description |
| **Execution Count** | Number of times test has been executed |
| **Duration (min)** | Fastest execution time |
| **Duration (max)** | Slowest execution time |
| **Duration (avg)** | Average execution time |
**Example Table**:
```
Name Count Min Max Avg
Correct display of blocks and buttons in navbar 1 2m 40s 2m 40s 2m 40s
User should see "About Us" page after clicking 1 1m 20s 1m 20s 1m 20s
User should see "Today's Menu" block 1 1m 30s 1m 30s 1m 30s
Changing to corresponding cursor... 1 2m 2m 2m
Correct display in different screen resolutions 1 3m 3m 3m
```
### Folder Organization
Tests are organized by folder structure:
```
📁 Navbar
└─ Test 1: 2m 40s (avg)
└─ Test 2: 1m 20s (avg)
📁 About us
└─ Test 3: 1m 30s (avg)
📁 Checkout
└─ Test 4: 3m (avg)
└─ Test 5: 2m (avg)
```
**Folder Insights**:
* **Total folder time**: Sum of all test durations in folder
* **Folder average**: Mean duration for folder tests
* **Slowest tests**: Identify optimization candidates per folder
## Generating the Report

1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Select **Test Case Duration**
4. Click **Next**
5. Choose the way to select test cases for the report: by **Milestone**, **Test Run** or time **Period**
6. Click **Build report**
## Export Options
**Export XLSX**:
* Raw data export for further analysis
* Open in Excel, Google Sheets, or BI tools
* Click ... and then **Export XLSX** button
**Export PDF**:
* Full report with charts and tables
* Professional formatting for stakeholder distribution
* Click ... and then **Export PDF** button
**Print**:
* Direct print for physical documentation
* Formatted for standard paper sizes
* Click ... and then **Print** button
## Best Practices
### 1. Track Duration Trends
**Establish Baselines**:
```
Baseline (Sprint 20):
- Average: 2m 30s
- Total suite: 45m
- Slowest test: 5m
```
**Monitor Changes**:
```
Sprint 21:
- Average: 2m 45s (+15s) ⚠️
- Total suite: 48m (+3m) ⚠️
- Slowest test: 6m (+1m) ⚠️
Trend: Degrading - investigate!
```
**Set Alerts**:
* Alert if average > 3m
* Alert if total suite > 60m
* Alert if any test > 10m
* Alert if variance > 50%
### 2. Optimize High-Impact Tests
**Use the 80/20 Rule**:
* 20% of tests typically consume 80% of time
* Focus optimization on slowest 20%
* Biggest ROI from optimizing slow tests
### 3. Set Duration Targets
**Establish Standards**:
**Fast Tests** (Target: \< 30s):
* Unit tests
* Simple integration tests
* API tests
* Smoke tests
**Medium Tests** (Target: 30s - 3m):
* UI integration tests
* Database integration tests
* Multi-step workflows
**Slow Tests** (Target: 3m - 10m):
* Complex E2E scenarios
* Cross-system integration
* Performance tests
**Too Slow** (> 10m):
* Needs optimization or restructuring
* Consider splitting into multiple tests
* May need architectural changes
**Example Policy**:
```
Unit Tests: Must be < 10s
API Tests: Must be < 30s
UI Tests: Must be < 5m
E2E Tests: Must be < 10m
Total Suite: Must be < 1h
```
### 4. Regular Duration Reviews
**Review Cadence**:
* **Daily**: Check if any tests exceeded thresholds
* **Weekly**: Review trend in average duration
* **Sprint**: Comprehensive duration analysis
* **Quarterly**: Major optimization initiative
**Review Checklist**:
* [ ] Average duration stable or improving
* [ ] No tests exceed maximum thresholds
* [ ] Variance is acceptable (\< 50%)
* [ ] Total suite time within budget
* [ ] New tests follow duration standards
### 5. Document Performance Requirements
**Include in Test Design**:
```
Test Case: User Registration
Expected Duration: 2 minutes ± 30s
Maximum Allowed: 3 minutes
Performance Requirements:
- Page load < 2s
- API calls < 500ms
- Database queries < 100ms
```
**Benefits**:
* Sets clear expectations
* Enables performance regression detection
* Guides test optimization efforts
### 6. Balance Speed and Thoroughness
**Don't Sacrifice Quality for Speed**:
* Faster isn't always better
* Some tests legitimately need time
* Important: Accurate > Fast
**When Long Duration is OK**:
* Complex multi-step workflows
* Necessary wait times (email delivery, processing)
* Comprehensive integration scenarios
* Performance/load tests
**When to Optimize**:
* Unnecessary waits
* Redundant operations
* Inefficient test design
* Can be faster without compromising accuracy
## Related Reports
* **Test Runs Scorecard Analysis**: Compare duration across multiple test runs
* **Test Case Success Rate Analysis**: Correlate duration with flakiness
* **Testing Effort Analysis**: Total time spent on testing activities
## Getting Help
For assistance with this report:
1. Verify test runs include duration data
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Review test framework configuration for duration tracking
4. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Quick Summary**: The Test Case Duration report helps you optimize testing speed. Focus on the slowest 20% of tests for maximum impact. Track duration trends to detect regressions early. Balance test suite for efficient parallelization. Set and enforce duration standards to maintain fast feedback loops.
---
# Test Case Success Rate
URL: /docs/reports/test-case-success-rate-report
The Test Case Success Rate report calculates success rates for individual test cases across multiple executions to identify unreliable tests, track test quality, and prioritize test maintenance efforts. This report is essential for maintaining a reliable and trustworthy test suite.
## What This Report Shows

The Test Case Success Rate report displays:
1. **Overall Success Rate**: Aggregate success percentage across all test cases
2. **Per-Test Success Rates**: Individual success percentages for each test case
3. **Execution Counts**: Number of times each test has been executed
4. **Reliability Metrics**: Statistical significance of success rates
5. **Folder Organization**: Tests grouped by folder structure
## When to Use This Report
Use the Test Case Success Rate report when you need to:
* **Identify flaky tests** that pass/fail inconsistently
* **Track test reliability** across multiple executions
* **Prioritize test maintenance** based on failure frequency
* **Evaluate test quality** before expanding test suite
* **Build confidence** in test results through consistency metrics
* **Quarantine unreliable tests** from critical pipelines
## Understanding the Report
### Overall Success Rate
At the top of the report, you'll see the aggregate success rate displayed in a circular progress indicator showing the overall percentage of successful test executions.
**Example**:
```
Success Rate: 68.1%
```
**Interpretation**: Across all test executions, tests passed 68.1% of the time. This indicates room for improvement in test reliability.
### Success Rate Table
The detailed table shows per-test metrics organized by folder structure:
| Column | Description |
| ------------------- | -------------------------------------- |
| **Name** | Test case name and description |
| **Execution Count** | Number of times test has been executed |
| **Success Rate** | Percentage of executions that passed |
**Success Rate Indicators**:
* **90-100%**: Reliable test ✅
* **70-89%**: Acceptable but needs monitoring ⚠️
* **50-69%**: Flaky test requiring attention ❌
* **Below 50%**: Broken test needing immediate fix 🚫
## Generating the Report

1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Select **Test Case Success Rate**
4. Click **Next**
5. Choose the way to select test cases for the report: by **Milestone**, **Test Run** or time **Period**
6. Click **Build report**
## Export Options
**Export XLSX**:
* Raw data export for further analysis
* Open in Excel, Google Sheets, or BI tools
* Click ... and then **Export XLSX** button
**Export PDF**:
* Full report with charts and tables
* Professional formatting for stakeholder distribution
* Click ... and then **Export PDF** button
**Print**:
* Direct print for physical documentation
* Formatted for standard paper sizes
* Click ... and then **Print** button
## Getting Help
For assistance with this report:
1. Review the report parameters to ensure correct configuration
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Quick Summary**: Use the Test Case Success Rate report to identify unreliable tests. Target 95%+ success for critical tests, 90%+ for others. Investigate tests below 80% immediately. Track improvement over time and quarantine flaky tests from critical pipelines.
---
# Traceability
URL: /docs/reports/traceability-report
The Traceability Report, also known as the Test Traceability Matrix (TTM), maps test cases to requirements, user stories, or features to ensure complete test coverage. This report is essential for regulatory compliance, release readiness verification, and requirement coverage analysis.
## What This Report Shows

The Traceability Report displays:
1. **Requirements List**: All requirements, user stories, or features linked to test cases
2. **Test Case Mappings**: Which test cases validate each requirement
3. **Execution Status**: Pass/fail status for tests linked to each requirement
4. **Coverage Gaps**: Requirements with no associated test cases
5. **Linked Issues**: Bugs or blockers associated with failed requirements
## When to Use This Report
Use the Traceability Report when you need to:
* **Verify requirement coverage** before releases
* **Demonstrate compliance** for audits or regulatory requirements
* **Identify testing gaps** in requirement coverage
* **Track requirement validation** across test runs
* **Prepare release documentation** showing tested requirements
* **Assess release readiness** based on requirement pass rates
* **Track defects** blocking requirements and their resolution status
* **Identify quality issues** affecting requirement validation
## Setting Up Requirements for Traceability
For the Traceability Report to display meaningful data, each test case must be linked to one or more requirements. Follow these steps to set up requirements and link them to test cases:
### Step 1: Configure Requirements on the Resources Page
Before you can assign requirements to test cases, you need to define them for the project:
1. Open the project and click the project-level **Resources** icon in the top bar. Resources is separate from Workspace Settings — the gear icon opens Workspace Settings, the Resources icon opens this page.
2. Locate the **Requirements** section
3. Add your requirements, user stories, or feature references
4. Save your changes
Requirements can also be pulled in from a connected issue tracker instead of being typed by hand — see [Importing requirements from Jira or Linear](#importing-requirements-from-an-issue-tracker) below.
### Step 2: Link Requirements to Test Cases
When creating or editing a test case:
1. Open the test case editor
2. Find the **Requirement** dropdown field
3. Select one or more requirements that this test case validates
4. Save the test case
You can link multiple requirements to a single test case if the test validates several requirements simultaneously.
Test cases without linked requirements appear in a **"No Requirement"** section at the bottom of the Traceability Report. While these test cases are still visible, linking them to requirements ensures better traceability and coverage analysis.
### Importing Requirements from an Issue Tracker
If your requirements already live in Jira or Linear, you can pull them in instead of retyping them. Open the **Edit Requirements** modal on a test case and choose the **Import from Jira** (or **Import from Linear**) option, then pick the issues that this test case validates. Imported requirements behave exactly like manually entered ones in this report, and the issue key is preserved so the report links back to the tracker.
Linear requirements need the [Linear integration](/docs/linear) connected to the project; Jira requirements need the [Jira integration](/docs/jira).
### Requirement Badges in the Test Case List
Requirement badges appear alongside tags in the test case list, so you can see coverage without opening each case. Issue keys such as `PROJ-123` are shown as badges with the full requirement text on hover. Toggle the badges in **Settings → Customization**.
## Understanding the Report
### Traceability Matrix Structure
The report lists requirements as section headers, with test cases displayed in a table format below each requirement with three columns: **Test Case**, **Results**, and **Issues**.

**Table Columns**:
| Column | Description |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Test Case** | Name of the test case linked to the requirement |
| **Results** | Execution status (Passed, Failed, Blocked, Open, Skipped) |
| **Issues** | Linked bugs or blockers displayed as clickable tags. The appearance and text format depend on the issue tracker type connected to your project (Jira, GitHub, Linear, etc.) and the project name configured in your issue tracker. Click to view full details in your issue tracker |
### Status Badges
Each test case displays a status badge in the **Results** column:
* **Passed** (Green): Test executed successfully
* **Failed** (Red): Test failed one or more assertions
* **Blocked** (Orange): Test blocked by dependencies or issues
* **Open** (Blue): Test not yet executed
* **Skipped** (Gray): Test intentionally skipped
### Defects and Issues in Traceability
When a test case fails, QA Sphere allows you to create a new issue or link to an existing issue in your integrated issue tracker. Each project can be connected to a specific issue tracker such as Jira, GitHub, Linear, Notion, GitLab, and others. For setup instructions, see the [Integrations section](/docs/integrations-intro).
#### How Issues Appear in the Report

Issues linked to test cases appear as clickable tags in the **Issues** column. The tag appearance and issue ID format depend on your connected issue tracker type and the project name configured in that tracker.
Clicking an issue tag opens the full issue details directly in your issue tracker:

**Key Points**:
* Issues can be linked to test cases with Failed, Blocked, or other statuses
* All issue tags are clickable and open directly in your connected issue tracker
## Generating the Report

1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Select **Traceability Report**
4. Click **Next**
5. Choose the way to select test cases for the report: by **Milestone**, **Test Run** or time **Period**
6. Click **Build report**
### Filtering and Report Metadata
**Status Filter**: Use the **Status** dropdown at the top of the report to filter test cases by execution status (All, Passed, Failed, Blocked, Open, Skipped).
**Report Metadata**: The right sidebar displays the report name, generation date/time, generated by user, and associated test runs (displayed as tags, e.g., "Functional Testing" with platform tags like "iOS").
## Export Options
**Export XLSX**:
* Raw data export for further analysis
* Open in Excel, Google Sheets, or BI tools
* Click ... and then **Export XLSX** button
**Export PDF**:
* Full report with charts and tables
* Professional formatting for stakeholder distribution
* Click ... and then **Export PDF** button
**Print**:
* Direct print for physical documentation
* Formatted for standard paper sizes
* Click ... and then **Print** button
## Best Practices
### 1. Link Tests to Requirements Early
**Best Practice**: Link test cases to requirements during test case creation
**Benefits**:
* Ensures traceability from the start
* Prevents coverage gaps
* Simplifies compliance documentation
**How to Link**:
```
Test Case: "User can reset password"
Linked Requirements: REQ-042, REQ-043
```
**Avoid**: Creating test cases first, then linking requirements later.
### 2. Maintain One-to-Many Relationships
**Best Practice**: One requirement can have multiple test cases
**Good Example**:
```
REQ-015: User Authentication
├─ TC-101: Login with valid credentials
├─ TC-102: Login with invalid credentials
├─ TC-103: Login with expired session
├─ TC-104: Login with locked account
└─ TC-105: Logout functionality
```
**Why**: Comprehensive testing requires multiple test scenarios per requirement.
### 3. Track Coverage Metrics Over Time
**Track These Metrics**:
* **Coverage Percentage**: % of requirements with tests
* **Pass Rate**: % of requirements with passing tests
* **Untested Requirements**: Count of requirements without tests
**Set Goals**:
```
Sprint 1: 60% coverage, 70% pass rate
Sprint 2: 75% coverage, 80% pass rate
Sprint 3: 90% coverage, 90% pass rate ← Goal
Sprint 4: 100% coverage, 95% pass rate ← Ideal
```
**Track Progress**:
* Review traceability report weekly
* Track coverage trends
* Celebrate improvements
* Address regressions immediately
### 4. Prioritize Based on Risk
**High-Risk Requirements** (Test First):
* Security-related
* Payment/financial
* Data integrity
* Core business logic
* Regulatory compliance
**Medium-Risk Requirements** (Test Second):
* User-facing features
* Configuration settings
* Reporting functionality
* API integrations
**Low-Risk Requirements** (Test Last):
* Cosmetic changes
* Documentation updates
* Non-critical UI elements
* Internal tools
**Example Prioritization**:
```
Sprint Test Creation Priority:
1. REQ-099: Encryption implementation (Security) - 5 tests
2. REQ-042: Payment gateway (Financial) - 8 tests
3. REQ-071: User registration (Core) - 6 tests
4. REQ-053: Dashboard widgets (UI) - 3 tests
5. REQ-014: Theme customization (Cosmetic) - 2 tests
```
### 5. Include in Definition of Done
**Definition of Done Checklist**:
* ✅ Code written and reviewed
* ✅ Unit tests created and passing
* ✅ Integration tests created and passing
* ✅ **Test cases linked to requirements** ← Traceability
* ✅ **All requirement tests passing** ← Coverage
* ✅ Documentation updated
* ✅ Code deployed to staging
**Benefits**:
* Ensures consistent traceability
* Prevents coverage gaps
* Makes traceability part of workflow
### 6. Regular Traceability Reviews
**Recommended Cadence**:
* **Weekly**: Quick coverage check during planning
* **Sprint End**: Full traceability review during retrospective
* **Release**: Comprehensive validation before deployment
* **Quarterly**: Audit readiness check
**Review Checklist**:
* [ ] All new requirements have linked test cases
* [ ] All critical requirements have passing tests
* [ ] Coverage percentage maintained or improved
* [ ] No orphaned test cases (tests with no requirements)
* [ ] No untested high-priority requirements
## Related Reports
* **Test Cases Results Overview**: See test execution details for requirements
* **Test Runs Scorecard Analysis**: Compare requirement coverage across test runs
* **Testing Effort Analysis**: Time spent testing requirements
## Getting Help
For assistance with this report:
1. Verify requirements and test cases are properly linked
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Review your requirement management process
4. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Quick Summary**: The Traceability Report ensures every requirement is tested. Use it before releases to verify coverage, during audits for compliance, and during planning to identify gaps. The report tracks defects linked to failed tests, helping you assess release readiness and prioritize fixes. Aim for 100% coverage of critical requirements and 90%+ overall. Link test cases to requirements from the start, and link defects when tests fail to maintain complete traceability.
---
# View Results
URL: /docs/reports/view-results-report
The Test Cases Results Overview report provides a comprehensive snapshot of test case execution results across selected test runs. **The report shows the latest result for each test case** - when you include one or multiple test runs, each test case appears once with its most recent execution status. This gives you an overall view of your current testing efforts and helps you understand the current state of your test suite, not historical trends.
## What This Report Shows
The Test Cases Results Overview displays:
1. **Overall Status Distribution**: Visual breakdown of test results by status (Passed, Failed, Open, Blocked, Skipped)
2. **Test Case Details**: Complete list of test cases with their **latest execution results** across selected test runs
3. **Configuration Information**: Test configuration details (browser, environment, etc.)
4. **Test Run Assignments**: Which test run each result belongs to (the most recent run for each test case)
5. **Folder Organization**: Test cases grouped by their folder structure
**Latest Result Per Test Case**: When you include multiple test runs in the report, each test case appears only once showing its **most recent execution result**. For example, if "Login Test" was run in Test Run A (Passed) and Test Run B (Failed), the report shows only the Failed status from Test Run B. This provides a current-state snapshot of your testing efforts rather than historical data.
## When to Use This Report
Use the Test Cases Results Overview when you need to:
* **Check current testing status** during daily standups or status meetings
* **Identify failing test cases** that need immediate attention
* **Review test coverage** across different test folders
* **Prepare for release** by verifying test execution status
* **Communicate results** to stakeholders with clear visualizations
* **Track progress** during a testing cycle or sprint
## Understanding the Report
### Status Visualization
At the top of the report, you'll see a visual breakdown of test case statuses:

**Status Bars Show**:
* **Passed** (Green): Percentage and count of successful tests
* **Failed** (Red): Percentage and count of failed tests
* **Open** (Blue): Percentage and count of unexecuted tests
* **Blocked** (Orange): Percentage and count of blocked tests
* **Skipped** (Gray): Percentage and count of skipped tests
**How to Read the Visualization**:
* Longer bars indicate higher percentages
* Numbers show both percentage and absolute count
* Color coding provides instant visual recognition
* Aim for high green (Passed) percentages
### Test Case Table
Below the visualization, you'll find a detailed table with:
| Column | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **Test Case** | Name and description of the test case |
| **Configuration** | Test configuration (browser, OS, environment) |
| **Status** | Latest execution status (badge with color coding) - shows the most recent result if the test case was executed in multiple runs |
| **Test Run** | Which test run this result belongs to (the most recent run where this test case was executed) |
**Status Badges**:
* **Passed** - Green badge, test executed successfully
* **Failed** - Red badge, test failed one or more assertions
* **Open** - Blue badge, test not yet executed
* **Blocked** - Orange badge, test blocked by dependency or issue
* **Skipped** - Gray badge, test intentionally skipped
### Folder Organization
Test cases are organized by their folder structure in QA Sphere:
```
📁 Navbar
└─ Test Case 1
└─ Test Case 2
📁 About us
└─ Test Case 3
📁 Menu
└─ Test Case 4
└─ Test Case 5
```
## Generating the Report

1. Open your QA Sphere project
2. Click **Reports** in the top navigation
3. Select **View Results**
4. Click **Next**
5. Choose the way to select test cases for the report: by **Milestone**, **Test Run** or time **Period**
6. Click **Build report**
## Export Options
**Export XLSX**:
* Raw data export for further analysis
* Open in Excel, Google Sheets, or BI tools
* Click ... and then **Export XLSX** button
**Export PDF**:
* Full report with charts and tables
* Professional formatting for stakeholder distribution
* Click ... and then **Export PDF** button
**Print**:
* Direct print for physical documentation
* Formatted for standard paper sizes
* Click ... and then **Print** button
## Best Practices
### 1. Regular Report Reviews
**Establish a Cadence**:
* **Daily**: Generate report each morning to track overnight test runs
* **Sprint Reviews**: Generate at sprint end for retrospectives
* **Release Gates**: Generate before each release decision
**Benefits**:
* Early detection of quality issues
* Consistent quality tracking
* Data-driven decision making
### 2. Use Meaningful Test Run Names
When creating test runs in QA Sphere, use descriptive names:
**Good Examples**:
* "Sprint 23 - Chrome - Regression Suite"
* "Release 2.5 - Cross-Browser - Smoke Tests"
* "Feature ABC - Integration Tests"
**Poor Examples**:
* "Test Run 1"
* "Monday tests"
* "Run 123"
**Why This Matters**: Clear test run names make the report immediately understandable.
### 3. Export for Documentation
**PDF Exports for**:
* Release documentation
* Audit trails
* Stakeholder reports
**XLSX Exports for**:
* Trend analysis in Excel
* Integration with BI tools
* Custom reporting
### 4. Combine with Other Reports
Use multiple reports together for complete picture:
**Test Cases Results Overview** + **Test Traceability Matrix**:
* Verify all requirements are tested
* Check requirement coverage status
**Test Cases Results Overview** + **Test Case Success Rate**:
* Identify consistently failing tests
* Prioritize test maintenance
**Test Cases Results Overview** + **Test Case Duration**:
* Optimize slow tests
* Improve CI/CD performance
## Getting Help
For assistance with this report:
1. Review the report parameters to ensure correct configuration
2. Check the [Reports Overview](/docs/reports-overview) for general guidance
3. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Quick Summary**: The Test Cases Results Overview report shows the latest result for each test case across one or multiple test runs, giving you an overall view of your current testing efforts. Use it daily for quick status checks, before releases for readiness verification, and during sprints for progress tracking. Focus on maintaining a high pass rate and quickly addressing failures and blocked tests.
---
# AI Features
URL: /docs/tms/ai-features
QA Sphere has AI built into the test case workflow rather than bolted on beside it. This page covers what the AI can do, how to steer it with rules, and how usage is metered.
Everything here works on your project's own data. No separate API key or model subscription is needed — AI usage is included in your plan and metered as **AI credits**.
## Generating Test Cases in Bulk
The fastest way to populate a library. From the **Test Cases** tab, choose **Create → Bulk Test Cases with AI**, describe what you want covered (or attach a spec, requirements document, or spreadsheet), and review the generated cases before saving.
Two behaviors worth knowing:
* **Duplicate detection runs during generation.** Generated cases that duplicate something already in the project are highlighted so you can drop them before adding. This keeps repeated generation runs from silently inflating the library.
* **Navigating away is guarded.** A confirmation dialog appears if you leave the bulk generation page with work in progress, so a stray click does not discard a batch.
Bulk generation is also the recommended path for importing spreadsheets that do not match QA Sphere's CSV layout — see [Import with AI](/docs/import-with-ai).
## The AI Test Case Assistant
The assistant is a conversational panel on the **Test Cases** page. Instead of building a filter, you ask:
* "Which test cases cover checkout with an expired card?"
* "Summarize what this folder tests."
* "Do we have coverage for the password reset flow?"
* "Show me high-priority cases that are still drafts."
It can search, filter, summarize, and answer questions about the test cases in the project.
The assistant reads your library; it does not silently change it. Use it to find and understand cases, then act on them yourself.
## Duplicate Detection and Merge
Beyond the check that runs during generation, QA Sphere can sweep an entire project for duplicates. It surfaces groups of similar test cases so you can review them and **merge** each group into a single case, which is the practical way to clean up a library that has grown through copy-paste.
Detection also recognizes cases and folders that were copied rather than rewritten, so near-identical clones are grouped correctly.
Project-wide duplicate detection is currently limited to projects with **500 or fewer test cases**. Larger projects can still rely on the duplicate check that runs during bulk generation.
## Global AI Rules
AI rules are standing instructions that shape every generation in scope: house style for step wording, a required precondition, terminology to use or avoid, the level of detail you expect.
Define them once in **Workspace Settings** and apply them to selected projects or to all projects. A rule applied at the workspace level means a new project inherits your conventions on day one instead of after the first review cycle.
Good rules are specific and testable. "Write clearly" changes nothing; "Every step must state the expected result in a separate Expected field" and "Refer to the product as *Acme Cloud*, never *the app*" both do.
## AI Elsewhere in QA Sphere
| Where | What AI does |
| -------------------------------------- | ----------------------------------------------------------------------------------------------- |
| [Jira integration](/docs/jira) | Drafts the summary and description of a bug from the test case and the tester's result comments |
| [Import with AI](/docs/import-with-ai) | Parses arbitrary spreadsheets into structured test cases |
## AI Credits and Usage
AI usage is metered as credits and included in your plan: the Free plan has limited credits, paid plans more, and the Business plan extended credits. See [Billing](/docs/billing) for the per-plan picture.
Current usage is shown as a **percentage of your limit**, together with when the limit resets, so you can see what is left before starting a large generation run.
Bulk generation over a long document is the most credit-intensive operation; asking the assistant a question is among the cheapest.
## Working Well with AI
**Review before saving.** Generated cases are a first draft. The generation step is the cheap part; a library full of unreviewed cases is expensive for years.
**Give it real context.** AI issue generation in Jira, for instance, can fail outright when the test case and result comments do not contain enough to identify what went wrong. Thin input produces thin output, or none.
**Encode conventions as rules, not as repeated prompts.** If you find yourself typing the same instruction into every prompt, it belongs in a global AI rule.
**Let duplicate detection run before a cleanup sprint.** It is far quicker to review AI-proposed duplicate groups than to eyeball a few thousand titles.
AI issue generation is not available when batch-adding results for multiple test cases at once. Add the result individually when you want AI to draft the bug report.
---
# Quick Start
URL: /docs/quick-start
This guide will help you get started with creating projects, adding test cases, and running tests.
Your browser does not support the video tag.
## Creating a Project
A project in QA Sphere can be used for assigning test cases to a specific app or a certain functional part of a bigger application.
1. Navigate to the top-right corner of the screen.
2. Click on the **Add Project** button.
3. Follow the prompts to set up your new project.
## Adding Test Cases
Well-described and structured test cases are the basic requirement for running tests.
1. Switch to the **Test Cases** tab in your project.
2. Add test cases using one of three methods:
* Type directly into the list
* Use the **Create Test Case** form for more detailed entries
* Generate a batch with **Create → Bulk Test Cases with AI**, from a prompt or an attached spec — see [AI Features](https://qasphere.com/docs/tms/ai-features)
3. Create folders using **Create Folder** button and organize your test cases for better structure
### Using the **Create Test Case** Form
The form allows you to specify:
* Detailed description
* Preconditions
* Steps to take, each with an expected result and optional **test data**
* Requirements
* Priority
* Tags
* Custom fields defined for the project
* Additional resources (attachments)
#### Test Data on Steps
A step can carry its own test data alongside its description and expected result: credentials, request payloads, sample values, links, and file attachments. This keeps the data next to the step that uses it instead of buried in the preconditions.
Each item is text (with an optional language hint for syntax highlighting), a link, or a file, and a step can hold up to 20 items. Text items can hold large payloads, so a full JSON request body is fine. The Data field can be turned on or off for the workspace in **Settings**.
### Drafts and Publishing
A test case is either a **draft** or **published**. Drafts are work in progress: visible in the library, but not yet part of your stable suite. Publish a case when it is ready to be executed.
The transition works in both directions:
* Published cases can be reverted to draft, individually or in bulk, when they need rework. A case that is already linked to a test run cannot be reverted — remove it from the run first.
* While editing a published case, you can save your changes as a draft rather than publishing them immediately, so an in-progress rewrite does not disturb testers using the current version.
## Creating Test Runs
1. Navigate to the **Test Runs** section and click **Create Test Run**.
2. Name and describe the test run, assign a team member, and select a milestone.
3. Select the test cases update option:
* Choose **User Selection** to pick test cases individually.
* **Live** mode builds test runs based on the test case folder structure.
> **NOTE:** In both modes, the test run will update when test cases are modified in the library.
* Select **Fixed Version** to preserve the current state of test cases regardless of future modifications in the library.
4. Select test cases for the test run, review the preview if needed, and click **Create Test Run** to finalize.
## Executing Test Runs
1. Start the test run by clicking on it.
2. Follow the instructions for each test case.
3. Mark the status of each test case based on results.
4. Track time spent on individual test cases.
## Reviewing Results
* Once the status of all test cases is updated, the test run can be closed.
* All test run details are automatically saved and can be reviewed later.
* Detailed reports can be generated out of the test runs' data.
By following these steps, you'll be well on your way to effectively using QA Sphere for testing your products.
## Where to Next
* [Test Run Configuration](https://qasphere.com/docs/test-run-configuration) — flexibility options, milestones, and running a test run with several testers at once
* [Test Plans](https://qasphere.com/docs/tms/test-plans) — group related runs when you need the same suite across several browsers or environments
* [AI Features](https://qasphere.com/docs/tms/ai-features) — bulk generation, the test case assistant, duplicate detection, and AI rules
* [Reports](/docs/reports-overview) — turn run data into status, coverage, and effort reporting
* [Import & Export](/docs/import) — bring an existing library in from CSV or another test management system
* [Integrations](/docs/integrations-intro) — connect an issue tracker, Slack, and your CI pipeline
---
# Test Plans
URL: /docs/tms/test-plans
A **test plan** groups related test runs so they can be executed and tracked as one unit. Where a [test run](https://qasphere.com/docs/test-run-configuration) is one pass over a set of test cases, a plan is the container for the several runs that make up a release cycle — the same suite across four browsers, the same regression pack across three environments, or a set of module-by-module runs for a sprint.
Plans keep the configurations, assignments, and test case selections of every run they contain, so the whole cycle is set up once and reported on together.
## When to Use a Plan Instead of a Run
Reach for a plan when the same testing has to happen more than once in parallel:
| Situation | Shape of the plan |
| -------------------------------- | ------------------------------------------------------------------ |
| **Cross-browser testing** | One run per browser, identical test cases, different configuration |
| **Multi-platform testing** | One run per device or OS version |
| **Multi-environment regression** | One run per environment (staging US, staging EU, staging APAC) |
| **Sprint sign-off by module** | One run per module, each with its own test cases and owner |
If you only need a single pass over a set of test cases, create a plain test run instead — a plan adds structure you would not use.
## Creating a Test Plan
1. Open your project and go to the **Test Plans** section.
2. Click **Create Test Plan**.
3. Give the plan a **title**, and optionally a **description** (rich text: code blocks, images, and tables are supported).
4. Optionally associate the plan with a **milestone**, so the release it belongs to is explicit.
5. Add the runs the plan should contain. For each run, set its title, assignee, configuration, and the test cases it covers.
6. Save the plan.
Plan titles must be unique within their milestone (or among plans that have no milestone). Reusing a title in the same milestone is rejected.
### Adding and Cloning Runs
Runs can be added to a plan after it is created, and existing runs can be **cloned** into a plan. Cloning copies the run's configuration, assignment, and test case selection, which is the fastest way to build a matrix: set up the first run exactly as you want it, then clone it once per browser or environment and change only the configuration.
## Naming Runs Inside a Plan
Because a plan's runs are usually near-identical, a consistent naming pattern is what makes the plan readable later:
* **Good**: `Checkout — Chrome`, `Checkout — Firefox`, `Checkout — Safari`
* **Harder to read**: `Chrome tests`, `FF run 2`, `safari final`
Keep the functional part of the name identical across runs and vary only the configuration suffix. Reports that compare runs, notably [Run Scorecard](/docs/reports/run-scorecard-report), read much better this way.
## Assigning Work
Each run in a plan can be assigned to a different person. When you are testing one feature across several platforms, assign by **platform expertise** rather than by feature: the person who knows iOS takes the iOS run, even though every run covers the same test cases.
Assignees must be active users with a role above Viewer. See [Users and Permissions](/docs/users-permissions) for what each role can do.
## Tracking Progress
* **Test Plans list** — plans are sorted by activity time, which updates when results are added. Until a plan has results, it sorts by creation time, so a freshly created plan does not jump to the top of the list on every edit.
* **Notifications** — plan notifications cover lifecycle events: a plan being closed, reopened, or deleted. Assignment notifications are raised for the individual **runs** inside a plan, since assignment happens at the run level rather than on the plan itself. Notifications appear in the notifications panel, with unread filters and bulk mark-as-read.
* **Slack** — subscribing a channel to a project's `runs` event category also covers test plans created, closed, reopened, and deleted. See [Slack](/docs/slack).
* **Webhooks** — the `plan_created` and `plan_updated` events fire for plans. See [Webhooks](/docs/webhooks).
## Test Plans and Milestones
Milestones and plans solve adjacent problems and work well together:
* A **milestone** marks a point in the project timeline, such as "Version 2.4 Release".
* A **plan** is the concrete set of runs executed for it.
Attaching plans to milestones lets you answer "what testing did we do for 2.4?" without reconstructing it from individual runs. Milestones are covered in [Test Run Configuration](https://qasphere.com/docs/test-run-configuration#what-are-milestones).
## Creating Plans Programmatically
Plans can be created through the public API and the CLI, which is how you wire a plan into a release pipeline:
* [Test Plans API](/docs/api/plan) — `POST /api/public/v0/project/{project_id}/plan`, including worked examples for cross-browser, multi-platform, and multi-environment plans
* [CLI Public API commands](/docs/cli/public-api) — drive the same endpoints from the terminal or CI
**API limitations**
Plans created through the API support **User selection** runs only: each run must list its `tcaseIds` explicitly, and exactly one query plan per run. Dynamic folder- or tag-based selection, cloning a plan, and updating an existing plan are not available through the public API yet — do those in the web interface.
---
# Test Run Configuration
URL: /docs/test-run-configuration
Test Runs in QA Sphere are a crucial part of the software development lifecycle, helping ensure that products meet quality standards before release. They involve executing predefined test cases to evaluate the functionality, performance, and reliability of a software application or system.
## Creating a New Test Run
There are two ways to create a new test run:
### Method 1: Using the Test Runs Tab
1. Navigate to the **Test Runs** tab.
2. Click on the **Create Test Run** button.
### Method 2: From the Test Cases Tab
1. In the Test Cases tab, select a folder containing the desired test cases.
2. Click the options icon next to the folder name.
3. Choose **Create Test Run with Folder**. This will automatically include all test cases from the selected folder in your new test run.
## Configuring Your Test Run
The key steps in configuring your test run are:
1. Assign a title and description to clearly identify the purpose of the test run.
2. Designate a responsible executive to oversee the test run.
3. Select or create a new milestone to associate with this test run.
4. Choose your preferred flexibility option based on your project needs.
5. Add folders containing the test cases you want to include in this run.
## Understanding Key Concepts
### What are Milestones?
Milestones in QA Sphere are significant points or stages in your project's timeline. They help you:
* Organize and group related test runs
* Track progress towards specific project goals or releases
* Manage deadlines and prioritize testing efforts
For example, you might create milestones like "Version 1.0 Release", "Q4 Security Audit", or "New Feature Beta Testing". By associating test runs with milestones, you can easily monitor testing progress for each important phase of your project.
### Test Run Flexibility Options
When creating a test run, you have two options for managing how updates to test cases are handled. Choosing the right option can improve test management efficiency:
1. **User Selection**:
* Manually select test cases from the library, using filters for folders, priority, or tags to find exactly what you need.
* **Best for**: Full control over which test cases are included, enabling you to pick specific cases based on criteria like priority, tags, or folder organization.
2. **Live**:
* The test run dynamically includes test cases that match your query, updating automatically as cases are added or modified in the library.
* **Best for**: Projects with frequent updates, ensuring that the test run always includes the latest test cases.
**Choosing the Right Option**:
* **User Selection** is the default and offers full control, letting you see and lock in the specific test cases to include. This option is ideal if your test cases are relatively stable and unlikely to change.
* If you're testing a rapidly evolving product, **Live** might be preferable, as it ensures the test run always reflects the latest cases.
> Note: The **User Selection** option includes a ‘Fixed Version’ setting, which prevents automatic updates to test cases if there are no results.
### Adding Test Cases
To add test cases to your test run:
* **User Selection**: Click **Select Test Cases** and choose the specific test cases you want to include.
* **Live**: In the **Create Test Run** form, click **Add Folder**. Select the folders and apply any additional filters to include the desired test cases automatically.
When setting up your test run, consider the following:
* **Scope**: Carefully select which test cases to include based on the goals of this particular test run.
* **Responsibility**: Assign the test run to the team member best suited to oversee its execution.
* **Timing**: Choose the appropriate milestone to ensure the test run aligns with your project timeline.
* **Flexibility**: Select the option that best fits how you want to handle test case updates for this run.
## Executing a Run as a Team
Test runs are **multiplayer**: several testers can work in the same run at the same time. Results synchronize in real time, participants' presence is visible, and the run's progress updates live as results come in.
This changes how you can split a large run: rather than carving the suite into one run per tester, put everyone in a single run and let them work through it together. The assignee remains the person accountable for the run overall, but they are not the only one who can record results.
A run's activity time updates when results are added, not on every edit. Runs that have not been executed yet therefore sort by creation time, which keeps a freshly created run from jumping to the top of the list every time someone adjusts it.
## Automated Runs
Runs created through the [public API](/docs/api/run) or the [CLI](/docs/cli) — typically by a CI pipeline uploading results — are marked with an **automation icon** in the Test Runs list, so automated runs are distinguishable from manual ones at a glance.
Automated runs can also carry **run logs**. When your pipeline uploads logs alongside the results, they appear in an information block above the test cases on the run page, which you can expand to read in full. This puts the CI output next to the failures it explains instead of in a separate build log.
See [Result Upload](/docs/integrations/result-upload) for uploading JUnit XML, Playwright JSON, or Allure results into a run.
## Test Runs and Test Plans
When you need the same suite executed several times in parallel — one run per browser, environment, or device — group the runs into a [test plan](https://qasphere.com/docs/tms/test-plans) instead of creating them separately. A plan keeps the configurations, assignments, and test case selections together and lets you track the whole cycle as one unit.
By thoughtfully configuring your test runs, you can streamline your quality assurance process, improve collaboration among team members, and enhance the overall reliability of your software products.
---
# Overview
URL: /docs/tms
## What is QA Sphere?
QA Sphere is a **Test Management System (TMS)**, which is a specialized software tool designed to help organizations plan, organize, execute, and track their software testing efforts. It serves as a central repository for test cases, test results, and related documentation, enabling teams to manage the entire testing lifecycle more effectively.
## Why use a Test Management Systems?
Test Management Systems play a crucial role in software development for several reasons:
1. **Organized Testing Process**: They provide a structured approach to testing, ensuring that all aspects of the software are thoroughly evaluated.
2. **Improved Collaboration**: TMSs facilitate better communication between testers, developers, and other stakeholders by centralizing information.
3. **Traceability**: They allow teams to track the relationship between requirements, test cases, and defects, ensuring comprehensive coverage.
4. **Efficiency**: By automating many administrative tasks, TMSs save time and reduce the likelihood of human error.
5. **Reporting and Analytics**: These systems offer insights into the testing process, helping teams identify bottlenecks and areas for improvement.
## How to use QA Sphere TMS?
The typical workflow for using QA Sphere includes:
1. **Test Case Creation**: QA teams develop and store test cases in QA Sphere, often categorizing them by feature, priority, or test type. Cases can be written by hand or generated in bulk with [AI](https://qasphere.com/docs/tms/ai-features) from a specification.
2. **Test Planning**: Teams create test runs and select relevant test cases for upcoming releases or sprints, grouping related runs into [test plans](https://qasphere.com/docs/tms/test-plans) when the same suite has to be executed across several browsers or environments.
3. **Test Execution**: Testers run the selected tests and record results directly in the system, several people working in the same run at once. Automated suites push their results in from CI.
4. **Defect Tracking**: When issues are found, they are logged in your issue tracker and linked to the relevant test case, without leaving QA Sphere.
5. **Reporting**: Managers and stakeholders use built-in reporting tools to monitor testing progress and make informed decisions.
## Why QA Sphere?
QA Sphere is a simple, straight-forward and fully functional Test Management System that embodies these principles while offering clean design and additional features to enhance the testing process:
* **Test Cases Management**: A structured library for organizing, categorizing, and prioritizing test cases, with folders, tags, requirements, custom fields, shared steps, and parameterized templates.
* **AI Built In**: Generate test cases in bulk, ask a [conversational assistant](https://qasphere.com/docs/tms/ai-features) about your library, find and merge duplicates, and steer all of it with workspace-wide AI rules.
* **Advanced Test Runs**: Detailed test runs built from complex queries to target specific areas of an application, executed by [several testers simultaneously](https://qasphere.com/docs/test-run-configuration#executing-a-run-as-a-team) with results syncing in real time.
* **Test Plans**: Group related runs into a [plan](https://qasphere.com/docs/tms/test-plans) to execute and track a whole release cycle as one unit.
* **Reporting**: An [Overview dashboard](/docs/reports-overview) plus eight configurable reports covering results, effort, duration, flakiness, requirement traceability, and automation coverage.
* **Integration Capabilities**: Native integrations with Jira, GitHub, Linear, and Slack; GitLab, Notion, Trello, YouTrack and others through the [Custom Issue Tracker](/docs/custom-issue-trackers), which works with any tracker you can describe with a URL pattern; plus [webhooks](/docs/webhooks) for everything else.
* **Automation-Friendly**: A [REST API](/docs/api/api_intro), a [CLI](/docs/cli) that uploads JUnit, Playwright, and Allure results from any CI system, and an [MCP server](/docs/integrations/mcp) that connects AI assistants directly to your test data.
* **Enterprise Controls**: [SAML SSO](/docs/saml), [SCIM provisioning](/docs/scim), two-factor authentication, IP allow lists, and a SIEM-ready audit log.
* **User-Friendly Interface**: Its clean, minimalistic design ensures ease of use for both QA specialists and developers, with light and dark themes.
* **Data Management**: Effortless import and export, including CSV and built-in importers for other test management systems.
By leveraging these features, development teams can streamline their QA processes, improve software quality, and ultimately deliver more reliable products to their users.
## Where to Start
* [Quick Start](https://qasphere.com/docs/quick-start) — create a project, add test cases, and run your first test run
* [Test Run Configuration](https://qasphere.com/docs/test-run-configuration) — the options behind test runs, in depth
* [Test Plans](https://qasphere.com/docs/tms/test-plans) — organize multiple runs into a release cycle
* [AI Features](https://qasphere.com/docs/tms/ai-features) — what the AI can do and how to steer it
---
# Audit Logs
URL: /docs/api/audit_logs
The audit logs endpoint allows administrators to retrieve security and activity events for compliance and monitoring purposes.
## List Audit Logs
`GET /api/public/v0/audit-logs`
Returns a paginated list of audit log events. This endpoint uses cursor-based pagination for efficient retrieval of large datasets.
### Authentication
Requires an API key with Admin role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Restricted API Keys
You can create API keys that are restricted to only access this endpoint by naming them with the `SIEM-LOG-ONLY` prefix. This is useful for SIEM integrations or third-party services that only need audit log access.
For example, an API key named `SIEM-LOG-ONLY-splunk` or `SIEM-LOG-ONLY-datadog` will:
* Be allowed to access `GET /api/public/v0/audit-logs`
* Be blocked from accessing all other API endpoints (returns `403 Forbidden`)
This provides a security best practice of least-privilege access for audit log integrations.
### Subscription Requirements
This endpoint is only available on plans with the **Advanced Auth** feature (Business and Enterprise plans). Requests from tenants without this feature will receive a `402 Payment Required` response.
### Query Parameters
| Parameter | Type | Required | Description | Default |
| --------- | ------- | -------- | ------------------------------------------------------------------------------------- | ------- |
| `after` | integer | No | Cursor for pagination. Returns events with ID greater than this value. | 0 |
| `count` | integer | No | Number of events to return per page. Must be between 1 and 1000. Omit to use default. | 100 |
### Response Format
Status: 200 OK
```typescript
{
after: number // Cursor value for next page (last event ID in this response)
count: number // Number of events returned in this response
events: Array<{
id: number // Unique event identifier
user: {
// User who performed the action (null for system events)
id: number // User ID
name: string // User's display name
email: string // User's email address
} | null
action: string // Action type (see Action Types below)
ip: string // IP address of the request
userAgent: string // User agent string
createdAt: string // ISO 8601 timestamp
meta?: object // Additional context about the action (see Action Types below)
}>
}
```
### Action Types
The `meta` field provides additional context about the action. It is omitted from the response when empty.
For authentication failure actions, `user` identifies the account associated with the attempted credential. It does not mean the request successfully authenticated as that user. The `reason` and `flow` meta fields describe why authentication failed and which authentication flow was involved.
| Action | Description | Meta Fields |
| ----------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `2fa_disable` | Two-factor authentication disabled | |
| `2fa_enable` | Two-factor authentication enabled | |
| `archive_project` | Project was archived | `project_id`, `project_code`, `project_title` |
| `auth.2fa_failed` | Two-factor authentication failed | `reason`, `flow` |
| `auth.api_key_failed` | API key authentication failed | `reason`, `flow`, `api_key_id`, `api_key_name` |
| `auth.google_login_failed` | Google login failed | `reason`, `flow` |
| `auth.ip_or_user_agent_changed` | IP address or user agent changed during session | |
| `auth.oauth_token_failed` | OAuth token authentication failed | `reason`, `flow`, `oauth_authorization_id` |
| `auth.other_sessions_revoked` | All other sessions were revoked | `count` (active, non-staff sessions revoked) |
| `auth.password_login_failed` | Password login failed | `reason`, `flow` |
| `auth.password_verification_failed` | Password verification failed | `reason`, `flow` |
| `auth.saml_login_failed` | SAML login failed | `reason`, `flow` |
| `auth.session_failed` | Session authentication failed | `reason`, `flow`, `source` |
| `auth.session_revoked` | Session was revoked | `session_id`, `ip`, and `user_agent` of the revoked session |
| `cancel_invite` | User invitation was cancelled | `invited_email`, `invited_role` |
| `delete_project` | Project was deleted | `project_id`, `project_code`, `project_title` |
| `email_change` | User changed their email address | `old` (previous email), `new` (new email) |
| `integration.created` | Issue tracker integration was created | `integration_id`, `integration_title`, `integration_type`, plus type-specific fields: `new_url` and `view_url` (custom), `account` (GitHub), `email` and `url` (Jira), `organization_key` (Linear) |
| `integration.deleted` | Issue tracker integration was deleted | `integration_id`, `integration_title`, `integration_type`, `linked_project_count` |
| `integration.project_linked` | Project was linked to an issue tracker integration | `integration_id`, `integration_title`, `integration_type`, `project_id`, `project_code`, `project_title`, plus relation-config fields per integration type: `github_repo` (GitHub), `jira_project_id` and `jira_project_name` (Jira), `linear_team_id` and `linear_team_name` (Linear). When the project was previously linked, the prior config is included with a `previous_` prefix (e.g., `previous_integration_id`, `previous_integration_title`, `previous_github_repo`) |
| `integration.project_unlinked` | Project was unlinked from an issue tracker integration | Same as `integration.project_linked` but without the `previous_` fields |
| `integration.updated` | Issue tracker integration configuration was updated | `integration_id`, `integration_title`, `integration_type`, plus only the fields that changed (from the same set as `integration.created`) |
| `invite_user` | User was invited to the organization | `invited_email`, `invited_role` |
| `login` | User logged in | |
| `logout` | User logged out | |
| `oauth.authorization_created` | OAuth authorization granted (e.g., for [QAS CLI](https://github.com/Hypersequent/qas-cli)) | `grant_type`, `client_id`, `authorization_id` |
| `oauth.authorization_revoked` | OAuth authorization revoked | `client_id`, `authorization_id` |
| `password_change` | User changed their password | |
| `password_reset` | Password was reset | |
| `register` | New user registered | |
| `request_password_reset` | Password reset was requested | |
| `scim.user_create` | User provisioned via SCIM | `userName`, `apiKeyId`, `externalId` (when set on the user) |
| `scim.user_deactivate` | User suspended via SCIM | Same as `scim.user_create` |
| `scim.user_reactivate` | User unsuspended via SCIM | Same as `scim.user_create` |
| `scim.user_update` | User attributes updated via SCIM | Same as `scim.user_create` |
| `slack_disconnect` | Slack workspace was disconnected | |
| `slack_install` | Slack workspace was connected | `team_id`, `team_name`, `domain` |
| `slack_link_user` | Slack user was linked to a QA Sphere user | `team_id`, `slack_user_id`, `source` (`oauth_install` when auto-linked during install) |
| `slack_subscribe` | Slack channel subscribed to project events | `team_id`, `channel_id`, `channel_name`, `project_id`, `project_code`, `event_types` |
| `slack_unlink_user` | Slack user was unlinked from a QA Sphere user | |
| `slack_unsubscribe` | Slack channel unsubscribed from project events | `team_id`, `channel_id`, `channel_name`, `project_id`, `project_code`, `event_types`, `remaining` |
| `unarchive_project` | Project was unarchived | `project_id`, `project_code`, `project_title` |
| `webhook.created` | Webhook was created | `webhook_id`, `webhook_name`, `endpoint`, `enabled`, `event_types`, `allow_all_projects`, `allowed_project_count` (when `allow_all_projects` is false). `secret`, `headers`, and `payload` appear as `****` when set (values are redacted) |
| `webhook.deleted` | Webhook was deleted | Same as `webhook.created` |
| `webhook.updated` | Webhook configuration was updated | `webhook_id`, `webhook_name`, plus only the fields that changed (from the same set as `webhook.created`; secret/headers/payload changes appear as `****`) |
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/audit-logs?count=50"
```
### Example Response
```json
{
"after": 156,
"count": 3,
"events": [
{
"id": 154,
"user": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
"action": "login",
"ip": "192.168.1.100",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
"createdAt": "2025-01-28T10:30:00Z"
},
{
"id": 155,
"user": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
"action": "archive_project",
"ip": "192.168.1.100",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
"createdAt": "2025-01-28T11:00:00Z",
"meta": {
"project_id": "1CKgJ5HMU_2apSDSQWRw6Ys",
"project_code": "PROJ",
"project_title": "My Project"
}
},
{
"id": 156,
"user": {
"id": 2,
"name": "Jane Smith",
"email": "jane@example.com"
},
"action": "email_change",
"ip": "192.168.1.101",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"createdAt": "2025-01-28T12:00:00Z",
"meta": {
"old": "jane.old@example.com",
"new": "jane@example.com"
}
}
]
}
```
### Pagination
This endpoint uses cursor-based pagination for efficient retrieval:
1. Make an initial request without the `after` parameter to get the first page
2. Use the `after` value from the response as the `after` parameter for the next request
3. Continue until you receive fewer events than requested (end of data)
#### Pagination Example
```bash
# First page
curl -H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/audit-logs?count=100"
# Response: { "after": 100, "count": 100, "events": [...] }
# Second page (using after value from previous response)
curl -H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/audit-logs?after=100&count=100"
# Response: { "after": 156, "count": 56, "events": [...] }
# count < 100 indicates this is the last page
```
When `after` is 0 or omitted, the response starts from the first event of the current month. If no events exist for the current month, an empty result is returned. The `after` value in the response equals the input `after` value when there are no more events to return.
### Error Responses
| Status Code | Description |
| ----------- | --------------------------------------------- |
| 400 | Invalid parameters (e.g., count > 1000) |
| 401 | Invalid or missing API key |
| 402 | Subscription plan lacks Advanced Auth feature |
| 403 | Insufficient permissions (non-admin access) |
| 500 | Internal server error |
This endpoint enables you to:
* Monitor user authentication activity
* Track security-related changes (2FA, password changes)
* Audit project lifecycle events
* Integrate with SIEM systems for compliance
* Build custom security dashboards
---
# Folders
URL: /docs/api/folders
The folders endpoint allows you to retrieve the folder structure of test cases within a project.
## List Project Folders
`GET /api/public/v0/project/{project_id}/tcase/folders`
Returns a hierarchical list of all folders in the project. This endpoint is useful for getting folder IDs and understanding the test case organization structure.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Query Parameters
| Parameter | Type | Description | Example |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| `offset` | number | Number of rows to skip before returning results. Combine with `limit` for offset-based pagination. | `offset=10` |
| `limit` | number | Maximum number of items to return (0–5000). May be `0` to return only the total count (no rows). | `limit=10` |
| `page` | number | **Deprecated** — use `offset` instead. 1-based page number. Ignored when `offset` is set. If `limit` is omitted, a default of 10 is applied. | `page=1` |
| `sortField` | string | Field to sort by. Allowed values: - `id` - `project_id` - `title` - `pos` - `parent_id` - `created_at` - `updated_at` | `sortField=title` |
| `sortOrder` | string | Sort direction (requires `sortField`). Allowed values: `asc`, `desc` | `sortOrder=desc` |
### Example Request
#### Skip the first 10 folders and return the next 10 — or, return 10 folders starting from 0-based index 10
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://company.qasphere.com/api/public/v0/project/BD/tcase/folders?offset=10&limit=10&sortField=title&sortOrder=desc
```
### Response
Status: 200 OK
```typescript
{
total: number, // Total number of items available
offset?: number, // The offset that was applied (present when pagination was applied)
limit?: number, // The limit that was applied (present when pagination was applied)
page?: number, // **Deprecated**. Echo of the page that was requested (present only if `page` was used in the request)
data: Array<{ // Array of folder objects
id: number // Unique identifier for the folder
title: string // Name of the folder
comment: html // Additional notes or description
pos: number // Position of the folder among its siblings
parentId: number // ID of the parent folder (0 for root folders)
projectId: string // ID of the project the folder belongs to
}>
}
```
### Example Response
```json
{
"total": 12,
"offset": 0,
"limit": 2,
"data": [
{
"id": 11866,
"parentId": 11844,
"title": "Welcome",
"comment": "",
"projectId": "1CGeNZsqU_BRPFrugwAVDs3",
"pos": 4
},
{
"id": 11855,
"parentId": 11844,
"title": "Today's menu",
"comment": "",
"projectId": "1CGeNZsqU_BRPFrugwAVDs3",
"pos": 3
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project not found |
Use the folder IDs returned by this endpoint when creating or updating test runs to specify which folders should be included in the run.
## Bulk Upsert Folders
`POST /api/public/v0/project/{project_id}/tcase/folder/bulk`
Creates or updates multiple folders in a single request using folder path hierarchies. This endpoint automatically creates nested folder structures and updates existing folders' comments.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Request Body
```typescript
{
folders: Array<{
path: string[] // Array of folder names representing the hierarchy
comment?: html // Additional notes or description for the leaf folder.
}>
}
```
### Response
Status: 200 OK
```typescript
{
ids: Array> // Each array represents the full folder path hierarchy in the request as an array of folder IDs, from root to leaf
}
```
**Details:**
* The `ids` field is an array where each item corresponds to one input folder path.
* Each inner array contains folder IDs that map 1:1 to the specified folder path in the request.
* For example, if your path is `["Frontend", "Components", "Navigation"]`, the result could be `[12, 13, 14]` where `12` is "Frontend", `13` is "Components", `14` is "Navigation".
* Newly created folders will always get new IDs; existing folders return their original IDs.
* The order of returned arrays matches the order of the input `folders` in the request.
### Example Request
```bash
curl -X POST \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"folders": [
{
"path": ["Frontend", "Components", "Navigation"],
"comment": "Tests for navigation components
"
},
{
"path": ["Frontend", "Components", "Forms"],
"comment": "Form validation and interaction tests
"
},
{
"path": ["Backend", "API", "Authentication"],
"comment": "Authentication endpoint tests
"
}
]
}' \
https://company.qasphere.com/api/public/v0/project/BD/tcase/folder/bulk
```
### Example Response
Status: 200 OK
```json
{
"ids": [
[12, 13, 14],
[12, 13, 15],
[16, 17, 18]
]
}
```
### Behavior
* **Creates nested structure**: Automatically creates all parent folders in the path if they don't exist
* **Updates existing folders**: If a folder path already exists, only the comment is updated
* **Idempotent**: Running the same request multiple times produces the same result
* **Preserves hierarchy**: Maintains proper parent-child relationships between folders
* **Position assignment**: New folders are positioned automatically within their parent
### Example Folder Creation
Given the request above, the following folder structure would be created:
```
Frontend/
├── Components/
│ ├── Navigation/ (comment: "Tests for navigation components")
│ └── Forms/ (comment: "Form validation and interaction tests")
Backend/
└── API/
└── Authentication/ (comment: "Authentication endpoint tests")
```
### Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------- |
| 400 | Invalid request body or folder path format |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project not found |
| 500 | Internal server error |
### Validation Rules
* Each folder name in the path must be 1-255 characters long
* Folder names cannot be empty strings
* The `path` array cannot be empty
* folder comment should be in html format
This endpoint is particularly useful for:
* Setting up folder structures during project initialization
* Bulk importing test case organization from external systems
* Synchronizing folder structures across projects
* Automating test case creation
The endpoint only updates the `comment` field for existing folders. Other properties like position and parent relationships are preserved.
---
# Milestones
URL: /docs/api/milestone
The milestones endpoint allows you to retrieve all milestones associated with a project. Milestones help organize and track test runs across different versions or phases of your project.
## List Project Milestones
`GET /api/public/v0/project/{project_id}/milestone`
Returns a list of all milestones in the project. This endpoint is particularly useful when you need milestone IDs for creating or cloning test runs.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Query Parameters
| Parameter | Type | Description | Example |
| ---------- | ---- | ------------------------------------------- | --------------- |
| `archived` | bool | Fetch only archived/non-archived milestones | `archived=true` |
### Response
Status: 200 OK
```typescript
{
milestones: Array<{
// Array of milestone objects
id: number // Unique identifier for the milestone
title: string // Name of the milestone
createdAt: string // Creation timestamp in ISO 8601 format
updatedAt: string // Last update timestamp in ISO 8601 format
archivedAt: string | null // Timestamp when the milestone was archived in ISO 8601 format
}>
}
```
### Example Request
#### Fetch all milestones
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/milestone
```
#### Fetch only non-archived milestones
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/milestone?archived=false
```
### Example Response
```json
{
"milestones": [
{
"id": 1,
"title": "Version 0.9",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"archivedAt": null
},
{
"id": 2,
"title": "Version 1.0",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"archivedAt": "2024-02-01T00:00:00.000Z"
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | ---------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project not found |
| 500 | Internal server error during milestone listing |
## Create Milestone
`POST /api/public/v0/project/{project_id}/milestone`
Creates a new milestone in the project. Milestones help organize test runs by version or project phase.
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Request Body
```typescript
{
title: string // Required: Name of the milestone (max 255 chars)
}
```
### Response
Status: 201 Created
```typescript
{
id: number // The ID of the newly created milestone
}
```
### Example Request
#### Using cURL
```bash
curl \
-X POST \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"title": "Version 2.0"
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/milestone
```
#### Request Body (JSON)
```json
{
"title": "Version 2.0"
}
```
#### Minimal Request Example
```json
{
"title": "Quick Fix Release"
}
```
### Example Response
```json
{
"id": 42
}
```
### Validation Rules
* **Title**: Required, must be unique within the project, maximum 255 characters
### Error Responses
| Status Code | Description |
| ----------- | ----------------------------------------------- |
| 400 | Invalid request body or validation error |
| 401 | Invalid or missing API key |
| 403 | Duplicate milestone title exists in the project |
| 404 | Project not found |
| 500 | Internal server error during milestone creation |
After creating a milestone, you can use its ID when creating test runs to associate them with this specific project version or phase.
---
# Test Plans
URL: /docs/api/plan
The plans endpoints allow you to create and manage test plans in your project. A test plan is a collection of test runs that are organized and executed together, typically for a specific milestone or release. Write operations (create/update/delete) can only be performed by users with role test runner or with higher privileges.
## Test Plan Overview
A test plan consists of:
* **Title and Description**: Basic information about the plan
* **Milestone**: Optional association with a project milestone
* **Runs**: One or more test runs, each containing a set of test cases
Each run within a plan:
* Has its own title
* Can be assigned to a specific user
* Can be associated with a configuration
* Contains exactly one query plan that specifies the test cases to include
## Create New Test Plan
`POST /api/public/v0/project/{project_id}/plan`
Creates a new test plan in the project with one or more test runs.
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Request Body
```typescript
{
title: string // Required: Plan title (max 255 characters)
description?: html // Optional: Plan description
milestoneId?: number // Optional: Associated milestone
runs: Array<{ // Required: List of runs in the plan
title: string // Required: Run title (max 255 characters)
assignmentId?: number // Optional: Assigned user ID
configurationId?: string // Optional: Configuration ID
queryPlans: Array<{ // Required: Exactly one query plan per run
tcaseIds: Array // Required: Test case IDs to include
}>
}>
}
```
**Field Constraints**
* `title`: Must be 1-255 characters long and unique within the milestone (or among plans without milestones)
* `description`: HTML content that will be sanitized
* `milestoneId`: The milestone must belong to the project and must not be archived
* `runs`: Must contain at least one run
* Each run must have exactly one query plan
* `tcaseIds`: Must be valid test case IDs belonging to the project
* `assignmentId`: Must be an active user with permissions above Viewer role
* Test case IDs must be standalone or filled types (not templates)
### Response
Status: 201 Created
```json
{
"id": 5
}
```
The response contains the ID of the newly created test plan.
### Error Responses
| Status Code | Description |
| ----------- | ---------------------------------------------------- |
| 400 | Invalid request data or validation errors |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions (requires Test Runner role) |
| 404 | Project not found |
| 409 | Conflict - Plan title already exists in milestone |
| 500 | Internal server error |
## Common Use Cases
### Cross-Browser Testing
Create a test plan to run the same test suite across different browsers:
```json
{
"title": "Release 3.0 Browser Compatibility",
"description": "Browser compatibility testing for Release 3.0
",
"milestoneId": 15,
"runs": [
{
"title": "Chrome Tests",
"configurationId": "chrome_latest",
"assignmentId": 3,
"queryPlans": [
{
"tcaseIds": [
"1CEPaUhgH_Tvt2LZygwVRQa",
"1CAPaUhgH_Tvt2LZygwVRTb",
"1DAPaUhgH_Tvt2LZygwVRSc",
"1EEPaUhgH_Tvt2LZygwVRLm",
"1FEPaUhgH_Tvt2LZygwVRNn"
]
}
]
},
{
"title": "Firefox Tests",
"configurationId": "firefox_latest",
"assignmentId": 3,
"queryPlans": [
{
"tcaseIds": [
"1CEPaUhgH_Tvt2LZygwVRQa",
"1CAPaUhgH_Tvt2LZygwVRTb",
"1DAPaUhgH_Tvt2LZygwVRSc",
"1EEPaUhgH_Tvt2LZygwVRLm",
"1FEPaUhgH_Tvt2LZygwVRNn"
]
}
]
},
{
"title": "Safari Tests",
"configurationId": "safari_latest",
"assignmentId": 3,
"queryPlans": [
{
"tcaseIds": [
"1CEPaUhgH_Tvt2LZygwVRQa",
"1CAPaUhgH_Tvt2LZygwVRTb",
"1DAPaUhgH_Tvt2LZygwVRSc",
"1EEPaUhgH_Tvt2LZygwVRLm",
"1FEPaUhgH_Tvt2LZygwVRNn"
]
}
]
},
{
"title": "Edge Tests",
"configurationId": "edge_latest",
"assignmentId": 3,
"queryPlans": [
{
"tcaseIds": [
"1CEPaUhgH_Tvt2LZygwVRQa",
"1CAPaUhgH_Tvt2LZygwVRTb",
"1DAPaUhgH_Tvt2LZygwVRSc",
"1EEPaUhgH_Tvt2LZygwVRLm",
"1FEPaUhgH_Tvt2LZygwVRNn"
]
}
]
}
]
}
```
### Multi-Platform Testing
Test the same application across different platforms and devices:
```json
{
"title": "Mobile App Platform Testing",
"description": "Testing mobile app across different platforms
",
"runs": [
{
"title": "iOS 17 - iPhone 15",
"configurationId": "ios17_iphone15",
"assignmentId": 4,
"queryPlans": [
{
"tcaseIds": [
"1GEPaUhgH_Tvt2LZygwVROo",
"1HEPaUhgH_Tvt2LZygwVRPp",
"1IEPaUhgH_Tvt2LZygwVRQq",
"1JEPaUhgH_Tvt2LZygwVRRr",
"1KEPaUhgH_Tvt2LZygwVRSs"
]
}
]
},
{
"title": "iOS 17 - iPad Pro",
"configurationId": "ios17_ipad_pro",
"assignmentId": 4,
"queryPlans": [
{
"tcaseIds": [
"1GEPaUhgH_Tvt2LZygwVROo",
"1HEPaUhgH_Tvt2LZygwVRPp",
"1IEPaUhgH_Tvt2LZygwVRQq",
"1JEPaUhgH_Tvt2LZygwVRRr",
"1KEPaUhgH_Tvt2LZygwVRSs"
]
}
]
},
{
"title": "Android 14 - Pixel 8",
"configurationId": "android14_pixel8",
"assignmentId": 5,
"queryPlans": [
{
"tcaseIds": [
"1GEPaUhgH_Tvt2LZygwVROo",
"1HEPaUhgH_Tvt2LZygwVRPp",
"1IEPaUhgH_Tvt2LZygwVRQq",
"1JEPaUhgH_Tvt2LZygwVRRr",
"1KEPaUhgH_Tvt2LZygwVRSs"
]
}
]
},
{
"title": "Android 14 - Samsung Galaxy",
"configurationId": "android14_galaxy",
"assignmentId": 5,
"queryPlans": [
{
"tcaseIds": [
"1GEPaUhgH_Tvt2LZygwVROo",
"1HEPaUhgH_Tvt2LZygwVRPp",
"1IEPaUhgH_Tvt2LZygwVRQq",
"1JEPaUhgH_Tvt2LZygwVRRr",
"1KEPaUhgH_Tvt2LZygwVRSs"
]
}
]
}
]
}
```
### Regression Testing Across Environments
Run regression tests across different deployment environments:
```json
{
"title": "Regression Test Suite - All Environments",
"description": "Full regression testing across staging and production-like environments
",
"runs": [
{
"title": "Regression Tests - Staging US",
"configurationId": "staging_us_east",
"assignmentId": 3,
"queryPlans": [
{
"tcaseIds": [
"1LEPaUhgH_Tvt2LZygwVRTt",
"1MEPaUhgH_Tvt2LZygwVRUu",
"1NEPaUhgH_Tvt2LZygwVRVv",
"1OEPaUhgH_Tvt2LZygwVRWw",
"1PEPaUhgH_Tvt2LZygwVRXx",
"1QEPaUhgH_Tvt2LZygwVRYy"
]
}
]
},
{
"title": "Regression Tests - Staging EU",
"configurationId": "staging_eu_west",
"assignmentId": 4,
"queryPlans": [
{
"tcaseIds": [
"1LEPaUhgH_Tvt2LZygwVRTt",
"1MEPaUhgH_Tvt2LZygwVRUu",
"1NEPaUhgH_Tvt2LZygwVRVv",
"1OEPaUhgH_Tvt2LZygwVRWw",
"1PEPaUhgH_Tvt2LZygwVRXx",
"1QEPaUhgH_Tvt2LZygwVRYy"
]
}
]
},
{
"title": "Regression Tests - Staging APAC",
"configurationId": "staging_apac",
"assignmentId": 5,
"queryPlans": [
{
"tcaseIds": [
"1LEPaUhgH_Tvt2LZygwVRTt",
"1MEPaUhgH_Tvt2LZygwVRUu",
"1NEPaUhgH_Tvt2LZygwVRVv",
"1OEPaUhgH_Tvt2LZygwVRWw",
"1PEPaUhgH_Tvt2LZygwVRXx",
"1QEPaUhgH_Tvt2LZygwVRYy"
]
}
]
}
]
}
```
### Component-Based Testing
Create test plans with different test cases for distinct components or modules:
```json
{
"title": "Sprint 23 Feature Test Plan",
"description": "Test plan for different components developed in Sprint 23
",
"runs": [
{
"title": "User Authentication Module",
"assignmentId": 3,
"queryPlans": [{ "tcaseIds": ["1CEPaUhgH_Tvt2LZygwVRQa", "1CAPaUhgH_Tvt2LZygwVRTb"] }]
},
{
"title": "Payment Processing Module",
"assignmentId": 4,
"queryPlans": [{ "tcaseIds": ["1EEPaUhgH_Tvt2LZygwVRLm", "1FEPaUhgH_Tvt2LZygwVRNn"] }]
},
{
"title": "Notification Service",
"assignmentId": 5,
"queryPlans": [{ "tcaseIds": ["1GEPaUhgH_Tvt2LZygwVROo", "1HEPaUhgH_Tvt2LZygwVRPp"] }]
}
]
}
```
**Best Practices**
* **Configuration-Based Runs**: Most test plans will have runs with similar titles and identical test cases, differing only in configurations (e.g., browsers, devices, environments)
* **Consistent Naming**: Use a consistent naming pattern for runs testing the same functionality across configurations (e.g., "Feature X - Chrome", "Feature X - Firefox")
* **Same Test Cases**: Reuse the same test case IDs across runs when testing across different configurations
* **Assign by Expertise**: When testing across platforms, assign runs based on platform expertise rather than feature expertise
* **Link to Milestones**: Associate plans with milestones for better release tracking
* **Exception Cases**: Only create runs with different test cases when testing distinct components or modules
**Limitations**
* Each run must have exactly one query plan
* Only User selection test runs are supported (tcaseIds must be specified). See [Types of Runs](https://qasphere.com/docs/api/run#types-of-runs) for more details.
* Dynamic folder/tag-based selection is not available for plans
* Test plans cannot be cloned via the public API (planned for future release)
* Updating test plans is not yet available via the public API
## Related Resources
* [Runs](https://qasphere.com/docs/api/run) - Learn about individual test runs
* [Test Cases](https://qasphere.com/docs/api/tcases) - Manage test cases
* [Milestones](https://qasphere.com/docs/api/milestone) - Work with project milestones
* [Results](https://qasphere.com/docs/api/result) - Add results to test cases in runs
---
# Projects
URL: /docs/api/projects
The projects endpoint allows you to retrieve projects in your account.
## Authentication
Project visibility will depend if the user has proper access to the project. If you are the owner or an admin, you may grant access to users to a project
by going to your QA Sphere account, then go to the Members page in settings to grant access to the user.
## List Projects
`GET /api/public/v0/project`
Returns a list of all projects.
### Response
Status: 200 OK
```typescript
{
projects: Array<{
// A list of projects
id: string // Unique identifier for the project
code: string // User specified unique identifier for the project
title: string // Name of the project
description: html // Description of the project (Deprecated: use overviewDescription)
overviewTitle: string // Overview title shown in overview page of the project
overviewDescription: html // Overview description shown in overview page of the project
links: Array<{
// A list of links that is shown in the overview page of the project
url: string // URL of the link
text: string // Displayed text of the link
}>
createdAt: Date // Date when the project is created
updatedAt: Date // Date when project information was last updated
archivedAt: Date | null // Date when the project has been archived
}>
}
```
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project
```
### Example Response
```json
{
"projects": [
{
"id": "1CJo8oDjj_vkGo2rQAdzz4F",
"code": "BD",
"title": "Bistro Delivery",
"description": "Welcome to the Bistro Delivery example project. This project showcases a typical food ordering website with features like a menu, shopping cart, and order process. We've included basic test cases, organized by type, tags, and priorities, along with test runs to demonstrate how QA Sphere can streamline your testing workflow.
",
"overviewTitle": "Bistro Delivery - Example",
"overviewDescription": "Welcome to the Bistro Delivery example project. This project showcases a typical food ordering website with features like a menu, shopping cart, and order process. We've included basic test cases, organized by type, tags, and priorities, along with test runs to demonstrate how QA Sphere can streamline your testing workflow.
",
"links": [
{
"text": "Bistro Delivery Site",
"url": "https://hypersequent.github.io/bistro/"
},
{
"text": "Automation Tests",
"url": "https://github.com/Hypersequent/bistro-e2e"
},
{
"text": "QA Sphere CLI Tool",
"url": "https://github.com/Hypersequent/qas-cli"
}
],
"createdAt": "2025-01-02T11:41:19.547371+04:00",
"updatedAt": "2025-01-02T11:41:19.547371+04:00",
"archivedAt": null
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------- |
| 500 | Internal server error during project listing |
## Get Project
`GET /api/public/v0/project/{project_code_or_id}`
Returns the project identified by code or id.
### Response
Status: 200 OK
```typescript
{
id: string // Unique identifier for the project
code: string // User specified unique identifier for the project
title: string // Name of the project
description: html // Description of the project (Deprecated: use overviewDescription)
overviewTitle: string // Overview title shown in overview page of the project
overviewDescription: html // Overview description shown in overview page of the project
links: Array<{
// A list of links that is shown in the overview page of the project
url: string // URL of the link
text: string // Displayed text of the link
}>
createdAt: Date // Date when the project is created
updatedAt: Date // Date when project information was last updated
archivedAt: Date | null // Date when the project has been archived
}
```
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD
```
### Example Response
```json
{
"id": "1CJo8oDjj_vkGo2rQAdzz4F",
"code": "BD",
"title": "Bistro Delivery",
"description": "Welcome to the Bistro Delivery example project. This project showcases a typical food ordering website with features like a menu, shopping cart, and order process. We've included basic test cases, organized by type, tags, and priorities, along with test runs to demonstrate how QA Sphere can streamline your testing workflow.
",
"overviewTitle": "Bistro Delivery - Example",
"overviewDescription": "Welcome to the Bistro Delivery example project. This project showcases a typical food ordering website with features like a menu, shopping cart, and order process. We've included basic test cases, organized by type, tags, and priorities, along with test runs to demonstrate how QA Sphere can streamline your testing workflow.
",
"links": [
{
"text": "Bistro Delivery Site",
"url": "https://hypersequent.github.io/bistro/"
},
{
"text": "Automation Tests",
"url": "https://github.com/Hypersequent/bistro-e2e"
},
{
"text": "QA Sphere CLI Tool",
"url": "https://github.com/Hypersequent/qas-cli"
}
],
"createdAt": "2025-01-02T11:41:19.547371+04:00",
"updatedAt": "2025-01-02T11:41:19.547371+04:00",
"archivedAt": null
}
```
### Error Responses
| Status Code | Description |
| ----------- | --------------------------------------------- |
| 403 | User has no permission to access project |
| 404 | Project not found |
| 500 | Internal server error during project fetching |
## Create Project
`POST /api/public/v0/project`
Creates a new project. Only users with role Admin or Owner are allowed to create a project.
### Request Body
```typescript
{
code: string // Unique project code (2-5 alphanumeric characters)
title: string // Name of the project (max 255 characters)
links?: Array<{ // Optional list of links for the project overview
url: string // URL of the link (max 255 characters)
text: string // Displayed text of the link (max 255 characters)
}>
overviewTitle?: string // Optional overview title (max 255 characters)
overviewDescription?: html // Optional overview description
}
```
### Example Request
```bash
curl -X POST \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"code": "BD",
"title": "Bistro Delivery",
"links": [
{"url": "https://hypersequent.github.io/bistro/", "text": "Bistro Delivery Site"},
{"url": "https://github.com/Hypersequent/bistro-e2e", "text": "Automation Tests"}
],
"overviewTitle": "Bistro Delivery - Example",
"overviewDescription": "Welcome to the Bistro Delivery example project. This project showcases a typical food ordering website with features like a menu, shopping cart, and order process.
"
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project
```
### Response Fields
```typescript
{
id: string // Unique identifier for the project
}
```
### Example Response
Status: 201 Created
```json
{
"id": "1CJo8oDjj_vkGo2rQAdzz4F"
}
```
### Error Responses
| Status Code | Description |
| ----------- | --------------------------------------------- |
| 400 | Invalid project code format |
| 403 | User does not have admin permission |
| 409 | Project with the same title already exists |
| 500 | Internal server error during project creation |
---
# Requirements
URL: /docs/api/requirements
The requirements endpoints allow you to retrieve requirements that are linked to test cases within a project. Requirements help track traceability between test cases and external specifications, user stories, or other documentation.
## About Requirements
Requirements are references to external documentation or specifications that test cases are designed to verify. They consist of:
1. **Text**: A descriptive label for the requirement (1-255 characters)
2. **URL** (optional): A link to the external requirement document or issue tracker
Requirements can be linked to multiple test cases, and a single test case can be linked to multiple requirements. This enables full traceability between your tests and the specifications they validate.
* Requirements can be linked to external issues when a Jira or Linear integration is configured for the project
* Use `include=tcaseCount` to see how many test cases are linked to each requirement
* Requirements without any linked test cases are still returned in the list
## List Requirements
`GET /api/public/v0/project/{project_id}/requirement`
Retrieves all requirements within a project, optionally sorted and with additional fields included.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Query Parameters
All query parameters are optional.
| Parameter | Type | Description | Allowed Values | Example |
| ----------- | ------ | ---------------------------------------------------------------------- | -------------------- | -------------------- |
| `sortField` | string | Field to sort by | `created_at`, `text` | `sortField=text` |
| `sortOrder` | string | Sort order (requires `sortField`; default: `desc`) | `asc`, `desc` | `sortOrder=asc` |
| `include` | string | Include additional fields in the response which are omitted by default | `tcaseCount` | `include=tcaseCount` |
* Use `include=tcaseCount` to see how many test cases are linked to each requirement
* Sorting by `created_at` shows the most recently created requirements first (with `desc`) or oldest first (with `asc`)
* Sorting by `text` provides alphabetical ordering
### Example Request
#### Fetch all requirements
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/requirement
```
#### Fetch all requirements sorted by text in ascending order
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/requirement?sortField=text&sortOrder=asc
```
#### Fetch all requirements with test case count included
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/requirement?include=tcaseCount
```
### Response Fields
```typescript
{
requirements: Array<{
// List of requirement objects
id: string // Unique identifier of the requirement (HQID7 format)
text: string // Descriptive label for the requirement
url: string // URL to the external requirement document (empty string if not set)
integrationLink?: {
// Integration link (only present if linked to Jira or Linear)
type: string // Integration type ("jira" or "linear")
integrationId: string // ID of the integration configuration
issueId: string // Internal issue ID (Jira numeric ID or Linear UUID)
issueTitle: string // Title of the linked issue
issueUrl: string // Full URL to the linked issue
remoteLinkId: string // Remote link/attachment ID in the external system
}
tcaseCount?: number // Number of test cases linked to this requirement (only included if requested)
}>
}
```
### Example Response
```json
{
"requirements": [
{
"id": "1CKgJ5HMU_1VQTDrRJDdDVW",
"text": "User Authentication",
"url": "https://docs.example.com/specs/auth",
"tcaseCount": 5
},
{
"id": "1CKgJ5HMU_2BJje4hdXZHag",
"text": "PROJ-456: Implement password reset functionality",
"url": "https://jira.example.com/browse/PROJ-456",
"integrationLink": {
"type": "jira",
"integrationId": "1CTPNLhFU_rPbCr23CbqftL",
"issueId": "10456",
"issueTitle": "Implement password reset functionality",
"issueUrl": "https://jira.example.com/browse/PROJ-456",
"remoteLinkId": "12345"
},
"tcaseCount": 3
},
{
"id": "1CKgJ5HMU_3apSDSQWRw6Ys",
"text": "Performance Requirements",
"url": ""
}
]
}
```
---
# Results
URL: /docs/api/result
The results endpoint allows you to add results for test cases in runs. Only users with role test runner or with higher privileges, having access to a project can add results.
Each test case result is assigned a status reflecting the outcome of its execution. QA Sphere supports several common statuses: `passed`, `failed`, `blocked`, `skipped`, and `open`. If you require additional statuses, QA Sphere allows you to create up to four custom statuses. These custom statuses can be used in the results as `custom1`, `custom2`, `custom3`, `custom4`. For more information on viewing and updating custom statuses using public APIs, please refer to the [Settings](https://qasphere.com/docs/api/settings) page.
You can also attach links to external issues created in integrations configured for the project. If the corresponding issue ID/key is provided in the meta information, QA Sphere will add a comment on the issue for non-custom integrations (GitHub, Jira, Linear) to create a bi-directional reference:
* **GitHub/Jira**: Issue number (e.g., `"123"`)
* **Linear**: Issue key (e.g., `"PRJ-123"`)
Public result endpoints support integration links only. They do not accept uploaded file attachments.
## Add Result
`POST /api/public/v0/project/{project_id}/run/{run_id}/tcase/{tcase_or_legacy_id}/result`
Add result for a run test case.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `run_id`: The run identifier
* `tcase_or_legacy_id`: The test case identifier (can be one of test case UUID, sequence or legacy ID)
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Request Body
```typescript
{
status: string // Required: Result status ("passed" | "failed" | "blocked" | "skipped" | "open" | "custom1" | "custom2" | "custom3" | "custom4")
comment: html // Required: Comments/observations while executing the test case
timeTaken?: number // Optional: Time taken for executing the test case
links?: Array<{ // Optional: Links to issues on external integration to attach to this result
integrationId: string // Required: Unique identifier of the project integration
url: string // Required: URL of the external issue
text: string // Required: Title of the external issue
meta?: { // Optional: Additional information related to the issue (for non-custom integrations)
id?: string // Optional: Issue ID/key used to add a comment on the external issue linking back to this result
}
}>
}
```
### Response Fields
| Field | Type | Description |
| ----- | -------- | -------------------------------- |
| `id` | `number` | Unique identifier for the result |
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"status": "failed",
"comment": "Login page background color is not correct
",
"links": [{
"integrationId": "1CSWAh3ys_YniqfXepnwT8F",
"url": "https://external-integration/issues/1",
"text": "Login page background color is not correct"
}],
"timeTaken": 60
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase/1/result
```
### Example Response
```json
{
"id": 10
}
```
### Error Responses
| Status Code | Description |
| ----------- | ------------------------------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant or project is archived |
| 404 | Project or test run or test case not found |
| 409 | Test run is closed |
| 500 | Internal server error while adding result |
## Add Multiple Results
`POST /api/public/v0/project/{project_id}/run/{run_id}/result/batch`
Add results for multiple test cases in a run.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `run_id`: The run identifier
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Request Body
```typescript
{
items: Array<{
// Required: List of result items
tcaseId: string // Required: The unique identifier of the test case
status: string // Required: Result status ("passed" | "failed" | "blocked" | "skipped" | "open" | "custom1" | "custom2" | "custom3" | "custom4")
comment: html // Required: Comments/observations while executing the test case
timeTaken?: number // Optional: Time taken for executing the test case
links?: Array<{
// Optional: Links to issues on external integration to attach to this result
integrationId: string // Required: Unique identifier of the external integration
url: string // Required: URL of the external issue
text: string // Required: Title of the external issue
meta?: {
// Optional: Additional information related to the issue (for non-custom integrations)
id?: string // Optional: Issue ID/key used to add a comment on the external issue linking back to this result
}
}>
}>
}
```
### Response Fields
| Field | Type | Description |
| ----- | ---------- | --------------------------------------------------------------------- |
| `ids` | `number[]` | List of IDs for the created results, in the same order as the request |
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"tcaseId": "1CSm3erpq_Ykq6AVPRrLYd1",
"status": "failed",
"comment": "Login page background color is not correct
",
"links": [{
"integrationId": "1CSWAh3ys_YniqfXepnwT8F",
"url": "https://external-integration/issues/1",
"text": "Login page background color is not correct"
}],
"timeTaken": 60
},
{
"tcaseId": "1CSaE4bJE_mHke3r3yJRAgk",
"status": "passed",
"comment": ""
},
{
"tcaseId": "1CSaDwU7T_FKcgke4dVwJNP",
"status": "custom3",
"comment": "Page failed to load
",
"links": [{
"integrationId": "1CSWAh3ys_YniqfXepnwT8F",
"url": "https://external-integration/issues/1",
"text": "Page failed to load"
}]
}
]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/result/batch
```
### Example Response
```json
{
"ids": [11, 12, 13]
}
```
### Error Responses
| Status Code | Description |
| ----------- | ------------------------------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant or project is archived |
| 404 | Project or test run not found |
| 409 | Test run is closed |
| 500 | Internal server error while adding result |
**Validation**
The system validates that the run belongs to the project, test case belongs to the run, the project is not archived and the run is not closed. Attempting to add result which does not satisfy these validations will result in an error.
---
# Runs
URL: /docs/api/run
The runs endpoints allow you to create and manage test executions in your project. You can create new runs, list existing runs, manage test cases within runs, and track their results. Write operations (create/update/delete) can only be performed by users with role test runner or with higher privileges.
## Types of Runs
QA Sphere supports three types of test runs:
### 1. User Selection (Static Structure)
* Specified by `type: "static_struct"`
* Test cases can be selected by their IDs or using filters (folders, tags, priorities)
* Test cases in the run are fixed after creation unless manually updated
* Updates to versioned test case properties, such as title and steps, are reflected for test cases with open statuses
### 2. Static Runs
* Specified by `type: "static"`
* Test cases can be selected directly by IDs or using filters (folders, tags, priorities)
* Similar to Static Structure in that test cases are fixed after creation
* Updates to versioned test case properties, such as title and steps, are not reflected in the run, even for test cases with open statuses
### 3. Live Runs
* Specified by `type: "live"`
* Only dynamic selection based on folder, tag, and priority filters
* Test cases are automatically added/removed when they match or do not match filter criteria
* Supports multiple query plans for flexible test case selection
* Updates to versioned test case properties, such as title and steps, are reflected for test cases with open statuses
1. Updates to test cases are never propagated to closed runs
2. For live and user selection runs, test case versions are fixed once the status is non-open. As a result, updates to versioned test case properties, such as title and steps, are not reflected in the run
3. Changes to the folder and position of test cases are always propagated to all run types, except closed runs, because these changes are not versioned. This means that such updates do not create a new test case version and are applied to all existing versions of the test case
## Test Case Selection
Test cases can be selected in two ways:
1. **Direct Selection**: Use `tcaseIds` to directly specify the test cases
2. **Using filters**:
* `folderIds`: Select test cases from specific folders, including those within subfolders
* `tagIds`: Select test cases with specific tags
* `priorities`: Select test cases with specific priority levels
* If any of these filters is not specified or is left empty, all test cases are selected without filtering based on that criterion
* The resulting list of test cases is obtained by applying a logical AND to these conditions
This selection method is referred to as a **Query Plan**.
* For static and user selection runs, only single query plan can be specified. When using filters, the system automatically resolves them to a fixed set of test cases at the time of creation
* For live runs, only filter-based selection is allowed, and multiple query plans can be specified. The results of all query plans are combined using a union to create the final list of test cases. Additionally, as test case properties change, test cases are automatically added to or removed from the run according to the query plans
1. Only `standalone` and `filled` test case types are allowed in a run.
## List Project Runs
`GET /api/public/v0/project/{project_id}/run`
Returns all runs in a project with their current status.
### Query Parameters
| Parameter | Description | Example |
| -------------- | ------------------------------------------------------------------------- | -------------------------------------------- |
| `closed` | Filter by run status | `closed=true` or `closed=false` |
| `milestoneIds` | Filter by milestone | `milestoneIds=1&milestoneIds=2` |
| `limit` | Maximum number of runs to return | `limit=10` |
| `include` | Return only the specified related objects (all are returned when omitted) | `include=configuration&include=statusCounts` |
By default every related object listed under [Response Fields](#response-fields) is returned. Supply one or more `include` values to return **only** the related objects you need — any related object you do not list is returned as `null`. Allowed values: `project`, `plan`, `milestone`, `assignment`, `configuration`, `statusCounts`.
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run
```
### Response Fields
```typescript
{
runs: Array<{
id: number // Unique identifier of the test run
type: string // Type of the run (`static` | `static_struct` | `live`)
title: string // Title of the test run
description: html // Description of the test run
projectId: string // ID of the project this run belongs to
project: {
// Project details
id: string // Project unique identifier
code: string // Project code
title: string // Project title
}
planId: number | null // ID of the test plan to which the run belongs to (if any)
plan: {
// Test plan details (if any)
title: string // Test plan title
} | null
milestoneId: number | null // ID of associated milestone (if any)
milestone: {
// Milestone details (if any)
title: string // Milestone Title
} | null
assignmentId: number | null // ID of the assigned user (if any)
assignment: {
// Assignee details (if any)
id: number // User ID
email: string // User email
name: string // User display name
avatar: string // URL to user's avatar; fetching it requires authentication
role: string // User role in the project
} | null
configurationId: number | null // ID of the configuration associated with the run (if any)
configuration: {
// Configuration details (if any)
id: string // Configuration ID
title: string // Configuration title
createdAt: string // Configuration creation timestamp
updatedAt: string // Configuration last update timestamp
} | null
statusCounts: {
// Count of run test cases by status
all: number // Total test cases
blocked: number // Blocked test cases
failed: number // Failed test cases
open: number // Open test cases
passed: number // Passed test cases
skipped: number // Skipped test cases
custom1: number // Count of test cases with first custom status
custom2: number // Count of test cases with second custom status
custom3: number // Count of test cases with third custom status
custom4: number // Count of test cases with fourth custom status
}
timeSpent: number | null // Time spent on the run
isAutomated: boolean // Whether the run was created using public APIs
createdAt: string // Run creation timestamp
closedAt: string | null // Run closure timestamp
closedByUserId: number | null // ID of user who closed the run
}>
}
```
## Create New Run
`POST /api/public/v0/project/{project_id}/run`
Creates a new test run in the project.
1. For `static`/`static_struct` run types:
* Only a single query plan should be specified, and either of the two selection methods (direct or filters) can be used
* When using filters, the system automatically resolves them to a fixed set of test cases at the time of creation
2. For `live` run types, only filter-based selection is permitted, and multiple query plans can be specified
3. Within a given query plan, the filter conditions are combined using a logical AND
4. The test case lists obtained from different query plans are combined using a union
5. Only `standalone` and `filled` test case types are allowed in a run
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Request Body
```typescript
{
title: string // Required: Run title
description?: html // Optional: Run description
type: string // Required: Run type (`static` | `static_struct` | `live`)
milestoneId?: number // Optional: Associated milestone
configurationId?: string // Optional: Associated configuration
assignmentId?: number // Optional: Assigned user
queryPlans: Array<{ // Required: Test case selection criteria
// Direct Selection:
tcaseIds?: Array // Directly specify test cases
// Using Filters:
folderIds?: Array // Select test cases from folders (including subfolders)
tagIds?: Array // Select test cases with tags
priorities?: Array // Select by priority (`low` | `medium` | `high`)
}>
}
```
**Field Constraints**
* `title`: Must be 1-255 characters long and unique within the project
* `description`: Maximum 512 characters
* `queryPlans`:
* For non-live runs: Only one query plan is allowed
* For live runs: Only filter based selection is allowed
* `milestoneId`: The milestone must belong to the project and must not be archived
* `assignmentId`: Must be an active user with permissions above Viewer role
### Example Request - Live Run With Filtered Test Cases
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"title": "Sprint 23 Regression",
"description": "Regression test suite for Sprint 23 release
",
"type": "live",
"milestoneId": 5,
"queryPlans": [{
"folderIds": [1, 2],
"tagIds": [1],
"priorities": ["high"]
}, {
"folderIds": [4, 6],
"tagIds": [],
"priorities": ["medium", "high"]
}]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run
```
### Example Request - Live Run With All Test Cases
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"title": "Complete Test Suite",
"description": "Run with all test cases from the project
",
"type": "live",
"milestoneId": 5,
"queryPlans": [{
"folderIds": [],
"tagIds": [],
"priorities": []
}]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run
```
### Example Request - Static Run With Specific Test Cases
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"title": "Specific Test Cases Run",
"type": "static",
"queryPlans": [{
"tcaseIds": ["1CEPaUhgH_Tvt2LZygwVRQa", "1CAPaUhgH_Tvt2LZygwVRTb", "1EEPaUhgH_Tvt2LZygwVRLm"]
}]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run
```
### Response
Status: 201 Created
```json
{
"id": 2
}
```
**Best Practices**
* Use live runs for ongoing test suites that should automatically update
* Use static runs for fixed test sets like release certifications
* Always provide descriptive titles and link runs to milestones when applicable
* Assign runs to specific users for better accountability
## Clone Existing Run
`POST /api/public/v0/project/{project_id}/run/clone`
Creates a new run by cloning an existing one. For live runs, the new run will reflect current test case states.
The support for cloning runs with test plans via this endpoint is planned for a future release.
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Request Body
```typescript
{
runId: number // Required: Source run ID to clone
title: string // Required: New run title
description?: html // Optional: New description
milestoneId?: number // Optional: New milestone
assignmentId?: number // Optional: New assignee
}
```
**Field Constraints**
* `title`: Must be 1-255 characters long and unique within the project
* `description`: Maximum 512 characters
* `runId`: Must be a valid run ID in the project
* `milestoneId`: The milestone must belong to the project and must not be archived
* `assignmentId`: Must be an active user with permissions above Viewer role
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"runId": 1,
"title": "Sprint 24 Regression - Clone",
"description": "Cloned regression suite for Sprint 24
",
"milestoneId": 5,
"assignmentId": 1
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/clone
```
### Example Response
```json
{
"id": 2
}
```
When cloning a live run, the new run will:
* Maintain the same query plans as the original run
* Reflect the current state of test cases (may differ from the original run)
* Start with all test cases in 'open' status regardless of the original run's results
## Close Run
`POST /api/public/v0/project/{project_id}/run/{run_id}/close`
Close an open test run.
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/close
```
## List Run Test Cases
`GET /api/public/v0/project/{project_id}/run/{run_id}/tcase`
Returns all test cases in a run with their current status.
### Query Parameters
All query parameters are optional and some can be specified multiple times using the format `param=value1¶m=value2¶m=value3`.
| Parameter | Type | Multiple | Description | Allowed Values | Example |
| -------------------------------- | ------ | -------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------- |
| `search` | string | no | Filter test cases by title (case insensitive, partial matches) | | `search=ui` |
| `tags` | number | yes | Filter test cases by tag ID | | `tags=12` |
| `priorities` | string | yes | Filter test cases by priority | `high`, `medium`, `low` | `priorities=low` |
| `include` | string | yes | Include additional fields in the response which are omitted by default | `folder`, `steps`, `tags`, `precondition`, `requirements`, `customFields` | `include=steps` |
| `cf_${custom field system name}` | string | yes | Filter test cases by custom field value | Custom field defined values | `cf_automation=Automated` |
* Different filters are combined with AND logic
* Multiple values for the same filter are combined with OR logic
* `include=steps`, `include=tags`, `include=precondition`, `include=requirements` and
`include=customFields` return the content of the exact test case version pinned by the
run, so the response matches what the run's results were recorded against even if a
test case was edited later. The
[Test Cases list endpoint](/docs/api/endpoints/tcases) always returns the latest version instead.
### Example Request
#### Fetch all run test cases with additional folder information
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?include=folder
```
#### Fetch all run test cases with their steps and tags in a single request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?include=steps&include=tags"
```
#### Fetch all test cases from a run with "Automation" custom field to be "Automated"
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?cf_automation=Automated
```
#### Fetch 20 test cases from a run sorted by title in ascending order
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?limit=20&sortField=title&sortOrder=asc
```
#### Fetch 10 most recent added test cases from a run
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?limit=10&sortField=created_at&sortOrder=desc
```
#### Fetch test cases with "backend" in their title from a run
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?search=backend
```
#### Fetch test cases with tag "cart" from a run
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?tag=cart
```
#### Fetch test cases with priority "high" from a run
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase?priority=high
```
### Response Fields
```typescript
{
tcases: Array<{
id: string // Unique identifier of the test case
version: number // Version number of the test case
legacyId: string // Legacy identifier (if any)
type: string // Type of the test case (`standalone` | `filled`)
folderId: number // ID of the folder containing the test case
pos: number // Position within the folder
seq: number // Sequence number
title: string // Title/description of the test case
priority: string // Priority level (high, medium, etc.)
status: string // Status of the latest result added for the run test case (open if no results are added)
isAutomated: boolean // Whether latest result was added using public APIs
isEmpty: boolean // Whether the test case is empty (has no comment and steps)
templateTCaseId?: string // Corresponding template test case ID, if it is a filled test case
folder?: {
// Folder information if include=folder query parameter is passed
id: number // Unique identifier for the folder
parentId: number // Unique identifier of the parent of the folder (0 if it is the root folder)
title: string // Title of the folder
comment: html // Added comment for the folder
pos: number // Position of the folder with respect to its sibling (starts with 0)
}
steps?: Array // Steps of the pinned test case version if include=steps is passed
// (same shape as `steps` in the Get Run Test Case response below)
tags?: Array<{
// Tags of the pinned test case version if include=tags is passed
id: number // Unique identifier of the tag
title: string // Title of the tag
}>
precondition?: {
// Precondition of the pinned test case version if include=precondition is passed
projectId: string // Project id the precondition belongs to
id: number // Unique identifier of the precondition
version: number // Version of the precondition
type: string // Type of the precondition (standalone | shared)
title?: string // Title of the precondition (only for shared preconditions)
text: html // Text of the precondition (empty when the test case has none)
isLatest: boolean // Whether this is the latest version of the precondition
}
requirements?: Array<{
// Requirements of the pinned test case version if include=requirements is passed
id: string // Unique identifier of the requirement
text: string // Title of the requirement
url: string // URL of the requirement
}>
customFields?: {
// Custom fields of the pinned test case version if include=customFields is passed
[key: string]: {
// Key-value pairs of custom field system names and corresponding details
value: string // Current value
isDefault: boolean // Whether default value is set by the system or selected by the user
}
}
}>
}
```
### Sample Response
```
{
"tcases": [
{
"id": "1CGeNaNVt_Axa7TcMjUm6Zh",
"version": 1,
"legacyId": "",
"type": "standalone",
"folderId": 11848,
"pos": 3,
"seq": 8,
"title": "The \"Checkout\" page with products from the cart should be shown after clicking the \"Checkout\" button",
"priority": "high",
"status": "open",
"isAutomated": false,
"isEmpty": true
},
{
"id": "1CGeNaNWP_Eiq5mjzPsKSX9",
"version": 1,
"legacyId": "",
"type": "filled",
"folderId": 11848,
"pos": 4,
"seq": 9,
"title": "The cart is still filled after going back from the \"Checkout\" page without submitting it",
"priority": "medium",
"status": "open",
"isAutomated": false,
"isEmpty": false
}
]
}
```
## Get Run Test Case
`GET /api/public/v0/project/{project_id}/run/{run_id}/tcase/{tcase_or_legacy_id}`
Get details of a single run test case using its ID, sequence or legacy ID.
Step `data` items follow the shape described in the Step Test Data section of the [Test Cases](/docs/api/tcases/#step-test-data) page.
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/tcase/1
```
### Response Fields
```typescript
{
id: string // Unique identifier of the test case
version: number // Version number of the test case
legacyId: string // Legacy identifier (if any)
type: string // Test case type (`standalone` | `filled`)
title: string // Title of the test case
seq: number // Sequence number of the test case
folderId: number // Identifier of the folder where the test case is placed
pos: number // Ordered position (0 based) of the test case in its folder
priority: string // Priority of the test case (`high` | `medium` | `low`)
templateTCaseId: string | null // Identifier of the parent template test case (in case of `filled` test case type)
comment: html // Test case precondition
steps: Array<{ // List of test case steps
id: number // Unique identifier of the step
type: string // Type of the step (standalone | shared)
version: number // Version of the step (always 1 for standalone steps)
isLatest: boolean // Whether this is the latest version of the step (always true for standalone steps)
title?: string // Title of the step (only for shared steps)
subSteps?: Array<{ // List of sub steps (only for shared steps)
id: number // Unique identifier of the step
type: string // Type of the step (shared_sub_step)
version: number // Version of the step (same as parent step)
isLatest: boolean // Whether this is the latest version (same as parent step)
description: html // Details of the sub step
expected: html // Expected result from the sub step
data?: Array // Sub step test data items (see Step Test Data on the Test Cases page)
deletedAt?: string // Date the sub step was deleted on
}>
description?: html // Details of step (only for standalone steps)
expected?: html // Expected result from the step (only for standalone steps)
data?: Array // Step test data items, only for standalone steps (see Step Test Data)
deletedAt?: string // Date the step was deleted on
}>
tags: Array<{ // List of test case tags
id: number // Unique identifier of the tag
title: string // Title of the tag
}>
files: Array<{ // List of files attached to the test case
id: string // Unique identifier of the file
fileName: string // Name of the file
mimeType: string // Mime type of the file
size: number // Size of the file
url: string // URL of the file
}>
requirements: Array<{ // Test case requirement (currently only single requirement is supported on UI)
id: string // Unique identifier of the requirement
text: string // Title of the requirement
url: string // URL of the requirement
}>
links: Array<{ // Additional links relevant to the test case
text: string // Title of the link
url: string // URL of the link
}>
customFields: { // Custom fields defined for the test case
[key: string]: { // Key-value pairs of custom field system names and corresponding details for the test case
value: string // Current value
isDefault: boolean // Whether default value is set by the system or selected by the user
}
}
authorId: number // Unique identifier of the user who created the test case
createdAt: string // Test case creation timestamp (ISO 8601 format)
status: string // Status of the latest result added for the run test case (open if no results are added)
isAutomated: boolean // Whether latest result was added using public APIs
isLatestVersion: boolean // Whether this is the latest version of the test case
isEmpty: boolean // Whether the test case is empty (has no comment and steps)
templateTCaseId?: string // Corresponding template test case ID, if it is a filled test case
results: Array<{ // Results created for this test case in the run
id: number // Unique identifier of the test case result
tcaseId: string // Unique identifier of the test case
tcaseVersion: string // Version number of the test case
authorId: number // Unique identifier of the user who added the result
author: { // Details of the user who added the result
id: number // Unique identifier of the user
email: string // Email of the user
name: string // Name of the user
avatar: string | null // Avatar URL of the user; fetching it requires authentication
role: string // Role of the user (`owner` | `admin` | `user` | `test-runner` | `viewer`)
}
status: string // Result status (`passed` | `failed` | `blocked` | `skipped` | `open` | `custom1` | `custom2` | `custom3` | `custom4`)
comment: html // Comments/observations while executing the test case
links: Array<{ // Details of issues created in external integrations
id: number // Unique identifier of the issue
resultId: number // Unique identifier of the result for which the issue is created
integrationId: string // Unique identifier of the external integration on which the issue is created
integration: { // Details of the external integration
id: string // Unique identifier of the integration
name: string // Name of the integration
type: string // Integration type (`jira` | `github` | `custom`)
config: object // Configuration for the integration (eg. url/email)
}
url: string // URL of the created issue
text: string // Title of the created issue
meta: object // Additional information related to the issue
}>
timeTaken: number | null // Time taken for executing the test case
apiKeyId: string | null // Unique identifier of the API key, if this result was added via public APIs
internal: boolean // Whether the result was added by system (eg. when test run is modified)
createdAt: string // Result creation time (ISO 8601 format)
}>
}
```
### Sample Response
```json
{
"id": "1CEPaUhgH_Tvt2LZygwVRQa",
"version": 1,
"legacyId": "",
"type": "standalone",
"title": "Changing to corresponding cursor after hovering the element",
"seq": 1,
"folderId": 2,
"pos": 0,
"priority": "low",
"templateTCaseId": null,
"comment": "The \"About Us\" page is opened
",
"steps": [
{
"description": "Test the display across various screen sizes (desktop, tablet, mobile) to ensure that blocks and buttons adjust appropriately to different viewport widths
",
"expected": ""
}
],
"tags": [
{
"id": 1,
"title": "About Us"
},
{
"id": 2,
"title": "Checklist"
}
],
"files": [],
"requirements": [],
"links": [],
"customFields": {},
"authorId": 1,
"createdAt": "2024-01-01T00:00:00.000Z",
"status": "open",
"isAutomated": false,
"isLatestVersion": true,
"isEmpty": false,
"results": [
{
"id": 20293,
"tcaseId": "1CEPaUhgH_Tvt2LZygwVRQa",
"tcaseVersion": 1,
"authorId": 1,
"author": {
"id": 1,
"email": "owner@example.com",
"name": "System Owner",
"avatar": null,
"role": "owner"
},
"status": "blocked",
"comment": "",
"links": null,
"timeTaken": null,
"apiKeyId": null,
"internal": false,
"createdAt": "2024-01-01T00:00:00.000Z"
}
]
}
```
## Create Run Log
`POST /api/public/v0/project/{project_id}/run/{run_id}/log`
Create a log entry for a test run. Run logs can be used to record messages from CI/CD pipelines, automation frameworks, or any external system during test execution. Logs cannot be added to closed runs.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `run_id`: The run identifier (numeric)
### Authentication
Requires an API key with at least Test Runner role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Request Body
```typescript
{
comment: string // Required: Log message content (HTML supported, minimum 1 character)
}
```
**Field Constraints**
* `comment`: Must be at least 1 character long. HTML content is sanitized and leading/trailing whitespace is trimmed.
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"comment": "Build #1234 failed: 3 test cases did not pass
"
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/run/1/log
```
### Response Fields
| Field | Type | Description |
| ----- | -------- | --------------------------------- |
| `id` | `string` | Unique identifier for the run log |
### Example Response
Status: 201 Created
```json
{
"id": "1CGeNaNVt_Axa7TcMjUm6Zh"
}
```
### Error Responses
| Status Code | Description |
| ----------- | ------------------------------------------------------------------- |
| 400 | Invalid request body or empty comment |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant or project is archived |
| 404 | Project or test run not found |
| 409 | Test run is closed |
| 500 | Internal server error while creating log |
---
# Settings
URL: /docs/api/settings
The settings endpoint allows you to check and update result statuses.
## Result Status
Each test case result is assigned a status based on the outcome of its execution. QA Sphere supports two categories of statuses:
1. **Default Statuses**: These are the commonly used statuses that come by default. They include `passed`, `failed`, `blocked`, `skipped`, and `open`. These statuses cannot be removed or modified.
2. **Custom Statuses**: If additional statuses are needed, QA Sphere allows for the creation of up to four custom statuses. The labels and colors for these custom statuses can be configured and will be displayed in the UI. In the API, these statuses are referred to as `custom1`, `custom2`, `custom3`, and `custom4`.
## Get Statuses
`GET /api/public/v0/settings/preferences/status`
Get current status configuration.
### Response
Status: 200 OK
```typescript
{
statuses: Array<{
id: string // Unique identifier for the status ("passed" | "failed" | "blocked" | "skipped" | "open" | "custom1" | "custom2" | "custom3" | "custom4")
name: string // Display name of the status
color: string // Display color of the status ("blue" | "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "indigo" | "purple" | "pink")
isDefault: boolean // Is this a default status
isActive: boolean // Is this (custom) status enabled (always true for default statuses)
inUse: boolean // Is this (custom) status in use (always true for default statuses)
}>
}
```
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/settings/preferences/status
```
### Example Response
```json
{
"statuses": [
{
"id": "open",
"name": "Open",
"color": "blue",
"isDefault": true,
"isActive": true,
"inUse": true
},
{
"id": "passed",
"name": "Passed",
"color": "green",
"isDefault": true,
"isActive": true,
"inUse": true
},
{
"id": "failed",
"name": "Failed",
"color": "red",
"isDefault": true,
"isActive": true,
"inUse": true
},
{
"id": "skipped",
"name": "Skipped",
"color": "gray",
"isDefault": true,
"isActive": true,
"inUse": true
},
{
"id": "blocked",
"name": "Blocked",
"color": "orange",
"isDefault": true,
"isActive": true,
"inUse": true
},
{
"id": "custom1",
"name": "Known Issue",
"color": "teal",
"isDefault": false,
"isActive": true,
"inUse": true
},
{
"id": "custom2",
"name": "Retest",
"color": "orange",
"isDefault": false,
"isActive": false,
"inUse": false
},
{
"id": "custom3",
"name": "Custom 3",
"color": "purple",
"isDefault": false,
"isActive": true,
"inUse": true
},
{
"id": "custom4",
"name": "Custom 4",
"color": "teal",
"isDefault": false,
"isActive": false,
"inUse": false
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | --------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 500 | Internal server error while fetching statuses |
## Update Custom Statuses
`POST /api/public/v0/settings/preferences/status`
Update custom statuses.
* Custom statuses apply across the entire account, and any updates will also be reflected in previously added results.
* Once a custom status is enabled and is in use, it cannot be disabled.
### Authentication
Requires an API key with at least Admin role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Request Body
```typescript
{
statuses: Array<{
id: string // Unique identifier for the custom status ("custom1" | "custom2" | "custom3" | "custom4")
name: string // Display name of the status
color: string // Display color of the status ("blue" | "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "indigo" | "purple" | "pink")
isActive: boolean // Is this custom status enabled
}>
}
```
### Response
Status: 200 OK
```typescript
{
message: 'Statuses updated'
}
```
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"statuses": [
{
"id": "custom3",
"name": "Blocker",
"color": "red",
"isActive": true
}
]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/settings/preferences/status
```
### Error Responses
| Status Code | Description |
| ----------- | ------------------------------------------------ |
| 400 | Invalid status id or color |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 409 | Trying to update default or in use custom status |
| 500 | Internal server error while updating statuses |
* Custom statuses can only be updated by users with owner or admin roles.
* Custom statuses apply across the entire account, and any updates will also be reflected in previously added results.
* Once a custom status is enabled and used, it cannot be disabled.
---
# Shared Preconditions
URL: /docs/api/shared_preconditions
The shared preconditions endpoints allow you to manage reusable test preconditions that can be referenced across multiple test cases. Shared preconditions consist of a title and text content that describes the initial state or setup required before executing test cases.
## About Shared Preconditions
Shared preconditions are reusable precondition templates that can be used in multiple test cases. They consist of:
1. **Title**: A descriptive name for the shared precondition (required, minimum 1 character)
2. **Text**: The actual precondition content in HTML format (required, minimum 1 character)
When a shared precondition is used in a test case, it provides consistent setup instructions. Updates to a shared precondition automatically propagate to all test cases that reference it.
* Shared preconditions must have both a title and text content
* The title of a shared precondition must be unique within a project
* Shared preconditions are versioned - updates create new versions while preserving old ones
* Deleted preconditions are marked with a `deletedAt` timestamp but remain in the data structure
## List Shared Preconditions
`GET /api/public/v0/project/{project_id}/shared-precondition`
Retrieves all shared preconditions within a project, optionally sorted and with additional fields included.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Query Parameters
All query parameters are optional.
| Parameter | Type | Description | Allowed Values | Example |
| ----------- | ------ | ---------------------------------------------------------------------- | --------------------- | -------------------- |
| `sortField` | string | Field to sort by | `created_at`, `title` | `sortField=title` |
| `sortOrder` | string | Sort order (requires `sortField`; default: `desc`) | `asc`, `desc` | `sortOrder=asc` |
| `include` | string | Include additional fields in the response which are omitted by default | `tcaseCount` | `include=tcaseCount` |
* Use `include=tcaseCount` to see how many test cases reference each shared precondition
* Sorting by `created_at` shows the most recently created preconditions first (with `desc`) or oldest first (with `asc`)
* Sorting by `title` provides alphabetical ordering
* If no `sortField` is specified, the default sort is by `title` in ascending order
### Example Request
#### Fetch all shared preconditions
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-precondition
```
#### Fetch all shared preconditions sorted by title in ascending order
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-precondition?sortField=title&sortOrder=asc
```
#### Fetch all shared preconditions sorted by creation date (newest first)
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-precondition?sortField=created_at&sortOrder=desc
```
#### Fetch all shared preconditions with test case count included
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-precondition?include=tcaseCount
```
### Response Fields
```typescript
Array<{
// List of shared precondition objects
projectId: string // Unique identifier of the project
id: number // Unique identifier of the shared precondition
version: number // Version of the shared precondition
title: string // Title of the shared precondition
type: string // Type of the precondition (always "shared" for shared preconditions)
text: html // Text content of the precondition (HTML format)
isLatest: boolean // Whether this is the latest version of the precondition
createdAt: string // Precondition creation time (ISO 8601 format)
updatedAt: string // Precondition updation time (ISO 8601 format)
deletedAt?: string // Date the precondition was deleted on (ISO 8601 format)
tcaseCount?: number // Number of test cases using this shared precondition (only included if requested)
}>
```
### Example Response
```json
[
{
"projectId": "2HKj57k3z_YXYQVTdnPqrs8",
"id": 1,
"version": 2,
"title": "User is logged in",
"type": "shared",
"text": "The user has valid credentials and is authenticated in the system
",
"isLatest": true,
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-20T14:45:00.000Z"
},
{
"projectId": "2HKj57k3z_YXYQVTdnPqrs8",
"id": 2,
"version": 1,
"title": "Application is running",
"type": "shared",
"text": "The application server is running and accessible
",
"isLatest": true,
"createdAt": "2025-01-16T09:15:00.000Z",
"updatedAt": "2025-01-16T09:15:00.000Z",
"tcaseCount": 15
},
{
"projectId": "2HKj57k3z_YXYQVTdnPqrs8",
"id": 3,
"version": 1,
"title": "Database is initialized",
"type": "shared",
"text": "The database contains the required test data
",
"isLatest": true,
"createdAt": "2025-01-17T11:20:00.000Z",
"updatedAt": "2025-01-17T11:20:00.000Z",
"tcaseCount": 3
}
]
```
## Get Shared Precondition
`GET /api/public/v0/project/{project_id}/shared-precondition/{shared_precondition_id}`
Get details of a single shared precondition using its ID.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `shared_precondition_id`: The shared precondition identifier (numeric ID)
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-precondition/1
```
### Response Fields
```typescript
{
projectId: string // Unique identifier of the project
id: number // Unique identifier of the shared precondition
version: number // Version of the shared precondition
title: string // Title of the shared precondition
type: string // Type of the precondition (always "shared" for shared preconditions)
text: html // Text content of the precondition (HTML format)
isLatest: boolean // Whether this is the latest version of the precondition
createdAt: string // Precondition creation time (ISO 8601 format)
updatedAt: string // Precondition updation time (ISO 8601 format)
deletedAt?: string // Date the precondition was deleted on (ISO 8601 format)
}
```
### Example Response
```json
{
"projectId": "2HKj57k3z_YXYQVTdnPqrs8",
"id": 1,
"version": 2,
"title": "User is logged in",
"type": "shared",
"text": "The user has valid credentials and is authenticated in the system
",
"isLatest": true,
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-20T14:45:00.000Z"
}
```
---
# Shared Steps
URL: /docs/api/shared_steps
The shared steps endpoints allow you to manage reusable test steps that can be referenced across multiple test cases. Shared steps consist of a title and a list of sub-steps, each with a description and expected result.
## About Shared Steps
Shared steps are reusable test step templates that can be used in multiple test cases. They consist of:
1. **Title**: A descriptive name for the shared step (1-255 characters)
2. **Sub-steps**: A list of individual steps, each with:
* **Description**: What action to perform (HTML content)
* **Expected**: The expected result (HTML content)
* **Test data** (optional): A list of up to 20 test data items (`text`, `link`, or `file`), returned in the `data` field — see the Step Test Data section of the [Test Cases](/docs/api/tcases/#step-test-data) page for the item shape
When a shared step is used in a test case, all its sub-steps are included. Updates to a shared step automatically propagate to all test cases that reference it.
* Shared steps must have at least one sub-step
* Each sub-step must have at least a description, expected result, or test data
* The title of a shared step must be unique within a project
* Shared steps are versioned - updates create new versions while preserving old ones
* Deleted sub-steps are marked with a `deletedAt` timestamp but are not deleted because they may still be referenced by some test case versions
## List Shared Steps
`GET /api/public/v0/project/{project_id}/shared-step`
Retrieves all non deleted shared steps within a project, optionally sorted and with additional fields included.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Query Parameters
All query parameters are optional.
| Parameter | Type | Description | Allowed Values | Example |
| ----------- | ------ | ---------------------------------------------------------------------- | --------------------- | -------------------- |
| `sortField` | string | Field to sort by | `created_at`, `title` | `sortField=title` |
| `sortOrder` | string | Sort order (requires `sortField`; default: `desc`) | `asc`, `desc` | `sortOrder=asc` |
| `include` | string | Include additional fields in the response which are omitted by default | `tcaseCount` | `include=tcaseCount` |
* Use `include=tcaseCount` to see how many test cases reference each shared step
* Sorting by `created_at` shows the most recently created steps first (with `desc`) or oldest first (with `asc`)
* Sorting by `title` provides alphabetical ordering
### Example Request
#### Fetch all shared steps
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-step
```
#### Fetch all shared steps sorted by title in ascending order
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-step?sortField=title&sortOrder=asc
```
#### Fetch all shared steps with test case count included
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-step?include=tcaseCount
```
### Response Fields
```typescript
{
sharedSteps: Array<{
// List of shared step objects
id: number // Unique identifier of the shared step
version: number // Version of the shared step
type: string // Type of the step (always "shared" for shared steps)
title: string // Title of the shared step
isLatest: boolean // Whether this is the latest version of the step
subSteps: Array<{
// List of sub-steps
id: number // Unique identifier of the sub-step
type: string // Type of the step (always "shared_sub_step")
version: number // Version of the step (same as parent step)
isLatest: boolean // Whether this is the latest version (same as parent step)
description: html // Details of the sub-step
expected: html // Expected result from the sub-step
data?: Array // Sub-step test data items (see Step Test Data on the Test Cases page)
deletedAt?: string // Date the sub-step was deleted on (ISO 8601 format)
}>
deletedAt?: string // Date the shared step was deleted on (ISO 8601 format)
tcaseCount?: number // Number of test cases using this shared step (only included if requested)
}>
}
```
### Example Response
```json
{
"sharedSteps": [
{
"id": 1,
"version": 3,
"type": "shared",
"title": "User login validation",
"isLatest": true,
"subSteps": [
{
"id": 2,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Navigate to the login page
",
"expected": "Login form is displayed
"
},
{
"id": 3,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Enter valid username and password
",
"expected": "Credentials are accepted
"
},
{
"id": 4,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Click the login button
",
"expected": "User is redirected to the dashboard
"
}
]
},
{
"id": 5,
"version": 1,
"type": "shared",
"title": "Form submission validation",
"isLatest": true,
"subSteps": [
{
"id": 6,
"type": "shared_sub_step",
"version": 1,
"isLatest": true,
"description": "Fill in all required fields
",
"expected": "All fields are populated correctly
"
},
{
"id": 7,
"type": "shared_sub_step",
"version": 1,
"isLatest": true,
"description": "Submit the form
",
"expected": "Form is submitted successfully
"
}
],
"tcaseCount": 12
}
]
}
```
## Get Shared Step
`GET /api/public/v0/project/{project_id}/shared-step/{step_id}`
Get details of a single shared step using its ID.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `step_id`: The shared step identifier (numeric ID)
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/shared-step/1
```
### Response Fields
```typescript
{
id: number // Unique identifier of the shared step
version: number // Version of the shared step
type: string // Type of the step (always "shared" for shared steps)
title: string // Title of the shared step
isLatest: boolean // Whether this is the latest version of the step
subSteps: Array<{ // List of sub-steps
id: number // Unique identifier of the sub-step
type: string // Type of the step (always "shared_sub_step")
version: number // Version of the step (same as parent step)
description: html // Details of the sub-step
expected: html // Expected result from the sub-step
data?: Array // Sub-step test data items (see Step Test Data on the Test Cases page)
deletedAt?: string // Date the sub-step was deleted on (ISO 8601 format)
}>
isLatest: boolean // Whether this is the latest version (same as parent step)
deletedAt?: string // Date the shared step was deleted on (ISO 8601 format)
}
```
### Example Response
```json
{
"id": 1,
"version": 3,
"type": "shared",
"title": "User login validation",
"isLatest": true,
"subSteps": [
{
"id": 2,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Navigate to the login page
",
"expected": "Login form is displayed
"
},
{
"id": 3,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Enter valid username and password
",
"expected": "Credentials are accepted
",
"data": [
{
"type": "text",
"label": "Credentials",
"data": { "value": "user@example.com / s3cret", "format": "plaintext" }
}
]
},
{
"id": 4,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Click the login button
",
"expected": "User is redirected to the dashboard
"
}
]
}
```
---
# Tags
URL: /docs/api/tag
Tags help organize and categorize test cases within your project. You can use tags in query plans to filter test cases when creating runs.
## List Project Tags
`GET /api/public/v0/project/{project_id}/tag`
Returns all tags defined in the project. This endpoint is particularly useful when creating run query plans that filter test cases by tags.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Response
Status: 200 OK
```typescript
{
tags: Array<{
id: number // Unique tag identifier within the project
title: string // Tag name/label
}>
}
```
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tag
```
### Example Response
```json
{
"tags": [
{
"id": 1,
"title": "regression"
},
{
"id": 2,
"title": "api-tests"
},
{
"id": 3,
"title": "smoke-tests"
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project not found |
| 500 | Internal server error |
### Using Tags in Run Query Plans
Tags returned by this endpoint can be used in run query plans to filter test cases. For example:
```json
{
"title": "API Regression Run",
"type": "live",
"queryPlans": [
{
"folderIds": [1],
"tagIds": [2], // Using the tag ID for "api-tests"
"priorities": ["high"]
}
]
}
```
Tag IDs are unique within a project but not across projects. Always verify you're using tag IDs from the correct project.
**Using Multiple Tags**
You can include multiple tag IDs in a query plan to select test cases that have any of the specified tags.
```json
{
"tagIds": [2, 3] // Selects test cases with either "api-tests" or "smoke-tests" tags
}
```
---
# Test Cases
URL: /docs/api/tcases
The test cases endpoints allow you to retrieve information about test cases in your project. This can be useful for planning test runs and monitoring your test coverage.
## Types of Test Cases
In QA Sphere, there are three types of test cases:
1. **Standalone Test Case**: These are the standard test cases.
2. **Template Test Case**: Similar to standalone test cases, but they can include parameters within `${}` in their title, preconditions, and steps. These parameters can be replaced with specific values to generate multiple test cases from the same template.
3. **Filled Test Cases**: Automatically created by the system by substituting parameter values in template test cases. They inherit all properties from the parent template test case.
* Users can directly create standalone and template test cases. When creating template test cases, users can specify a list of values for the parameters, which the system uses to automatically generate the corresponding filled test cases.
* Updates to a template test case will also update the corresponding filled test cases.
* Deletion is permitted for all three types of test cases. Deleting a template test case will also delete the associated filled test cases. Deleting a filled test case will only remove that specific test case.
* Test runs include only standalone and filled test cases.
## Step Test Data
Each standalone step (and each sub-step of a shared step) can carry a list of test data items in its `data` field. Every item is one of three types, discriminated by `type`:
```typescript
{
type: string // Required: `text` | `link` | `file`
label?: string // Optional: Item label (max 255 characters, trimmed)
data: // Required: Value, shape depends on `type`
| { value: string, format?: string } // text: required content (max 65535 UTF-16 code units) with an optional language hint (max 32 characters; see below)
| { value: string } // link: an http(s) URL (max 255 characters)
| { value: File } // file: a file object (`id`, `fileName`, `mimeType`, `size`, `stableUrl`, `url`), same shape as test case `files`
}
```
* A step can have at most 20 test data items.
* `text` items must have a non-empty `value` of at most 65,535 UTF-16 code units. `format` is a language hint for syntax highlighting (e.g. `plaintext`, `json`, `sql`); an unsupported value falls back to plain text.
* For `file` items, upload the file first using the upload file endpoint, then pass the object it returns as the item's `value`.
* A step is kept when it has a description, an expected result, **or** test data, so a step carrying only `data` is valid.
* Test data belongs to standalone steps and to shared step sub-steps. A step that references a shared step by `sharedStepId` must not send `data` — the shared step owns the data on its sub-steps, and sending both is rejected.
* Shared steps and their test data are managed through the web UI; the public API returns sub-step `data` in read responses.
## List Project Test Cases
`GET /api/public/v0/project/{project_id}/tcase`
Retrieves all test cases within a project based on the filters provided in the request query parameters.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Query Parameters
All query parameters are optional and some can be specified multiple times using the format `param=value1¶m=value2¶m=value3`.
| Parameter | Type | Multiple | Description | Allowed Values | Example |
| -------------------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `offset` | number | no | Number of rows to skip before returning results. Combine with `limit` for offset-based pagination. | | `offset=10` |
| `limit` | number | no | Maximum number of test cases to return (0–5000). May be `0` to return only the total count (no rows). | | `limit=10` |
| `page` | number | no | **Deprecated** — use `offset` instead. 1-based page number. Ignored when `offset` is set. If `limit` is omitted, a default of 10 is applied. | | `page=1` |
| `sortField` | string | no | Field to sort by | `id`, `seq`, `folder_id`, `author_id`, `pos`, `title`, `priority`, `created_at`, `updated_at`, `legacy_id` | `sortField=title` |
| `sortOrder` | string | no | Sort order (requires `sortField`; default: `desc`) | `asc`, `desc` | `sortOrder=desc` |
| `types` | string | yes | Filter test cases by type | `standalone`, `template`, `filled` | `types=standalone` |
| `search` | string | no | Filter test cases by title (case insensitive, partial matches) | | `search=ui` |
| `folders` | number | yes | Filter test cases by folder ID (does not consider child folders) | | `folders=10&folders=12` |
| `tags` | number | yes | Filter test cases by tag ID | | `tags=12` |
| `priorities` | string | yes | Filter test cases by priority | `high`, `medium`, `low` | `priorities=low` |
| `draft` | bool | no | Filter test cases by draft status | `true`, `false` | `draft=true` |
| `templateTCaseIds` | string | yes | Filter test cases by their parent template test case identifiers | | `templateTCaseIds=1CEPaUhuR_yNsLvcbYJhw46` |
| `requirementIds` | string | yes | Filter test cases by requirement ID | | `requirementIds=1CEPaUhuR_abc123def456` |
| `cf_${custom field system name}` | string | yes | Filter test cases by custom field value | The values for custom fields are defined under Settings > Custom Fields | `cf_automation=Automated` |
| `include` | string | yes | Include additional fields in the response which are omitted by default | `steps`, `tags`, `project`, `folder`, `path`, `requirements`, `customFields`, `filterableCustomFields`, `parameterValues` | `include=steps` |
* Use pagination when project contains large number of test cases
* Only include necessary non-default fields
* Different filters are combined with AND logic
* Multiple values for the same filter are combined with OR logic
### Example Request
#### Fetch all test cases with default fields
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase
```
#### Fetch all test cases with "Automation" custom field to be "Automated"
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?cf_automation=Automated
```
#### Fetch all test cases with "Known Issue" custom field to be "Yes"
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?cf_known_issue=Yes
```
#### Fetch 20 test cases sorted by title in ascending order
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?limit=20&sortField=title&sortOrder=asc
```
#### Skip the first 90 test cases and return the next 15 — or, return 15 rows starting from 0-based index 90
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?offset=90&limit=15&sortField=pos&sortOrder=asc
```
#### Fetch all draft test cases
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?draft=true
```
#### Fetch 10 most recent added test cases
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?limit=10&sortField=created_at&sortOrder=desc
```
#### Fetch test cases with "backend" in their title
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?search=backend
```
#### Fetch test cases with "backend" in their title and include custom fields
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?search=backend&include=customFields
```
#### Fetch all filled test cases corresponding to template test case ID '1CEPaUhuR\_yNsLvcbYJhw46'
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?template_tcase_ids=1CEPaUhuR_yNsLvcbYJhw46
```
#### Fetch test cases linked to a specific requirement
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?requirementIds=1CEPaUhuR_abc123def456
```
#### Fetch test cases linked to multiple requirements (OR logic)
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?requirementIds=1CEPaUhuR_abc123def456&requirementIds=1CEPaUhuR_xyz789ghi012"
```
### Response Fields
```typescript
{
total: number, // Total number of filtered test cases
offset?: number, // The offset that was applied (present when pagination was applied)
limit?: number, // The limit that was applied (present when pagination was applied)
page?: number, // **Deprecated**. Echo of the page that was requested (present only if `page` was used in the request)
data: Array<{ // List of test case objects
id: string // Unique identifier of the test case
legacyId: string // Legacy identifier of the test case. Empty string if the test case has no legacy ID
version: number // Version of the test case. Updates to test (except folder/pos) creates a new version
type: string // Type of the test case (`standalone` | `template` | `filled`)
title: string // Title of the test case
seq: number // Sequence number of the test case. Test cases in a project are assigned incremental sequence numbers
folderId: number // Identifier of the folder where the test case is placed
pos: number // Ordered position (0 based) of the test case in its folder
priority: string // Priority of the test case (`high` | `medium` | `low`)
comment: html // Test case precondition text. DEPRECATED, usable but prefer precondition object below
precondition: {
projectId: string, // Project id the precondition belongs to. Same as test cases'
id: number, // Id of the precondition. Not useful unless the precondition is shared
version: number, // Version of the precondition
title?: string, // Title of the precondition. Only populated for shared
type: 'standalone' | 'shared', // Type of the precondition
text: html, // Actual text contents of the precondition
isLatest: boolean, // Whether precondition's version is latest or not
createdAt: string,
updatedAt: string,
deletedAt?: string,
}
files: Array<{ // List of files attached to the test case
id: string // Unique identifier of the file
fileName: string // Name of the file
mimeType: string // Mime type of the file
size: number // Size of the file
url: string // URL of the file
}>
links: Array<{ // Additional links relevant to the test case
text: string // Title of the link
url: string // URL of the link
}>
authorId: number // Unique identifier of the user who added the test case
isDraft: boolean // Whether the test case is still in draft state
isLatestVersion: boolean // Whether this is the latest version of the test case
isEmpty: boolean // Whether the test case is empty (has no comment and steps)
templateTCaseId?: string // Corresponding template test case ID, if it is a filled test case
numFilledTCases? number // Number of corresponding filled test cases, if it is a template test case
createdAt: string // Test case creation time (ISO 8601 format)
updatedAt: string // Test case updation time (ISO 8601 format)
// Non default fields
customFields: { // Custom fields defined for the test case
[key: string]: { // Key-value pairs of custom field system names and corresponding details for the test case
value: string // Current value
isDefault: boolean // Whether default value is set by the system or selected by the user
}
}
tags: Array<{ // List of test case tags
id: number // Unique identifier of the tag
title: string // Title of the tag
}>
steps: Array<{ // List of test case steps
id: number // Unique identifier of the step
type: string // Type of the step (standalone | shared)
version: number // Version of the step (always 1 for standalone steps)
isLatest: boolean // Whether this is the latest version of the step (always true for standalone steps)
title?: string // Title of the step (only for shared steps)
subSteps?: Array<{ // List of sub steps (only for shared steps)
id: number // Unique identifier of the step
type: string // Type of the step (shared_sub_step)
version: number // Version of the step (same as parent step)
isLatest: boolean // Whether this is the latest version (same as parent step)
description: html // Details of the sub step
expected: html // Expected result from the sub step
data?: Array // Sub step test data items (see Step Test Data)
deletedAt?: string // Date the sub step was deleted on
}>
description?: html // Details of step (only for standalone steps)
expected?: html // Expected result from the step (only for standalone steps)
data?: Array // Step test data items, only for standalone steps (see Step Test Data)
deletedAt?: string // Date the step was deleted on
}>
requirements: Array<{ // Test case requirement (currently only single requirement is supported on UI)
id: string // Unique identifier of the requirement
text: string // Title of the requirement
url: string // URL of the requirement
}>
parameterValues: { // The details of corresponding filled tcases (relevant only for template tcases)
tcaseId: string // ID of the filled tcase
tcaseVersion: number // Version of the filled tcase
values: { // Values corresponding to the parameters in the template tcase for this filled tcase
[key: string]: string
}
}
folder: { // Details of the folder where the test case is placed
id: number // Unique identifier for the folder
title: string // Name of the folder
comment: html // Additional notes or description
pos: number // Position of the folder among its siblings
parentId: number // ID of the parent folder (0 for root folders)
projectId: string // ID of the project the folder belongs to
},
path: Array<{ // Path to the folder where the test cases is placed
id: number // Unique identifier for the folder
title: string // Name of the folder
comment: html // Additional notes or description
pos: number // Position of the folder among its siblings
parentId: number // ID of the parent folder (0 for root folders)
projectId: string // ID of the project the folder belongs to
}>
project: { // Details of project to which the test case belong
id: string // Unique identifier of the project
code: string // Short code of the project
title: string // Title of the project
overviewTitle: string // Title of the project overview
overviewDescription: html // Project Overview
links: { // Links relevant to the project
text: string // Title of the link
url: string // URL of the link
}
archivedAt: string // Project archival time (ISO 8601 format)
createdAt: string // Project creation time (ISO 8601 format)
updatedAt: string // Project updation time (ISO 8601 format)
}
}>
}
```
### Example Response
```json
{
"total": 4,
"offset": 1,
"limit": 2,
"data": [
{
"id": "1CJg36j1c_yFYPRcmZaoqp3",
"version": 6,
"legacyId": "",
"seq": 55,
"type": "standalone",
"folderId": 26,
"pos": 0,
"title": "User should see the content according to the \"About Us\" information",
"priority": "high",
"comment": "The \"About Us\" page is opened
",
"precondition": {
"projectId": "2HKj57k3z_YXYQVTdnPqrs8",
"id": 2,
"version": 3,
"type": "standalone",
"text": "The \"About Us\" page is opened
",
"isLatest": true,
"createdAt": "2025-03-25T10:48:34.66935+02:00",
"updatedAt": "2025-03-25T10:48:34.66935+02:00"
},
"authorId": 1,
"files": [
{
"id": "89f7a73e-043c-4fe1-beb3-9e8d8df55f28",
"fileName": "Screencast from 24-03-25 14:27:33.webm",
"mimeType": "video/webm",
"size": 555431
}
],
"links": [],
"isDraft": false,
"isLatestVersion": true,
"isEmpty": false,
"createdAt": "2025-03-25T10:48:14.243475+02:00",
"updatedAt": "2025-03-25T10:48:14.243475+02:00"
},
{
"id": "1CJg36j28_EaAHxNiNQNNTn",
"version": 6,
"legacyId": "",
"seq": 56,
"type": "standalone",
"folderId": 26,
"pos": 1,
"title": "User should place the order successfully after entering valid data in all required fields and selecting the \"Card Payment\" payment",
"priority": "high",
"comment": "The \"Checkout\" page is opened
There are pizzas, drinks and desserts
",
"authorId": 1,
"files": [
{
"id": "bf5fcc05-44a2-46b2-87fb-2501cfedb1f7",
"fileName": "Screenshot 2025-01-15 18:54:44.png",
"mimeType": "image/png",
"size": 89567
}
],
"links": [],
"isDraft": false,
"isLatestVersion": true,
"isEmpty": false,
"createdAt": "2025-03-25T10:48:34.66935+02:00",
"updatedAt": "2025-03-25T10:48:34.66935+02:00"
}
]
}
```
## Get Test Case
`GET /api/public/v0/project/{project_id}/tcase/{tcase_or_legacy_id}`
Get details of a single test case using its ID, sequence or legacy ID.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `tcase_or_legacy_id`: The test case identifier (can be one of test case UUID, sequence or legacy ID)
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/1
```
### Response Fields
```typescript
{
id: string // Unique identifier of the test case
legacyId: string // Legacy identifier of the test case. Empty string if the test case has no legacy ID
version: number // Version of the test case. Updates to test (except folder/pos) creates a new version
type: string // Type of the test case (`standalone` | `template` | `filled`)
title: string // Title of the test case
seq: number // Sequence number of the test case. Test cases in a project are assigned incremental sequence numbers
folderId: number // Identifier of the folder where the test case is placed
pos: number // Ordered position (0 based) of the test case in its folder
priority: string // Priority of the test case (`high` | `medium` | `low`)
comment: html // Test case precondition text. DEPRECATED, usable but prefer precondition object below
precondition: {
projectId: string, // Project id the precondition belongs to. Same as test cases'
id: number, // Id of the precondition. Not useful unless the precondition is shared
version: number, // Version of the precondition
title?: string, // Title of the precondition. Only populated for shared
type: 'standalone' | 'shared', // Type of the precondition
text: html, // Actual text contents of the precondition
isLatest: boolean, // Whether precondition's version is latest or not
createdAt: string,
updatedAt: string,
deletedAt?: string,
}
steps: Array<{ // List of test case steps
id: number // Unique identifier of the step
type: string // Type of the step (standalone | shared)
version: number // Version of the step (always 1 for standalone steps)
isLatest: boolean // Whether this is the latest version of the step (always true for standalone steps)
title?: string // Title of the step (only for shared steps)
subSteps?: Array<{ // List of sub steps (only for shared steps)
id: number // Unique identifier of the step
type: string // Type of the step (shared_sub_step)
version: number // Version of the step (same as parent step)
isLatest: boolean // Whether this is the latest version (same as parent step)
description: html // Details of the sub step
expected: html // Expected result from the sub step
data?: Array // Sub step test data items (see Step Test Data)
deletedAt?: string // Date the sub step was deleted on
}>
description?: html // Details of step (only for standalone steps)
expected?: html // Expected result from the step (only for standalone steps)
data?: Array // Step test data items, only for standalone steps (see Step Test Data)
deletedAt?: string // Date the step was deleted on
}>
tags: Array<{ // List of test case tags
id: number // Unique identifier of the tag
title: string // Title of the tag
}>
files: Array<{ // List of files attached to the test case
id: string // Unique identifier of the file
fileName: string // Name of the file
mimeType: string // Mime type of the file
size: number // Size of the file
url?: string // URL of the file (optional, not present in sample)
}>
requirements: Array<{ // Test case requirement (currently only single requirement is supported on UI)
id: string // Unique identifier of the requirement
text: string // Title of the requirement
url: string // URL of the requirement
}>
links: Array<{ // Additional links relevant to the test case
text: string // Title of the link
url: string // URL of the link
}>
customFields: { // Custom fields defined for the test case
[key: string]: { // Key-value pairs of custom field system names and corresponding details for the test case
value: string // Current value
isDefault: boolean // Whether default value is set by the system or selected by the user
}
}
parameterValues: { // The details of corresponding filled tcases (relevant only for template tcases)
tcaseId: string // ID of the filled tcase
tcaseVersion: number // Version of the filled tcase
values: { // Values corresponding to the parameters in the template tcase for this filled tcase
[key: string]: string
}
}
authorId: number // Unique identifier of the user who added the test case
isDraft: boolean // Whether the test case is still in draft state
isLatestVersion: boolean // Whether this is the latest version of the test case
isEmpty: boolean // Whether the test case is empty (has no comment and steps)
templateTCaseId?: string // Corresponding template test case ID, if it is a filled test case
numFilledTCases? number // Number of corresponding filled test cases, if it is a template test case
createdAt: string // Test case creation time (ISO 8601 format)
updatedAt: string // Test case updation time (ISO 8601 format)
}
```
### Sample Response
```json
{
"id": "1CJg36j1c_yFYPRcmZaoqp3",
"version": 6,
"legacyId": "",
"seq": 55,
"type": "standalone",
"folderId": 26,
"pos": 0,
"title": "User should see the content according to the \"About Us\" information",
"priority": "high",
"comment": "The \"About Us\" page is opened
",
"precondition": {
"projectId": "2HKj57k3z_YXYQVTdnPqrs8",
"id": 2,
"version": 3,
"type": "standalone",
"text": "The \"About Us\" page is opened
",
"isLatest": true,
"createdAt": "2025-03-25T10:48:14.243475+02:00",
"updatedAt": "2025-03-25T10:48:14.243475+02:00"
},
"authorId": 1,
"files": [
{
"id": "89f7a73e-043c-4fe1-beb3-9e8d8df55f28",
"fileName": "Screencast from 24-03-25 14:27:33.webm",
"mimeType": "video/webm",
"size": 555431
}
],
"links": [],
"requirements": [
{
"text": "AUTO-REQ-2 Automated Tests Requirements",
"url": "https://github.com/Hypersequent/bistro-e2e/docs/automated-testing/requirements#auto-req-2",
"id": "1CJg36j1s_WwGRdtSYt43VZ"
}
],
"tags": [
{ "id": 1, "title": "About Us" },
{ "id": 206, "title": "automation" },
{ "id": 3, "title": "REQ-4" }
],
"steps": [
{
"id": 1,
"type": "standalone",
"version": 1,
"isLatest": true,
"description": "Automated validation of About Us content
",
"expected": "Content matches expected About Us information
"
},
{
"id": 2,
"type": "shared",
"version": 3,
"isLatest": true,
"title": "About us validations",
"subSteps": [
{
"id": 3,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Verify company name and logo are displayed correctly
",
"expected": "Company name and logo match branding guidelines
"
},
{
"id": 4,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Check mission statement content
",
"expected": "Mission statement matches approved text
"
},
{
"id": 5,
"type": "shared_sub_step",
"version": 3,
"isLatest": true,
"description": "Validate team member information
",
"expected": "Team member profiles are accurate and complete
"
}
]
}
],
"customFields": {
"automation": {
"value": "Automated",
"isDefault": false
},
"known_issue": {
"value": "No",
"isDefault": true
}
},
"isDraft": false,
"isLatestVersion": true,
"isEmpty": false,
"createdAt": "2025-03-25T10:48:14.243475+02:00",
"updatedAt": "2025-03-25T10:48:14.243475+02:00"
}
```
## Get Test Case Edit History
`GET /api/public/v0/project/{project_id}/tcase/{tcase_or_legacy_id}/history`
Retrieves the edit history of a single test case — who changed what and when. This is the same data shown in the "Edit History" panel in the web interface. Entries are returned newest first, and history is available even for deleted test cases.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `tcase_or_legacy_id`: The test case identifier (can be one of test case UUID, sequence or legacy ID)
### Query Parameters
All query parameters are optional.
| Parameter | Type | Description | Example |
| --------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `offset` | number | Number of rows to skip before returning results. Combine with `limit` for offset-based pagination. | `offset=10` |
| `limit` | number | Maximum number of entries to return (0–5000). May be `0` to return only the total count (no rows). | `limit=10` |
| `page` | number | **Deprecated** — use `offset` instead. 1-based page number. Ignored when `offset` is set. If `limit` is omitted, a default of 10 is applied. | `page=1` |
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/55/history
```
### Response Fields
```typescript
{
total: number // Total number of edit history entries for the test case
offset?: number // Offset applied to the query, if any
limit?: number // Limit applied to the query, if any
page?: number // Echoes the deprecated page param when it was used
data: Array<{ // Edit history entries, newest first
id: number // Unique identifier of the entry
actionType: string // What changed (`create` | `change_type` | `delete` | `restore` | `title` | `priority` | `precondition` | `tags` | `steps` | `publish` | `others` | `version_rollback`)
tcaseId: string // Identifier of the test case
authorId: number // Unique identifier of the user who made the change
author: { // Details of the user who made the change
id: number // Unique identifier of the user
name: string // Name of the user
email: string // Email of the user
avatar?: string // Avatar URL of the user; fetching it requires authentication
role: string // Role of the user (`owner` | `admin` | `user` | `test-runner` | `viewer`)
}
oldValue?: string // Value before the change. Populated for `title`, `priority` and `change_type` changes; contains the version number for `version_rollback`
newValue?: string // Value after the change. Populated for the same action types as oldValue
tcaseVersion: number // Version of the test case this change produced
createdAt: string // Time of the change (ISO 8601 format)
}>
}
```
### Sample Response
```json
{
"total": 2,
"data": [
{
"id": 2,
"actionType": "title",
"tcaseId": "1CJg36j1c_yFYPRcmZaoqp3",
"authorId": 1,
"author": {
"id": 1,
"email": "jane@example.com",
"name": "Jane Doe",
"avatar": null,
"role": "admin"
},
"newValue": "User can log in with valid credentials",
"oldValue": "User can log in",
"tcaseVersion": 2,
"createdAt": "2026-08-05T10:48:34.66935+02:00"
},
{
"id": 1,
"actionType": "create",
"tcaseId": "1CJg36j1c_yFYPRcmZaoqp3",
"authorId": 1,
"author": {
"id": 1,
"email": "jane@example.com",
"name": "Jane Doe",
"avatar": null,
"role": "admin"
},
"newValue": null,
"oldValue": null,
"tcaseVersion": 1,
"createdAt": "2026-08-05T10:12:14.243475+02:00"
}
]
}
```
## Get Test Case Count
`GET /api/public/v0/project/{project_id}/tcase/count`
Returns the total number of test cases that match the specified filters. If no filters are provided, returns the total count of all test cases in the project.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Query Parameters
| Parameter | Type | Description | Example |
| ------------ | ------- | ----------------------------------------------------- | ----------------------------------- |
| `folders` | number | Filter by folder IDs | `folders=1&folders=2` |
| `recursive` | boolean | Include test cases in subfolders (requires `folders`) | `recursive=true` |
| `tags` | number | Filter by tag IDs | `tags=1&tags=2` |
| `priorities` | string | Filter by priority levels (high, medium, low) | `priorities=high&priorities=medium` |
| `draft` | boolean | Filter by draft status | `draft=true` |
### Example Requests
#### Basic Count
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count"
```
#### Filter Examples
1. **Folder-based counting**:
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?folders=1&recursive=true"
```
2. **Priority-based counting**:
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?priorities=high"
```
3. **Tag-based counting**:
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?tags=1&tags=2"
```
4. **Draft status counting**:
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?draft=true"
```
5. **Custom field counting**:
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?cf_automation=Automated"
```
### Response Format
```typescript
{
count: number // Total number of test cases matching the filters
}
```
### Example Response
```json
{
"count": 4
}
```
### Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project not found |
| 400 | Invalid filter parameters |
| 500 | Internal server error |
**Use Cases**
* Monitor test coverage by counting test cases across different folders
* Track high-priority test case volume
* Review draft test case count before publishing
* Plan test runs based on tagged test cases
**Filter Behavior**
* If no filters are specified, all test cases in the project are counted
* Different filters are combined with AND logic
* Multiple values for the same filter are combined with OR logic
* The `recursive` parameter only applies when `folders` is specified
## Create Test Case
`POST /api/public/v0/project/{project_id}/tcase`
Creates a new test case in the specified project. You can create both standalone and template test cases using this endpoint.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Request Body
```typescript
{
title: string // Required: Test case title (must be between 1-511 characters)
type: string // Required: Type of test case (`standalone` | `template`)
folderId: number // Required: ID of the folder where the test case will be placed
priority: string // Required: Test case priority (`high` | `medium` | `low`)
pos?: number // Optional: Position within the folder (0-based index)
comment?: html // Optional: Test case precondition. DEPRECATED, if precondition object is empty, comment is used to populated precondition.text
precondition?: // Optional: Test case precondition
| { sharedPreconditionId: number } // Use a shared precondition by specifying its unique id
| { text: html } // Or, use a standalone precondition with text
steps?: Array<{ // Optional: List of test case steps
// For shared steps
sharedStepId?: number // Unique identifier of the shared step
// For standalone steps
description?: html // Details of steps
expected?: html // Expected result from the step
data?: Array // Step test data items, max 20 (see Step Test Data)
}>
tags?: string[] // Optional: List of tag titles (max 255 characters each)
requirements?: Array<{ // Optional: Test case requirement
text: string // Required: Title of the requirement (must be between 1-255 characters)
url: string // Required: URL of the requirement (must be between 1-255 characters)
}>
files?: Array<{ // Optional: Files attached to the test case
id: string // Required: File identifier, typically returned by the upload file endpoint
fileName: string // Required: Original file name
mimeType: string // Required: MIME type of the file
size: number // Required: File size in bytes
url?: string // Optional: File URL returned by the upload file endpoint
}>
links?: Array<{ // Optional: Additional links relevant to the test case
text: string // Required: Title of the link (must be between 1-255 characters)
url: string // Required: URL of the link (must be between 1-255 characters)
}>
customFields?: { // Optional: Custom field values.
[key: string]: { // Custom field system names should be specified as keys. Only custom fields applied and enabled for a project should be specified
isDefault: boolean // Whether to set the default value. Should be true only if the custom field actually has a default value
value: string // Custom field value to be set. Should be specified only if not setting to the default value
}
}
parameterValues?: Array<{ // Optional: Values to substitute for parameters in the filled test cases (only relevant for template types)
values: { // Values for the parameters in the template test case to be substituted for this filled test case
[key: string]: string
}
}>
filledTCaseTitleSuffixParams?: string[] // Optional: Parameters to append to filled test case titles
isDraft?: boolean // Whether to create as draft, default false
}
```
* **Required fields**: `type`, `folderId`, `title`, `priority`
* **Test case types**: Only `standalone` and `template` can be created directly. `filled` test cases are automatically generated from template test cases.
* **Steps**: You can use either shared steps (by `sharedStepId`) or standalone steps (with `description`, `expected`, and/or `data`).
* **Step test data**: Standalone steps can include up to 20 `data` items (see Step Test Data). A step that references a shared step by `sharedStepId` must not include `data`.
* **Custom fields**: Must be created through the web UI before you can set their values via API.
* **Template test cases**: Use `parameterValues` to define parameter substitutions that will generate filled test cases.
* **Parameter names**: The keys of `parameterValues[].values` and the entries of `filledTCaseTitleSuffixParams` must start with a letter, contain only letters, digits, hyphens and underscores, end with a letter or digit, and be at most 255 characters. Placeholders inside the title, precondition and steps are not restricted this way - a `${...}` placeholder whose name breaks these rules is kept as literal text.
* **Position**: If `pos` is not specified, the test case will be added at the end of the folder.
* **Files**: Use the upload file endpoint first. Public upload responses include `id` and `url`; when attaching files to a test case, also provide the matching `fileName`, `mimeType`, and `size`.
### Example Requests
#### Create a Simple Standalone Test Case
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"type": "standalone",
"folderId": 26,
"title": "User should be able to login with valid credentials",
"priority": "high",
"precondition": {
"text": "User has valid account credentials
"
},
"isDraft": false,
"steps": [
{
"description": "Navigate to login page
",
"expected": "Login form is displayed
"
},
{
"description": "Enter valid username and password
",
"expected": "Credentials are accepted
",
"data": [
{
"type": "text",
"label": "Credentials",
"data": { "value": "user@example.com / s3cret", "format": "plaintext" }
},
{
"type": "link",
"label": "Test accounts",
"data": { "value": "https://example.com/wiki/test-accounts" }
}
]
},
{
"description": "Click login button
",
"expected": "User is redirected to dashboard
"
}
],
"tags": ["authentication", "login"],
"requirements": [
{
"text": "REQ-001: User Authentication",
"url": "https://docs.example.com/requirements/auth"
}
]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase
```
#### Create a Template Test Case with Parameters
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"type": "template",
"folderId": 26,
"title": "User should be able to login with ${browser} browser on ${device}",
"priority": "medium",
"precondition": {
"text": "Testing login functionality across different browsers and devices
"
},
"isDraft": false,
"steps": [
{
"description": "Open ${browser} browser on ${device}
",
"expected": "Browser opens successfully
"
},
{
"description": "Navigate to login page
",
"expected": "Login form is displayed correctly
"
},
{
"description": "Enter valid credentials and submit
",
"expected": "Login is successful on ${device}
"
}
],
"tags": ["authentication", "cross-browser", "responsive"],
"parameterValues": [
{
"values": {
"browser": "Chrome",
"device": "Desktop"
}
},
{
"values": {
"browser": "Firefox",
"device": "Desktop"
}
},
{
"values": {
"browser": "Safari",
"device": "Mobile"
}
}
],
"filledTCaseTitleSuffixParams": ["browser", "device"]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase
```
#### Create Test Case with Custom Fields
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"type": "standalone",
"folderId": 26,
"title": "API endpoint validation test",
"priority": "high",
"precondition": {
"text": "Test API endpoint response and data validation
"
},
"isDraft": false,
"steps": [
{
"description": "Send GET request to /api/users endpoint
",
"expected": "Response status is 200
"
},
{
"description": "Validate response JSON structure
",
"expected": "All required fields are present
"
}
],
"customFields": {
"automation": {
"value": "Automated"
},
"test_type": {
"value": "API"
}
},
"tags": ["api", "validation"]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase
```
#### Create Draft Test Case
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"type": "standalone",
"folderId": 26,
"title": "Work in progress test case",
"priority": "low",
"precondition": {
"text": "This test case is still being developed
"
},
"isDraft": true,
"steps": [
{
"description": "Step 1 - to be defined
",
"expected": "Expected result - to be defined
"
}
]
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase
```
### Response Fields
```typescript
{
id: string // Unique identifier of the created test case
seq: number // Sequence number of the test case in the project
}
```
### Example Response
Status: 201 Created
```json
{
"id": "1CJg36j1c_yFYPRcmZaoqp3",
"seq": 57
}
```
### Error Responses
| Status Code | Description |
| ----------- | ---------------------------------------------- |
| 400 | Invalid request data or validation errors |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project or folder not found |
| 409 | Position conflict or duplicate requirement |
| 500 | Internal server error while creating test case |
**Template Test Cases**
* Template test cases use `${parameter}` syntax in titles, comments, and steps
* Parameter values are substituted when creating filled test cases
* Multiple parameter value sets create multiple filled test cases
* Filled test cases inherit all properties from their template parent
* Updates to template test cases automatically update corresponding filled test cases
## Update Test Case
`PATCH /api/public/v0/project/{project_id}/tcase/{tcase_or_legacy_id}`
Updates a test case using its ID, sequence or legacy ID. Only users with role User or higher are allowed to update test cases.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
* `tcase_or_legacy_id`: The test case identifier (can be one of test case UUID, sequence or legacy ID)
### Request Body
```typescript
{
title?: string // Optional: Test case title (must be between 1-511 characters)
priority?: string // Optional: Test case priority (`high` | `medium` | `low`)
comment?: html // Optional: Test case precondition. DEPRECATED, if precondition object is not present but comment is, value of comment will be used to populated precondition.text
precondition?: // Optional: Test case precondition
| { sharedPreconditionId: number } // Use a shared precondition by specifying its unique id
| { text: html } // Or, use a standalone precondition with text
isDraft?: boolean // Optional: To publish a draft test case. A published test case cannot be converted to draft
steps?: Array<{ // Optional: List of test case steps
// For shared steps
sharedStepId?: number // Unique identifier of the shared step
// For standalone steps
description?: html // Details of steps
expected?: html // Expected result from the step
data?: Array // Step test data items, max 20 (see Step Test Data)
}>
tags?: string[] // Optional: List of test case tags (title)
requirements?: Array<{ // Optional: Test case requirement
text: string // Title of the requirement (must be between 1-255 characters)
url: string // URL of the requirement (must be between 1-255 characters)
}>
files?: Array<{ // Optional: Files attached to the test case
id: string // File identifier, typically returned by the upload file endpoint
fileName: string // Original file name
mimeType: string // MIME type of the file
size: number // File size in bytes
url?: string // File URL returned by the upload file endpoint
}>
links?: Array<{ // Optional: Additional links relevant to the test case
text: string // Title of the link (must be between 1-255 characters)
url: string // URL of the link (must be between 1-255 characters)
}>
customFields?: { // Optional: Custom field values to update. Only specified custom fields are updated, others are left as is
[key: string]: { // Custom field system names should be specified as keys. Only custom fields applied and enabled for a project should be specified
isDefault: boolean // Whether to set the default value. Should be true only if the custom field actually has a default value
value: string // Custom field value to be set. Should be specified only if not setting to the default value
}
}
parameterValues?: Array<{ // Optional: Values to substitute for parameters in the filled test cases (only relevant for template types)
tcaseId: string // Should be specified in order to update existing filled test case. Otherwise a new filled test case would be created. If an existing filled test case is absent in the update request, it is deleted
values: { // Values for the parameters in the template test case to be substituted for this filled test case
[key: string]: string
}
}>
}
```
* All top-level fields are optional. Include only the top-level fields that need to be updated in the request.
* For `customFields`, only the specified `key` values are updated; others remain unchanged.
* Steps can be either `shared` or `standalone`. To use a shared step, specify `sharedStepId`. For standalone steps, specify `description`, `expected`, and/or `data`.
* Standalone steps can include up to 20 `data` items (see Step Test Data). If you update `steps`, send the complete step list including each step's `data` — sending a step with an empty or omitted `data` list removes all its test data, and a step whose only content was `data` is dropped from the test case entirely. A step that references a shared step by `sharedStepId` must not include `data`.
* Filled test case type cannot be updated.
* If you update `files`, send the complete list of files you want stored on the test case.
* The keys of `parameterValues[].values` and the entries of `filledTCaseTitleSuffixParams` must follow the parameter name rules described under the create endpoint.
### Example Request
#### Switch to a Shared Precondition, Updating Test Case Title, Priority And Custom Field Value
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"title": "Changing to corresponding cursor after hovering the element",
"precondition": {
"id": 42
},
"priority": "high",
"customFields": {
"automation": {
"isDefault": false,
"value": "Automated"
}
}
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/1
```
#### Updating Multiple Custom Fields Values
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-H "Content-Type: application/json" \
-d '{
"customFields": {
"automation": {
"isDefault": false,
"value": "Cannot be Automated"
},
"known_issue": {
"isDefault": true
}
}
}' \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/56
```
* Custom fields and shared steps must be created through the web UI before you can set their values via API
* Use the system name (lowercase with underscores) of the custom field, not its display name
* The field value must match one of the predefined options for the custom field
* When updating custom fields, only the fields you specify will be modified
* To remove a custom field value, you need to set it to an empty string (if allowed by the field configuration)
### Example Response
Status: 200 OK
```json
{
"message": "Test case updated"
}
```
### Error Responses
| Status Code | Description |
| ----------- | ---------------------------------------------- |
| 400 | Converting a published test case to draft |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project or test case not found |
| 500 | Internal server error while updating test case |
---
# Custom Fields
URL: /docs/api/tcases_custom_fields
Custom fields allow you to extend test cases with additional metadata specific to your organization's needs. You can use custom fields to track information like automation status, test environment, component ownership, or any other project-specific attributes.
## Types of Custom Fields
In QA Sphere, there are four types of custom fields:
1. **Text**: A plain string value.
2. **Rich Text**: Text supporting formatting, held as HTML (see [HTML Support](https://qasphere.com/docs/api/html-support)).
3. **Dropdown**: One value out of the field's list of options.
4. **Checkbox**: A boolean.
* **Single option checkbox**: the option holds the label of the checked value, and an unchecked field holds an empty value.
* **Two option checkbox**: option order is significant, the first option holds the label of the checked value and the second one that of the unchecked value. The field always holds one of the two.
Every custom field has a display `name` and a `systemName`. The display name can be changed at any time, the system name cannot.
Keep system names short and readable, such as `automation` or `test_environment`, since they appear in test case payloads and filters and cannot be changed later.
A field can be marked `required` and can carry a `defaultValue`, which is applied to test cases that do not provide a value of their own. A required field always has a default value. For a checkbox, both follow from its options instead of being configurable:
* **Single option checkbox**: never required and has no default value.
* **Two option checkbox**: always required, with its unchecked value as the default value.
Only fields with `enabled: true` are meant to be used, and a field applies either to all projects (`allowAllProjects: true`) or only to the projects listed in `allowedProjectIds`.
## Using Custom Fields in Test Cases
Custom fields can be used when creating or updating test cases. Values are keyed by the field's `systemName`, not by its `id`.
### Creating Test Cases with Custom Fields
When creating a test case, you can include custom field values using the `customFields` object:
```json
{
"type": "standalone",
"folderId": 1,
"title": "Login Test",
"priority": "high",
"customFields": {
"automation": {
"value": "Automated"
},
"test_environment": {
"value": "production"
},
"regression": {
"value": "Yes"
},
"notes": {
"value": "Covers the happy path only.
"
}
}
}
```
### Custom Field Value Structure
Each custom field value in the `customFields` object should have:
* `value`: The actual value for the field. For dropdown and checkbox fields it must match one of the option `value` strings from the field's `options` array. An empty value is accepted only by a field that is not required, which is why a single option checkbox always takes one and a two option checkbox never does. Richtext values are HTML and are sanitized server-side
* `isDefault`: Boolean indicating whether to use the field's default value. When `true`, `value` must either be left out or match the field's default value, and the field must have a default value at all
### Using Default Values
You can use the default value for a custom field by setting `isDefault: true`, leaving out `value` or setting it to the field's default value:
```json
{
"customFields": {
"automation": {
"isDefault": true
}
}
}
```
The flag ties the test case value to the field definition. Whenever the field's `defaultValue` changes afterwards, the new default is applied to every test case value carrying `isDefault: true` and to every test case that has no value for the field, while clearing the field's default value removes those values again.
Default values are also applied without the flag:
* In a create request, a field left out of `customFields` takes the field's default value, if it has one, and is marked with `isDefault: true`. A required field does the same when an empty value is passed, while for a field that is not required an empty value is stored as an empty value.
* In an update request, only the fields present in `customFields` are changed and no default value is filled in. A required field can therefore not be given an empty value, unless `isDefault` is set.
### Filtering Test Cases by Custom Fields
Custom fields can also be used to filter test cases when listing them. Use the format `cf_{systemName}=value` in query parameters:
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?cf_automation=Automated"
```
Multiple values for the same custom field can be specified:
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
"https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?cf_automation=Automated&cf_automation=In%20Progress"
```
## List Project Custom Fields
`GET /api/public/v0/project/{project_id}/custom-field`
Returns all custom fields available for the project. This endpoint is useful when creating or updating test cases that include custom field values.
### Path Parameters
* `project_id`: The project identifier (can be either the project code or UUID)
### Response
Status: 200 OK
```typescript
{
customFields: Array<{
id: string // Unique custom field identifier
type: 'text' | 'dropdown' | 'checkbox' | 'richtext' // Field type
systemName: string // System identifier for the field (used in API requests)
name: string // Display name of the field
required: boolean // Whether the field is required for test cases
enabled: boolean // Whether the field is currently enabled
options?: Array<{
// Available options, only for dropdown and checkbox fields
id: string // Option identifier
value: string // Option display value
}>
defaultValue?: string // Default value for the field, implied by the options for checkbox fields
pos: number // Display position/order
allowAllProjects: boolean // Whether the field is available to all projects
allowedProjectIds?: string[] // List of project IDs if not available to all projects
createdAt: string // ISO 8601 timestamp when the field was created
updatedAt: string // ISO 8601 timestamp when the field was last updated
}>
}
```
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/custom-field
```
### Example Response
```json
{
"customFields": [
{
"id": "1customfield_1111111111111",
"type": "dropdown",
"systemName": "automation",
"name": "Automation",
"required": false,
"enabled": true,
"options": [
{
"id": "1customfieldoption_1111111111111",
"value": "Planned"
},
{
"id": "1customfieldoption_1111111111112",
"value": "Cannot be Automated"
},
{
"id": "1customfieldoption_1111111111113",
"value": "In Progress"
},
{
"id": "1customfieldoption_1111111111114",
"value": "Automated"
},
{
"id": "1customfieldoption_1111111111115",
"value": "Broken"
}
],
"defaultValue": "Planned",
"pos": 0,
"allowAllProjects": true,
"allowedProjectIds": [],
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
},
{
"id": "1customfield_1111111111112",
"type": "text",
"systemName": "test_environment",
"name": "Test Environment",
"required": true,
"enabled": true,
"options": [],
"defaultValue": "staging",
"pos": 1,
"allowAllProjects": false,
"allowedProjectIds": ["1project_1111111111111"],
"createdAt": "2024-01-20T14:15:00Z",
"updatedAt": "2024-01-20T14:15:00Z"
},
{
"id": "1customfield_1111111111113",
"type": "checkbox",
"systemName": "regression",
"name": "Regression",
"required": true,
"enabled": true,
"options": [
{
"id": "1customfieldoption_1111111111116",
"value": "Yes"
},
{
"id": "1customfieldoption_1111111111117",
"value": "No"
}
],
"defaultValue": "No",
"pos": 2,
"allowAllProjects": true,
"allowedProjectIds": [],
"createdAt": "2024-02-01T09:00:00Z",
"updatedAt": "2024-02-01T09:00:00Z"
},
{
"id": "1customfield_1111111111114",
"type": "richtext",
"systemName": "notes",
"name": "Notes",
"required": false,
"enabled": true,
"options": [],
"pos": 3,
"allowAllProjects": true,
"allowedProjectIds": [],
"createdAt": "2024-02-05T11:45:00Z",
"updatedAt": "2024-02-05T11:45:00Z"
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 404 | Project not found |
| 500 | Internal server error |
## Related Resources
* [Test Cases](https://qasphere.com/docs/api/tcases) - Create and manage test cases with custom fields
* [Authentication](https://qasphere.com/docs/api/authentication) - Learn about API authentication
---
# Upload Files
URL: /docs/api/upload_file
The upload file endpoints allow you to upload files to QA Sphere.
Uploaded files can be referenced in the `files` field of public test case create/update requests and inside HTML fields. Public result endpoints currently support links only and do not accept file attachments.
## Upload File
`POST /api/public/v0/file`
Upload a file to QA Sphere.
### Request Body
Request body should be a `multipart/form-data` with a `file` form-field.
### Limits
* Maximum file size: `50 MiB`
### Response Fields
| Field | Type | Description |
| ----------- | -------- | -------------------------------------------------------------------------------- |
| `id` | `string` | Unique identifier for the uploaded file |
| `stableUrl` | `string` | Host-relative URL of the uploaded file; safe across subdomain changes (use this) |
| `url` | `string` | Absolute URL of the uploaded file |
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-F 'file=@"/path/to/file"' \
https://your-company.your-region-code.qasphere.com/api/public/v0/file
```
### Example Response
```json
{
"id": "1CJLabPkq_PWeS4siaKcB1k",
"stableUrl": "/api/file/1CJLabPkq_PWeS4siaKcB1k",
"url": "https://your-company.your-region-code.qasphere.com/api/file/1CJLabPkq_PWeS4siaKcB1k"
}
```
### Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------- |
| 400 | Invalid multipart request or missing `file` |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 413 | File exceeds the `50 MiB` limit |
| 500 | Internal server error while uploading file |
## Upload Files In Batch
`POST /api/public/v0/file/batch`
Upload multiple files to QA Sphere in a single request.
### Request Body
Request body should be a `multipart/form-data` with one or more `files` form-fields.
### Limits
* Maximum files per request: `100`
* Maximum file size: `50 MiB` per file
* Maximum request body size: `500 MiB`
### Response Fields
```typescript
{
files: Array<{
id: string // Unique identifier for the uploaded file
stableUrl: string // Host-relative URL; safe across subdomain changes (use this)
url: string // Absolute URL
}>
}
```
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
-F 'files=@"/path/to/file1"' \
-F 'files=@"/path/to/file2"' \
https://your-company.your-region-code.qasphere.com/api/public/v0/file/batch
```
### Example Response
```json
{
"files": [
{
"id": "1CJLabPkq_PWeS4siaKcB1k",
"stableUrl": "/api/file/1CJLabPkq_PWeS4siaKcB1k",
"url": "https://your-company.your-region-code.qasphere.com/api/file/1CJLabPkq_PWeS4siaKcB1k"
},
{
"id": "1CJLabPkq_Q2x7A7Lwu7GsL5",
"stableUrl": "/api/file/1CJLabPkq_Q2x7A7Lwu7GsL5",
"url": "https://your-company.your-region-code.qasphere.com/api/file/1CJLabPkq_Q2x7A7Lwu7GsL5"
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | --------------------------------------------------------------- |
| 400 | Invalid multipart request, no files provided, or too many files |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions or suspended tenant |
| 413 | A file exceeds `50 MiB` or request body exceeds `500 MiB` |
| 500 | Internal server error while uploading files |
\:::tip Use `stableUrl`
Prefer the `stableUrl` field when referencing an uploaded file. It is host-relative (e.g. `/api/file/{id}`) and keeps resolving even after your tenant's subdomain changes. URLs that embed the old subdomain stop working once the subdomain changes.
\:::
\:::note Relative file URLs in responses
Read endpoints (e.g. `GET /tcase/{id}`, `GET /run/{id}`) return file references **embedded in HTML fields**, such as `precondition.text`, `steps[].description`, `steps[].expected`, run/plan descriptions, and comments, as host-relative URLs (`/api/file/{id}`). To fetch such an attachment, prepend your tenant base URL (e.g. `https://your-company.your-region-code.qasphere.com`). The dedicated `files[].url` field on the test-case response remains absolute.
\:::
---
# Users
URL: /docs/api/users
The users endpoint allows administrators to retrieve information about all users in the system.
## List Users
`GET /api/public/v0/users`
Returns a list of all users in the system. This endpoint is restricted to administrators only.
### Authentication
Requires an API key with Admin role permissions. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Response Format
```typescript
{
users: Array<{
email: string // User's email address
name: string // User's display name
role: string // User's role ('owner' | 'admin' | 'user' | 'test-runner' | 'viewer')
authorizationTypes: Array<'password' | 'google'> // Authentication methods
totpEnabled: boolean // Two-factor authentication status
createdAt: string // ISO 8601 timestamp
lastActivity: string // ISO 8601 date
}>
}
```
### User Roles
| Role | Permissions |
| --------------- | ----------------------------------------- |
| **Owner** | Full system access with tenant management |
| **Admin** | Full project access with user management |
| **User** | Can create and manage test cases and runs |
| **Test Runner** | Can execute test runs only |
| **Viewer** | Read-only access to projects |
### Example Request
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/users
```
### Example Response
```json
{
"users": [
{
"email": "admin@example.com",
"name": "System Admin",
"role": "admin",
"authorizationTypes": ["password"],
"totpEnabled": true,
"createdAt": "2024-01-01T00:00:00Z",
"lastActivity": "2024-11-14"
},
{
"email": "tester@example.com",
"name": "Test Engineer",
"role": "test-runner",
"authorizationTypes": ["password", "google"],
"totpEnabled": false,
"createdAt": "2024-03-15T00:00:00Z",
"lastActivity": "2024-11-14"
}
]
}
```
### Error Responses
| Status Code | Description |
| ----------- | ------------------------------------------- |
| 401 | Invalid or missing API key |
| 403 | Insufficient permissions (non-admin access) |
| 500 | Internal server error |
### Important Notes
| Requirement | Description |
| ----------- | -------------------------------------------------- |
| Email | Must be valid and unique within the system |
| User names | Must be between 1 and 255 characters |
| Dates | Creation and activity dates are in ISO 8601 format |
| Access | Only administrators can access this endpoint |
This endpoint enables you to:
* Audit user access and roles
* Monitor user activity
* Verify authentication methods
* Check 2FA adoption
## Get Current User
`GET /api/public/v0/users/me`
Returns the user identity associated with the calling credential — the API key creator, or the user who consented to an OAuth authorization. Available to any authenticated role.
### Authentication
Requires either an API key or an OAuth Bearer token. See [Authentication](https://qasphere.com/docs/api/authentication) for more details.
### Response Format
```typescript
{
user: {
id: number // User's numeric ID
email: string // User's email address
name: string // User's display name
avatar: string | null // Avatar URL, if set; fetching it requires authentication
role: 'owner' | 'admin' | 'user' | 'test-runner' | 'viewer'
}
}
```
### Example Request (API Key)
```bash
curl \
-H "Authorization: ApiKey your.api.key.here" \
https://your-company.your-region-code.qasphere.com/api/public/v0/users/me
```
### Example Request (OAuth Bearer)
```bash
curl \
-H "Authorization: Bearer your-oauth-access-token" \
https://your-company.your-region-code.qasphere.com/api/public/v0/users/me
```
### Example Response
```json
{
"user": {
"id": 42,
"email": "you@example.com",
"name": "Your Name",
"avatar": null,
"role": "admin"
}
}
```
### Error Responses
| Status Code | Description |
| ----------- | ----------------------------- |
| 401 | Invalid or missing credential |
| 500 | Internal server error |
---
# ClickUp
URL: /docs/clickup
QA Sphere allows you to integrate with ClickUp using the Custom Issue Tracker feature. This integration enables you to create ClickUp tasks directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your ClickUp workspace.
## Configuring ClickUp as a Custom Issue Tracker
To integrate ClickUp into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "ClickUp" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new task in your ClickUp workspace. For example:
```
https://app.clickup.com/[WORKSPACE_ID]/[SPACE_ID]/[LIST_ID]/create
```
* **Title Extraction Rule**: Enter the rule that matches your ClickUp task URL structure. For example:
```
https://app.clickup.com/t/$(id)
```
6. Click **Save** to add the ClickUp integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Task Title based on the URL. For ClickUp, you'll want to use `$(id)` as ClickUp uses unique task IDs. The rule you enter should match the structure of your ClickUp task URLs.
### Finding Your Workspace and List IDs
To find your ClickUp IDs:
1. Navigate to your desired List in ClickUp
2. The Workspace ID and List ID can be found in the URL when viewing the list
3. The URL format is typically: `app.clickup.com/[WORKSPACE_ID]/v/l/[LIST_ID]`
## Using ClickUp Integration
To create a ClickUp task during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the ClickUp task creation interface. The task details will be pre-filled based on your extraction rule.
Complete the task details in ClickUp and create the task. Once created, you can copy the task URL and paste it back into QA Sphere to link the task to your test case.
All tasks created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of ClickUp Integration
* **Customizable Views**: Take advantage of ClickUp's multiple view options (List, Board, Calendar, etc.).
* **Task Dependencies**: Utilize ClickUp's task relationship features.
* **Time Tracking**: Integrate QA activities with ClickUp's time tracking capabilities.
* **Custom Fields**: Leverage ClickUp's custom fields for detailed task information.
* **Automated Workflows**: Connect your QA process with ClickUp's automation features.
By leveraging this custom integration, your team can maintain a cohesive and efficient testing and issue management process across QA Sphere and ClickUp, tailored to your specific project needs.
## Best Practices
1. **Workspace Organization**: Create a dedicated Space or List for QA-related tasks.
2. **Custom Statuses**: Set up QA-specific statuses in ClickUp to match your testing workflow.
3. **Templates**: Use ClickUp task templates to standardize issue reporting.
4. **Custom Fields**: Configure custom fields to capture test-specific information.
5. **Notifications**: Set up appropriate notification rules for QA tasks.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link is correct and includes the proper Workspace and List IDs.
2. Ensure your Title Extraction Rule correctly matches your ClickUp task URL structure.
3. Verify that you have the necessary permissions in your ClickUp workspace.
4. Make sure you're logged into ClickUp in your browser for seamless task creation.
5. Check that you're using the correct workspace hierarchy (Workspace → Space → List).
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Document 360
URL: /docs/document360
QA Sphere allows you to integrate with Document 360 using the Custom Issue Tracker feature. This integration enables you to create Document 360 tickets directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your documentation system.
## Configuring Document 360 as a Custom Issue Tracker
To integrate Document 360 into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Document 360" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new ticket in your Document 360 portal. For example:
```
https://[YOUR_PORTAL].document360.io/tickets/new
```
* **Title Extraction Rule**: Enter the rule that matches your Document 360 ticket URL structure. For example:
```
https://[YOUR_PORTAL].document360.io/tickets/$(id:num)
```
6. Click **Save** to add the Document 360 integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Ticket Title based on the URL. For Document 360, you'll want to use `$(id:num)` as Document 360 uses numeric ticket IDs. The rule you enter should match the structure of your Document 360 ticket URLs.
### Finding Your Portal URL
To find your Document 360 Portal URL:
1. Log into your Document 360 account
2. Your portal name appears in the URL after logging in
3. It can also be found in Portal Settings
4. This name will be used in place of `[YOUR_PORTAL]` in your URLs
## Using Document 360 Integration
To create a Document 360 ticket during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Document 360 ticket creation interface. The ticket details will be pre-filled based on your extraction rule.
Complete the ticket details in Document 360 and submit the ticket. Once created, you can copy the ticket URL and paste it back into QA Sphere to link the ticket to your test case.
All tickets created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of Document 360 Integration
* **Documentation Link**: Directly connect issues with related documentation pages.
* **Version Control**: Track issues across different documentation versions.
* **Category Management**: Organize issues within Document 360's category structure.
* **Knowledge Base Integration**: Link tickets to specific documentation articles.
* **Feedback Management**: Connect user feedback with QA findings.
By leveraging this custom integration, your team can maintain a cohesive workflow between QA testing and documentation management, ensuring comprehensive issue tracking and resolution.
## Best Practices
1. **Category Structure**: Create a dedicated category for QA-related tickets.
2. **Custom Fields**: Set up custom fields to capture test-specific information.
3. **Version Tagging**: Use consistent version tagging for documentation-related issues.
4. **Article Links**: Include relevant documentation links in ticket descriptions.
5. **Feedback Integration**: Connect user feedback with QA findings when applicable.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link includes the correct portal name.
2. Ensure your Title Extraction Rule correctly matches your Document 360 ticket URL structure.
3. Verify that you have the necessary permissions in Document 360.
4. Make sure you're logged into Document 360 in your browser for seamless ticket creation.
5. Check that your portal settings allow external ticket creation.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# GitLab
URL: /docs/gitlab
QA Sphere allows you to integrate with GitLab using the Custom Issue Tracker feature. This integration enables you to create GitLab issues directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your GitLab projects.
## Configuring GitLab as a Custom Issue Tracker
To integrate GitLab Issues into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom Issue Tracker** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "GitLab" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new issue in your GitLab project. For example:
```
https://gitlab.com/your-group/your-project/-/issues/new
```
* **Title Extraction Rule**: Enter the rule that matches your GitLab issue URL structure. For example:
```
https://gitlab.com/your-group/your-project/-/issues/$(id:num)
```
6. Click **Save** to add the GitLab integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Issue Title based on the URL. For GitLab, you typically want to use `$(id:num)` as GitLab uses numeric IDs for issues. The rule you enter should match the structure of your GitLab issue URLs.
## Using GitLab Issues Integration
To create a GitLab issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the GitLab new issue page. The issue title will be pre-filled based on your extraction rule.
Complete the issue details in GitLab and submit the issue. Once created, you can copy the issue URL and paste it back into QA Sphere to link the issue to your test case.
All issues created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of GitLab Integration
* **Flexibility**: Customize the integration to match your specific GitLab project structure.
* **Seamless Workflow**: Quickly access GitLab's issue creation page from within QA Sphere.
* **Consistency**: Ensure all issues are properly documented and tracked in your GitLab project.
* **Traceability**: Easily link test cases to specific GitLab issues for better tracking.
* **Efficiency**: Reduce time spent switching between QA Sphere and GitLab.
By leveraging this custom integration, your team can maintain a cohesive and efficient testing and issue management process across QA Sphere and GitLab, tailored to your specific project needs.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link is correct and accessible.
2. Ensure your Title Extraction Rule correctly matches your GitLab issue URL structure.
3. Verify that you have the necessary permissions in your GitLab project to create issues.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Overview
URL: /docs/custom-issue-trackers
QA Sphere provides flexible integration with virtually any issue tracking system through its Custom Issue Tracker feature. This guide explains how to configure custom issue trackers and provides examples for popular systems.
## Configuring Custom Issue Trackers
To integrate any issue tracker into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. Provide the required details:
1. **Issue Tracker Name** - A name to identify your issue tracker integration.
2. **New Issue Link** - The URL for creating new issues on your issue tracker. QA Sphere will offer an option to easily navigate to this page while testing.
3. **Title Extraction Rule** - Allows QA Sphere to easily extract the issue identifier and title from its link.
4. **Value of $(project) for this project** - Shown only if either link contains the `$(project)` parameter. See [Per-Project Parameter](#per-project-parameter).
6. Click **Add** to complete the integration.
## Capturing Groups and Title Extraction Rule
The Title Extraction Rule in custom issue tracker configuration uses capturing groups to properly parse and store issue information.
These rules help QA Sphere understand the structure of your issue tracker's URLs.
### Basic Syntax
The basic syntax for capturing groups includes:
* $(id) - Captures any characters until the next delimiter
* $(id\:num) - Captures only numeric characters
* $(title) - Captures the issue title
### Examples of Capturing Groups
* **Basic numeric ID** - `https://yourtool.com/issues/$(id:num)`
* **Title and ID combination** - `https://yourtool.com/$(title)-$(id)`
* **Project and issue number** - `https://yourtool.com/$(project)/issues/$(id:num)`
## Per-Project Parameter
Some issue trackers require a project identifier in the URL, and that identifier differs for every QA Sphere project. To handle this, both the **New Issue Link** and the **Title Extraction Rule** may contain the `$(project)` parameter. Unlike `$(id)` and `$(title)`, `$(project)` is not a capturing group: QA Sphere replaces it with a value that you set separately for each project the integration is linked to.
This lets you configure the issue tracker once and reuse it across projects.
### Setting the Value
QA Sphere asks for the value whenever the integration is linked to a project:
* When you add a new custom issue tracker from a project, the **Value of $(project) for this project** field appears in the dialog as soon as either link contains `$(project)`.
* When you link an existing custom issue tracker to another project, QA Sphere opens a **Project Parameter** dialog that asks for the value and shows a preview of the resulting new issue link.
To change the value later, open **Settings → Issue Trackers**, find the row in the **Project Mapping** table, and click the pencil icon. The table shows the current value in the **Repository/Project/Team** column. If the links use `$(project)` but no value is set for the project, the column shows `$(project) not set` and the links are unavailable until you set it.
### Example
Configure the integration once:
* **New Issue Link** - `https://mytool.example/new-issue?project=$(project)`
* **Title Extraction Rule** - `https://mytool.example/browse/$(project)/$(id:num)`
Then link it to a project and enter `42` as the value. For that project, QA Sphere uses:
* New issue link - `https://mytool.example/new-issue?project=42`
* Title extraction rule - `https://mytool.example/browse/42/$(id:num)`
Another project can use the same integration with a different value, such as `77`.
### Whole-URL Templates
A link may also start with `$(project)`, in which case the value supplies the entire base URL. For example, the **New Issue Link** `$(project)/new-issue` with the value `https://mytool.example/team-a` resolves to `https://mytool.example/team-a/new-issue`.
The resolved link must be a valid `http` or `https` URL. QA Sphere rejects a value that produces an invalid URL.
## Using Custom Issue Trackers
Once configured, the Custom Issue Tracker integration enables you to link issues from your issue tracker to test case results in QA Sphere. To link an issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issues** and select one of the following options:
1. **Link issue** - Add a link to an existing issue in the issue tracker. QA Sphere will use the configured title extraction rule for the issue tracker to automatically populate the issue title, which can be updated if needed.
2. **Generate with AI** - Use test case details and result comments to auto-generate an issue title and description with the help of AI. Use these details to manually create an issue in the issue tracker, then enter the corresponding URL in QA Sphere. QA Sphere will again use the configured title extraction rule for the issue tracker to automatically populate the issue title, which can be updated if required.
All issues linked to the test case will be saved under the Action History for this test run, providing a clear documentation trail.
* AI issue generation may fail if there is insufficient context from the test case details and result comments to accurately determine the issue observed during testing.
* AI issue generation is not available when batch-adding results for multiple test cases simultaneously.
## Available Integration Examples
We provide detailed configuration guides for many popular issue tracking systems:
* [Jira](https://qasphere.com/docs/jira-custom) (Alternative Method) - Note: [Native Jira integration](https://qasphere.com/docs/jira) is recommended
* [Trello](https://qasphere.com/docs/trello)
* [GitLab](https://qasphere.com/docs/gitlab)
* [Notion](https://qasphere.com/docs/notion)
* [YouTrack](https://qasphere.com/docs/youtrack)
* [ClickUp](https://qasphere.com/docs/clickup)
* [Zendesk](https://qasphere.com/docs/zendesk)
* [Sentry.io](https://qasphere.com/docs/sentry)
* [Zoho Desk](https://qasphere.com/docs/zoho-desk)
* [Document 360](https://qasphere.com/docs/document360)
* [Nuclino](https://qasphere.com/docs/nuclino)
Click on any of the links above to view detailed configuration instructions for that specific issue tracker.
## Troubleshooting
If your custom issue tracker integration isn't working as expected:
* **URL Structure**: Verify that your New Issue Link is correct and accessible.
* **Extraction Rule**: Ensure your Title Extraction Rule matches the actual URL structure of your issues.
* **Project Parameter**: If your links use `$(project)`, confirm that a value is set for the project in the Project Mapping table and that the resolved URL is correct.
* **Permissions**: Check that you have the necessary permissions in both QA Sphere and the target issue tracker.
* **Special Characters**: If issues contain special characters, ensure they're properly handled in your extraction rules.
For further assistance, contact QA Sphere support at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Jira (Custom Integration)
URL: /docs/jira-custom
> **Note**: QA Sphere provides a [native Jira integration](https://qasphere.com/docs/jira) which offers enhanced features and a more streamlined experience. This custom integration method should only be used in specific cases where the native integration cannot be used.
QA Sphere allows you to integrate with Jira using the Custom Issue Tracker feature as an alternative to the native integration. This integration enables you to create Jira issues directly while going through test cases in a test run.
## Configuring Jira as a Custom Issue Tracker
To integrate Jira using the custom issue tracker feature, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Jira" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new issue in your Jira project. For example:
```
https://your-domain.atlassian.net/secure/CreateIssue.jspa?pid=[YOUR_PROJECT_ID]
```
* **Title Extraction Rule**: Enter the rule that matches your Jira issue URL structure. For example:
```
https://your-domain.atlassian.net/browse/[YOUR_PROJECT_ID]-$(id:num)
```
6. Click **Save** to add the Jira integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Issue Title based on the URL. For Jira, you'll want to use `$(project)` and `$(id:num)` as Jira uses a combination of project key and numeric ID (e.g., "PROJ-123"). The rule you enter should match the structure of your Jira issue URLs.
### Finding Your Project ID
To find your Jira Project ID:
1. Navigate to your project in Jira
2. The Project ID can be found in the URL when viewing project settings
3. Alternatively, you can use the Jira API to get a list of your projects and their IDs
## Using Jira Custom Integration
To create a Jira issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Jira issue creation page. The issue details will be pre-filled based on your extraction rule.
Complete the issue details in Jira and submit the issue. Once created, you can copy the issue URL and paste it back into QA Sphere to link the issue to your test case.
All issues created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Comparison with Native Integration
The custom integration has some limitations compared to the native Jira integration:
* No automatic issue status synchronization
* Limited field mapping capabilities
* Manual URL copying required
* No direct access to Jira issue types and fields
Consider using the [native Jira integration](https://qasphere.com/docs/jira) unless you have specific requirements that necessitate using the custom integration.
## Benefits of Custom Jira Integration
Despite the limitations, the custom integration still offers several benefits:
* **Flexibility**: Can be used when native integration requirements cannot be met
* **Simplicity**: No API tokens or complex configuration required
* **Accessibility**: Works with any Jira instance you can access via browser
* **Quick Setup**: Can be configured in minutes without administrative access
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link is correct and includes the proper Project ID.
2. Ensure your Title Extraction Rule correctly matches your Jira issue URL structure.
3. Verify that you have the necessary permissions in your Jira instance.
4. Make sure you're logged into Jira in your browser for seamless issue creation.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Notion
URL: /docs/notion
QA Sphere allows you to integrate with Notion using the Custom Issue Tracker feature. This integration enables you to create Notion pages (serving as issues) directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your Notion workspace.
## Configuring Notion as a Custom Issue Tracker
To integrate Notion into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Notion" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new page in your Notion database. For example:
```
https://www.notion.so/your-workspace/your-database-name-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?v=
```
Replace `your-workspace` and `your-database-name-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` with your actual Notion workspace and database ID.
* **Title Extraction Rule**: Enter the rule that matches your Notion page URL structure. For example:
```
https://www.notion.so/your-workspace/$(title)-$(id)
```
6. Click **Save** to add the Notion integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Issue Title based on the URL. For Notion, you typically want to use both `$(title)` and `$(id)` as Notion URLs often include both the page title and a unique identifier. The rule you enter should match the structure of your Notion page URLs.
## Using Notion Issues Integration
To create a Notion issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Notion page creation interface in your specified database. The page title will be pre-filled based on your extraction rule.
Complete the page details in Notion and publish the page. Once created, you can copy the page URL and paste it back into QA Sphere to link the issue to your test case.
All issues created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of Notion Integration
* **Flexibility**: Customize the integration to match your specific Notion workspace and database structure.
* **Rich Content**: Leverage Notion's powerful page creation features for detailed issue documentation.
* **Seamless Workflow**: Quickly access Notion's page creation interface from within QA Sphere.
* **Consistency**: Ensure all issues are properly documented and tracked in your Notion database.
* **Traceability**: Easily link test cases to specific Notion pages for better tracking.
* **Collaboration**: Take advantage of Notion's collaborative features for issue discussion and resolution.
By leveraging this custom integration, your team can maintain a cohesive and efficient testing and issue management process across QA Sphere and Notion, tailored to your specific project needs.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link is correct and points to the right Notion database.
2. Ensure your Title Extraction Rule correctly matches your Notion page URL structure.
3. Verify that you have the necessary permissions in your Notion workspace to create pages in the specified database.
4. Make sure you're logged into Notion in your browser for seamless page creation.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Nuclino
URL: /docs/nuclino
QA Sphere allows you to integrate with Nuclino using the Custom Issue Tracker feature. This integration enables you to create Nuclino items directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your collaborative workspace.
## Configuring Nuclino as a Custom Issue Tracker
To integrate Nuclino into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Nuclino" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new item in your Nuclino workspace. For example:
```
https://app.nuclino.com/[TEAM]/[WORKSPACE]/New-Item
```
* **Title Extraction Rule**: Enter the rule that matches your Nuclino item URL structure. For example:
```
https://app.nuclino.com/[TEAM]/[WORKSPACE]/$(title)-$(id)
```
6. Click **Save** to add the Nuclino integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Item Title based on the URL. For Nuclino, you'll want to use both `$(title)` and `$(id)` as Nuclino uses a combination of item title and unique identifier in URLs. The rule you enter should match the structure of your Nuclino item URLs.
### Finding Your Team and Workspace Names
To find your Nuclino identifiers:
1. Log into your Nuclino account
2. Navigate to your desired workspace
3. Your team and workspace names appear in the URL
4. The URL format is typically: `app.nuclino.com/[TEAM]/[WORKSPACE]`
## Using Nuclino Integration
To create a Nuclino item during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Nuclino item creation interface. The item details will be pre-filled based on your extraction rule.
Complete the item details in Nuclino and create the item. Once created, you can copy the item URL and paste it back into QA Sphere to link the item to your test case.
All items created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of Nuclino Integration
* **Real-time Collaboration**: Work together on issue documentation in real-time.
* **Workspace Organization**: Utilize Nuclino's flexible workspace structure.
* **Rich Text Formatting**: Take advantage of Nuclino's markdown-based editor.
* **Item Relations**: Create relationships between different QA items.
* **Graph Visualization**: Visualize connections between related issues.
By leveraging this custom integration, your team can maintain a cohesive workflow between QA testing and collaborative documentation, ensuring comprehensive issue tracking and knowledge sharing.
## Best Practices
1. **Workspace Structure**: Create a dedicated workspace for QA-related items.
2. **Item Templates**: Set up templates for common issue types.
3. **Tagging System**: Implement consistent tags for different types of QA issues.
4. **Hierarchical Organization**: Use Nuclino's tree structure for logical issue organization.
5. **Cross-linking**: Utilize bi-directional linking between related items.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link includes the correct team and workspace names.
2. Ensure your Title Extraction Rule correctly matches your Nuclino item URL structure.
3. Verify that you have the necessary permissions in your Nuclino workspace.
4. Make sure you're logged into Nuclino in your browser for seamless item creation.
5. Check that your workspace settings allow new item creation.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Sentry.io
URL: /docs/sentry
QA Sphere allows you to integrate with Sentry.io using the Custom Issue Tracker feature. This integration enables you to create Sentry issues directly while going through test cases in a test run, streamlining your workflow and ensuring efficient error tracking within your Sentry projects.
## Configuring Sentry as a Custom Issue Tracker
To integrate Sentry into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Sentry" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new issue in your Sentry organization. For example:
```
https://sentry.io/organizations/[ORG_NAME]/issues/new/
```
* **Title Extraction Rule**: Enter the rule that matches your Sentry issue URL structure. For example:
```
https://sentry.io/organizations/[ORG_NAME]/issues/$(id)
```
6. Click **Save** to add the Sentry integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Issue Title based on the URL. For Sentry, you'll want to use `$(id)` as Sentry uses unique issue identifiers. The rule you enter should match the structure of your Sentry issue URLs.
### Finding Your Organization Name
To find your Sentry Organization Name:
1. Log into your Sentry account
2. The organization name is visible in the URL after logging in
3. It can also be found in Organization Settings
4. This name will be used in place of `[ORG_NAME]` in your URLs
## Using Sentry Integration
To create a Sentry issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Sentry issue creation interface. The issue details will be pre-filled based on your extraction rule.
Complete the issue details in Sentry and create the issue. Once created, you can copy the issue URL and paste it back into QA Sphere to link the issue to your test case.
All issues created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of Sentry Integration
* **Error Tracking**: Connect QA findings directly with Sentry's error monitoring system.
* **Performance Monitoring**: Link test cases to performance issues tracked in Sentry.
* **Release Tracking**: Associate issues with specific releases in Sentry.
* **Stack Traces**: Access detailed stack traces and debug information.
* **Environment Segmentation**: Track issues across different environments.
By leveraging this custom integration, your team can maintain a cohesive workflow between QA testing and error monitoring, ensuring comprehensive issue tracking and resolution.
## Best Practices
1. **Project Organization**: Create dedicated Sentry projects for different environments or components.
2. **Issue Tags**: Use consistent tagging for QA-identified issues.
3. **Alert Rules**: Configure appropriate alert rules for QA-created issues.
4. **Integration Links**: Link Sentry issues to relevant source code when applicable.
5. **Environment Context**: Include environment information in issue descriptions.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link includes the correct organization name.
2. Ensure your Title Extraction Rule correctly matches your Sentry issue URL structure.
3. Verify that you have the necessary permissions in your Sentry organization.
4. Make sure you're logged into Sentry in your browser for seamless issue creation.
5. Check that your project settings allow manual issue creation.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Trello
URL: /docs/trello
QA Sphere allows you to integrate with Trello using the Custom Issue Tracker feature.
This integration enables you to open Trello board and then attach Trello cards to test results in a test run,
streamlining your workflow and ensuring efficient issue tracking within your Trello boards.
## Configuring Trello as a Custom Issue Tracker
To integrate Trello into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Trello" or a name of your choice.
* **New Issue Link**: Enter the URL for your Trello board. For example:
```
https://trello.com/b/[BOARD_ID]/[BOARD_NAME]
```
* **Title Extraction Rule**: Enter the rule that matches your Trello card URL structure. For most cases, you can use:
```
https://trello.com/c/$(base64url)/$(id:num)-$(title)
```
6. Click **Save** to add the Trello integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Card Title based on the URL. For Trello, you'll want to use both `$(id)` and `$(title)` as Trello URLs include both a unique card identifier and the card title. The rule you enter should match the structure of your Trello card URLs.
## Using Trello Integration
To create a Trello card during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Trello board interface. The card title will be pre-filled based on your extraction rule.
Complete the card details in Trello and create the card. Once created, you can copy the card URL and paste it back into QA Sphere to link the issue to your test case.
All cards created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of Trello Integration
* **Visual Workflow**: Take advantage of Trello's Kanban-style interface for issue tracking.
* **Seamless Workflow**: Quickly access Trello's card creation interface from within QA Sphere.
* **Flexibility**: Organize issues across different lists and boards based on your team's workflow.
* **Collaboration**: Leverage Trello's rich feature set for team communication and task management.
* **Efficiency**: Reduce time spent switching between QA Sphere and Trello.
By leveraging this custom integration, your team can maintain a cohesive and efficient testing and issue management process across QA Sphere and Trello, tailored to your specific project needs.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link is correct and points to the right Trello board.
2. Ensure your Title Extraction Rule correctly matches your Trello card URL structure.
3. Verify that you have the necessary permissions in your Trello workspace.
4. Make sure you're logged into Trello in your browser for seamless card creation.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# YouTrack
URL: /docs/youtrack
QA Sphere allows you to integrate with JetBrains YouTrack using the Custom Issue Tracker feature. This integration enables you to create YouTrack issues directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your YouTrack projects.
## Configuring YouTrack as a Custom Issue Tracker
To integrate YouTrack into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "YouTrack" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new issue in your YouTrack project. For example:
```
https://youtrack.yourdomain.com/newIssue?project=[PROJECT_ID]
```
* **Title Extraction Rule**: Enter the rule that matches your YouTrack issue URL structure. For example:
```
https://youtrack.yourdomain.com/issue/[PROJECT_ID]-$(id:num)
```
6. Click **Save** to add the YouTrack integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Issue Title based on the URL. For YouTrack, you'll want to use `$(project)` and `$(id:num)` as YouTrack uses a combination of project shortname and numeric ID (e.g., "TEST-123"). The rule you enter should match the structure of your YouTrack issue URLs.
### Finding Your Project ID
To find your YouTrack Project ID:
1. Navigate to your project in YouTrack
2. Open project settings
3. The Project ID is typically shown in the project settings or can be found in the URL
4. For cloud-hosted instances, make sure to use your specific YouTrack domain
## Using YouTrack Integration
To create a YouTrack issue during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the YouTrack issue creation page. The issue details will be pre-filled based on your extraction rule.
Complete the issue details in YouTrack and submit the issue. Once created, you can copy the issue URL and paste it back into QA Sphere to link the issue to your test case.
All issues created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of YouTrack Integration
* **Powerful Issue Management**: Take advantage of YouTrack's robust issue tracking capabilities.
* **Agile Boards**: Seamlessly integrate with YouTrack's agile board features.
* **Custom Fields**: Support for YouTrack's flexible custom field system.
* **Command Syntax**: Utilize YouTrack's command-based issue manipulation.
* **Workflow Integration**: Connect your QA process with existing YouTrack workflows.
By leveraging this custom integration, your team can maintain a cohesive and efficient testing and issue management process across QA Sphere and YouTrack, tailored to your specific project needs.
## Best Practices
1. **Project Structure**: Consider your YouTrack project structure when setting up the integration.
2. **Issue Types**: Define standard issue types in YouTrack for QA-related issues.
3. **Templates**: Use YouTrack issue templates to streamline issue creation.
4. **Custom Fields**: Set up relevant custom fields in YouTrack for QA-specific information.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link is correct and includes the proper Project ID.
2. Ensure your Title Extraction Rule correctly matches your YouTrack issue URL structure.
3. Verify that you have the necessary permissions in your YouTrack instance.
4. Make sure you're logged into YouTrack in your browser for seamless issue creation.
5. Check that your YouTrack instance is accessible from your current network.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Zendesk
URL: /docs/zendesk
QA Sphere allows you to integrate with Zendesk using the Custom Issue Tracker feature. This integration enables you to create Zendesk tickets directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your Zendesk support system.
## Configuring Zendesk as a Custom Issue Tracker
To integrate Zendesk into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Zendesk" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new ticket in your Zendesk instance. For example:
```
https://yourdomain.zendesk.com/agent/tickets/new
```
* **Title Extraction Rule**: Enter the rule that matches your Zendesk ticket URL structure. For example:
```
https://yourdomain.zendesk.com/agent/tickets/$(id:num)
```
6. Click **Save** to add the Zendesk integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Ticket Title based on the URL. For Zendesk, you'll want to use `$(id:num)` as Zendesk uses numeric ticket IDs. The rule you enter should match the structure of your Zendesk ticket URLs.
### Zendesk Domain Configuration
Your Zendesk domain will be in one of these formats:
* `https://yourdomain.zendesk.com` (Standard)
* `https://yourdomain.zendesk.eu` (European instances)
* Custom domain if configured for your organization
Make sure to use the correct domain in both the New Issue Link and Title Extraction Rule.
## Using Zendesk Integration
To create a Zendesk ticket during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Zendesk ticket creation interface. The ticket details will be pre-filled based on your extraction rule.
Complete the ticket details in Zendesk and submit the ticket. Once created, you can copy the ticket URL and paste it back into QA Sphere to link the ticket to your test case.
All tickets created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of Zendesk Integration
* **Support Workflow**: Integrate QA findings directly into your support system.
* **Ticket Management**: Utilize Zendesk's robust ticket management features.
* **SLA Tracking**: Take advantage of Zendesk's SLA monitoring capabilities.
* **Knowledge Base**: Link tickets to relevant knowledge base articles.
* **Communication**: Leverage Zendesk's communication tools for issue resolution.
By leveraging this custom integration, your team can maintain a cohesive workflow between QA testing and support operations, ensuring effective issue tracking and resolution.
## Best Practices
1. **Ticket Forms**: Create a dedicated ticket form for QA-related issues.
2. **Custom Fields**: Set up custom fields to capture test-specific information.
3. **Tags**: Use consistent tagging for QA-sourced tickets.
4. **Macros**: Create macros for common QA ticket responses or updates.
5. **Views**: Set up specific views for QA-related tickets.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link uses the correct Zendesk domain.
2. Ensure your Title Extraction Rule correctly matches your Zendesk ticket URL structure.
3. Verify that you have the necessary agent permissions in Zendesk.
4. Make sure you're logged into Zendesk in your browser for seamless ticket creation.
5. Check that your ticket form is accessible and properly configured.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Zoho Desk
URL: /docs/zoho-desk
QA Sphere allows you to integrate with Zoho Desk using the Custom Issue Tracker feature. This integration enables you to create Zoho Desk tickets directly while going through test cases in a test run, streamlining your workflow and ensuring efficient issue tracking within your help desk system.
## Configuring Zoho Desk as a Custom Issue Tracker
To integrate Zoho Desk into QA Sphere, follow these steps:
1. Go to **Settings** by clicking the gear icon in the top right corner and choose **Workspace Settings**.
2. Select **Issue Trackers** from the left sidebar.
3. A list of all available projects will be displayed. Click the **+** button next to the appropriate project to add integration.
4. Choose **Custom** from the list of available integrations.
5. You'll be presented with a form to configure your Custom Issue Tracker. Fill it out as follows:
* **Issue Tracker Name**: Enter "Zoho Desk" or a name of your choice.
* **New Issue Link**: Enter the URL for creating a new ticket in your Zoho Desk portal. For example:
```
https://desk.zoho.com/support/[ORG_NAME]/CreateTicket
```
* **Title Extraction Rule**: Enter the rule that matches your Zoho Desk ticket URL structure. For example:
```
https://desk.zoho.com/support/[ORG_NAME]/ShowTicket.do?ticketId=$(id:num)
```
6. Click **Save** to add the Zoho Desk integration.
### Understanding Title Extraction Rule
The Title Extraction Rule helps QA Sphere pre-fill the Ticket Title based on the URL. For Zoho Desk, you'll want to use `$(id:num)` as Zoho Desk uses numeric ticket IDs. The rule you enter should match the structure of your Zoho Desk ticket URLs.
### Finding Your Organization Name
To find your Zoho Desk Organization Name:
1. Log into your Zoho Desk account
2. Your organization name appears in the URL after logging in
3. It can also be found in Organization Settings
4. This name will be used in place of `[ORG_NAME]` in your URLs
## Using Zoho Desk Integration
To create a Zoho Desk ticket during testing:
1. Within your project, navigate to the **Test Runs** section.
2. Select an existing test run or create a new one.
3. Choose a test case within the run.
4. When changing the status of the test case, click **+ Add Custom Issue**.
A new browser tab will open with the Zoho Desk ticket creation interface. The ticket details will be pre-filled based on your extraction rule.
Complete the ticket details in Zoho Desk and submit the ticket. Once created, you can copy the ticket URL and paste it back into QA Sphere to link the ticket to your test case.
All tickets created for the test case will be saved under the Action History for this test run, providing a clear trail of documentation.
## Benefits of Zoho Desk Integration
* **Centralized Tracking**: Manage QA-related issues within your help desk system.
* **Department Organization**: Utilize Zoho Desk's department structure for issue categorization.
* **SLA Management**: Take advantage of Zoho Desk's SLA tracking capabilities.
* **Knowledge Base Integration**: Link tickets to relevant knowledge base articles.
* **Workflow Automation**: Connect with Zoho Desk's automated workflow features.
By leveraging this custom integration, your team can maintain a cohesive workflow between QA testing and customer support operations, ensuring comprehensive issue tracking and resolution.
## Best Practices
1. **Department Setup**: Create a dedicated department for QA-related tickets.
2. **Custom Fields**: Configure custom fields to capture test-specific information.
3. **Ticket Templates**: Create templates for common QA-related issues.
4. **Field Mapping**: Set up consistent field mapping between QA Sphere and Zoho Desk.
5. **Blueprint Configuration**: Design appropriate blueprints for QA ticket workflows.
## Troubleshooting
If you encounter any issues with the integration:
1. Double-check that your New Issue Link includes the correct organization name.
2. Ensure your Title Extraction Rule correctly matches your Zoho Desk ticket URL structure.
3. Verify that you have the necessary agent permissions in Zoho Desk.
4. Make sure you're logged into Zoho Desk in your browser for seamless ticket creation.
5. Check that your department and form settings are properly configured.
For further assistance, contact your QA Sphere administrator or support team at [sorted@qasphere.com](mailto:sorted@qasphere.com).
---
# Cypress Integration
URL: /docs/cli-usage-cypress
See a working example: [bistro-e2e-cypress](https://github.com/Hypersequent/bistro-e2e-cypress) — Cypress E2E tests with QA Sphere integration.
# Cypress Integration
This guide covers Cypress-specific setup. For install/auth/upload-command reference, see [Overview](/docs/cli), [Auth](/docs/cli/auth), and [Result Upload](/docs/integrations/result-upload).
## Prerequisites
* QAS CLI installed and authenticated — see the [Overview](/docs/cli). Node.js 22+ required for the CLI.
* Cypress test project.
## Configure the JUnit reporter
Cypress does not produce JUnit XML out of the box. The recommended setup uses [`cypress-multi-reporters`](https://www.npmjs.com/package/cypress-multi-reporters) with [`mocha-junit-reporter`](https://www.npmjs.com/package/mocha-junit-reporter) to print spec output and write JUnit XML in parallel.
```bash
npm install --save-dev cypress-multi-reporters mocha-junit-reporter
```
Create `reporter-config.json`:
```json
{
"reporterEnabled": "spec, mocha-junit-reporter",
"mochaJunitReporterReporterOptions": {
"mochaFile": "cypress/reports/junit/results-[hash].xml"
}
}
```
Reference it from `cypress.config.ts`:
```typescript
// cypress.config.ts
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
baseUrl: 'https://your-app-url.com',
specPattern: 'cypress/e2e/**/*.cy.ts',
screenshotOnRunFailure: true,
video: true,
videosFolder: 'cypress/videos',
screenshotsFolder: 'cypress/screenshots',
reporter: 'cypress-multi-reporters',
reporterOptions: {
configFile: 'reporter-config.json',
},
},
});
```
The `[hash]` placeholder in `mochaFile` produces one JUnit XML file per spec (e.g. `results-abc123.xml`), so uploads need a shell glob.
## Mark tests with QA Sphere markers
Cypress uses Mocha-style test names, which support the hyphenated `PROJECT-SEQUENCE` marker format. Place the marker at the start of the test name:
```typescript
// cypress/e2e/cart.cy.ts
describe('Cart', () => {
it('BD-023: User should see product list on the Checkout page', () => {
cy.visit('/');
cy.get('.menu-item').first().find('.add-to-cart').click();
cy.get('.checkout-btn').click();
cy.get('.checkout-items').should('be.visible');
});
it('BD-022: User should place order with valid data', () => {
// ...
});
});
```
For all supported marker formats and matching rules, see [Result Upload — Test case matching](/docs/integrations/result-upload#test-case-matching).
## Upload results
Pass every per-spec JUnit XML via shell glob:
```bash
npx qas-cli junit-upload --attachments cypress/reports/junit/results-*.xml
```
A convenient npm script:
```json
{
"scripts": {
"test": "cypress run --browser chrome",
"test:upload": "npm test && npx qas-cli junit-upload --attachments cypress/reports/junit/results-*.xml"
}
}
```
For the full option reference, run-name templates, and modes (new run vs existing), see [Result Upload](/docs/integrations/result-upload).
---
# Result Upload
URL: /docs/integrations/result-upload
The CLI ships three result-upload commands that share a single workflow:
```bash
qasphere junit-upload [options]
qasphere playwright-json-upload [options]
qasphere allure-upload [options]
```
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](https://qasphere.com/docs/cli-usage-playwright)
* [Cypress Integration](https://qasphere.com/docs/cli-usage-cypress)
* [Python / pytest Integration](https://qasphere.com/docs/cli-usage-pytest)
* [WebdriverIO Integration](https://qasphere.com/docs/cli-usage-webdriverio)
* [Auto-create test cases with Playwright](https://qasphere.com/docs/integrations/result-upload/playwright-create-tcases-guide)
## 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 ` 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.
```bash
# 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 of an existing test run to upload into. Project code and run ID are extracted from the URL. |
| `--project-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 ` | 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 to skip stdout from test results. Choices: `on-success`, `never` (default). |
| `--skip-report-stderr ` | 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:
```bash
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](https://playwright.dev/docs/test-annotations#annotate-tests) with `type: "test case"` (case-insensitive) and the full QA Sphere test case URL as `description`:
```typescript
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 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 `` elements and empty-name `` entries with `` or `` (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
```bash
# 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
```
---
# Uploading Playwright Results with Auto Test Case Creation
URL: /docs/integrations/result-upload/playwright-create-tcases-guide
This guide walks through the workflow for a QA engineer who has automated manual test cases from the **Bistro Delivery** project using Playwright and wants to report results back to QA Sphere — including automatically creating test cases in QA Sphere for any Playwright tests that don't yet have a matching case.
VIDEO
***
## When to use `--create-tcases`
By default, `playwright-json-upload` requires every test in the report to reference an existing QA Sphere test case (via an annotation or a `BD-XXX` marker in the test name). If any test lacks a valid reference, the upload fails.
The `--create-tcases` flag changes this behavior: instead of failing, the CLI **creates new test cases** in QA Sphere for any unmatched tests and includes them in the test run. A mapping file is generated so you can update your tests with the assigned codes going forward.
This is useful when:
* You're starting fresh and have Playwright tests that don't reference QA Sphere cases yet
* You've added new tests and want them tracked in QA Sphere without manually creating cases first
***
## Prerequisites
* Node.js 22+
* QAS CLI installed: `npm install -g qas-cli`
* Playwright project with JSON reporter configured
* A QA Sphere account with the **Bistro Delivery** project (project code: `BD`)
* A QA Sphere API token
***
## Step 1: Configure environment
Create a `.qaspherecli` file in your project root (or export as environment variables):
```sh
QAS_TOKEN=your_api_token_here
QAS_URL=https://qas.eu1.qasphere.com
```
***
## Step 2: Configure Playwright JSON reporter
In your `playwright.config.ts`, enable the JSON reporter:
```typescript
import { defineConfig } from '@playwright/test'
export default defineConfig({
reporter: [
['list'],
['json', { outputFile: 'test-results/results.json' }]
],
})
```
***
## Step 3: (Recommended) Add test case annotations
If your Playwright tests already reference QA Sphere test cases, annotate them so the CLI can match them precisely. This is the recommended approach for existing test cases:
```typescript
test(
'Add item to cart',
{
annotation: {
type: 'test case',
description: 'https://qas.eu1.qasphere.com/project/BD/tcase/002',
},
},
async ({ page }) => {
// test code
}
)
```
Alternatively, include the `BD-XXX` marker in the test name:
```typescript
test('BD-002: Add item to cart', async ({ page }) => {
// test code
})
```
Tests **without** an annotation or marker are the ones that will be auto-created when using `--create-tcases`.
***
## Step 4: Run Playwright tests
```bash
npx playwright test
```
This generates `test-results/results.json`.
***
## Step 5: Upload results with `--create-tcases`
```bash
qasphere playwright-json-upload test-results/results.json --project-code BD --create-tcases
```
The CLI will:
1. Create a new test run in the BD project (named automatically, e.g. `Automated test run - Apr 22, 2025, 10:34:00 AM`)
2. Match tests that have valid `BD-XXX` markers or annotations to existing test cases
3. **Create new QA Sphere test cases** for any tests without a valid marker
4. Upload pass/fail status for all tests
Any test cases that were not found in QA Sphere will be automatically created and placed in the **cli-import** folder in your project.

To give the run a meaningful name, add `--run-name`:
```bash
qasphere playwright-json-upload test-results/results.json --project-code BD --run-name "Bistro E2E - {YYYY}-{MM}-{DD}" --create-tcases
```
***
## Step 6: Check the mapping file
After the upload, the CLI generates a mapping file in your working directory, for example:
```
qasphere-automapping-20250422-103400.txt
```
It lists the QA Sphere sequence numbers assigned to each newly created test case:
```
"Verify checkout total" → BD-025
"Validate empty cart message" → BD-026
```
**Update your Playwright tests** to include these markers so future uploads match the existing cases instead of creating duplicates:
```typescript
test('BD-025: Verify checkout total', async ({ page }) => {
// test code
})
```
***
## Quick reference
| Goal | Command |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Upload to a new run, auto-create missing test cases | `qasphere playwright-json-upload results.json --project-code BD --create-tcases` |
| Same, with a custom run name | `qasphere playwright-json-upload results.json --project-code BD --run-name "Sprint 12" --create-tcases` |
| Upload to an existing run (no auto-creation needed) | `qasphere playwright-json-upload results.json -r https://qas.eu1.qasphere.com/project/BD/run/23` |
| Upload with screenshots attached | `qasphere playwright-json-upload results.json --project-code BD --create-tcases --attachments` |
| Suppress unmatched test warnings (without creating cases) | `qasphere playwright-json-upload results.json --project-code BD --ignore-unmatched` |
***
## Notes
* `--create-tcases` only works when **creating a new test run** (i.e., without `--run-url`). It cannot create test cases when uploading to an existing run.
* Run the mapping file update step before your next CI run to avoid creating duplicate test cases.
* If you want to silence unmatched test warnings without auto-creating cases, use `--ignore-unmatched` instead.
---
# Playwright Integration
URL: /docs/cli-usage-playwright
See a working example: [bistro-e2e](https://github.com/Hypersequent/bistro-e2e) — Playwright E2E tests with QA Sphere integration.
# Playwright Integration
This guide covers Playwright-specific setup. For install/auth/upload-command reference, see [Overview](/docs/cli), [Auth](/docs/cli/auth), and [Result Upload](/docs/integrations/result-upload).
The CLI supports **two upload paths** for Playwright:
1. **`playwright-json-upload`** (recommended) — uses Playwright's native JSON report with support for test annotations.
2. **`junit-upload`** — uses Playwright's JUnit reporter output.
## Prerequisites
* QAS CLI installed and authenticated — see the [Overview](/docs/cli).
* Playwright test project.
## Configure a reporter
Pick one of the reporters below depending on which upload path you'll use. JSON is recommended because it supports test annotations.
### Option A: JSON reporter (recommended)
```javascript
// playwright.config.js
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 30000,
reporter: [
['list'],
['json', { outputFile: 'test-results/results.json' }],
],
use: {
headless: true,
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
{ name: 'firefox', use: { browserName: 'firefox' } },
{ name: 'webkit', use: { browserName: 'webkit' } },
],
});
```
### Option B: JUnit XML reporter
```javascript
// playwright.config.js
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 30000,
reporter: [
['list'],
['junit', { outputFile: 'junit-results/results.xml' }],
],
use: {
headless: true,
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
},
});
```
## Attachments
When you pass `--attachments`, the CLI picks up the three artifact types Playwright produces automatically:
| Artifact | Enabled by |
| --------------- | ------------------------------------------------------------------------- |
| **Screenshots** | `use.screenshot: 'only-on-failure'` (or `'on'`) in `playwright.config.js` |
| **Videos** | `use.video: 'retain-on-failure'` (or `'on'`) |
| **Traces** | `use.trace: 'retain-on-failure'` (or `'on-first-retry'`) |
Each attachment is matched to its test case and uploaded alongside the result. Paths inside the JSON/JUnit report must be resolvable from the working directory the upload command runs in.
## Link tests to QA Sphere test cases
Playwright JSON supports two matching methods, checked in order: test annotations (recommended) and hyphenated `PROJECT-SEQUENCE` markers in the test name. JUnit XML supports the hyphenated marker only (plus the underscore/CamelCase variants — see [Result Upload — Test case matching](/docs/integrations/result-upload#test-case-matching)).
### Test annotations (Playwright JSON only)
Add a [Playwright test annotation](https://playwright.dev/docs/test-annotations#annotate-tests) with `type: "test case"` and the full QA Sphere test case URL:
```typescript
// tests/login.spec.ts
import { test, expect } from '@playwright/test';
test(
'Login with valid credentials',
{
annotation: {
type: 'test case',
description: 'https://qas.eu1.qasphere.com/project/PRJ/tcase/312',
},
},
async ({ page }) => {
await page.goto('https://example.com/login');
// ...
}
);
```
### Hyphenated marker in the test name
Works with both Playwright JSON and JUnit XML:
```typescript
test('PRJ-312: Login with valid credentials', async ({ page }) => {
// ...
});
test('Login with invalid credentials: PRJ-313', async ({ page }) => {
// ...
});
```
For `playwright-json-upload`, only annotations and hyphenated markers are supported. The underscore-separated and CamelCase variants are JUnit-only.
## Upload results
```bash
# Recommended: JSON path
npx playwright test
npx qas-cli playwright-json-upload --attachments test-results/results.json
# JUnit XML path
npx qas-cli junit-upload --attachments junit-results/results.xml
```
A convenient npm script:
```json
{
"scripts": {
"test": "playwright test",
"test:upload": "playwright test && npx qas-cli playwright-json-upload --attachments test-results/results.json"
}
}
```
For the full option reference, run-name templates, and modes (new run vs existing), see [Result Upload](/docs/integrations/result-upload).
---
# Python (pytest) Integration
URL: /docs/cli-usage-pytest
See a working example: [bistro-e2e-python](https://github.com/Hypersequent/bistro-e2e-python) — Playwright for Python (pytest) E2E tests with QA Sphere integration.
# Python (pytest) Integration
This guide covers pytest-specific setup. For install/auth/upload-command reference, see [Overview](/docs/cli), [Auth](/docs/cli/auth), and [Result Upload](/docs/integrations/result-upload).
While the examples below use Playwright for Python, the same approach works with **any Python test framework** that emits JUnit XML — pytest + Selenium, Robot Framework, plain unit tests, and so on.
## Prerequisites
* Python 3.8+ (3.13+ recommended) and a pytest project.
* QAS CLI installed and authenticated — see the [Overview](/docs/cli). The CLI is distributed as an npm package, so Node.js 22+ is required for the CLI itself (not for your Python project).
## Configure JUnit XML output
pytest has built-in JUnit XML support via the `--junitxml` flag. Wire it up in `pyproject.toml` so it runs automatically:
```toml
# pyproject.toml
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = [
"--junitxml=junit-results/results.xml",
]
```
Or pass it directly:
```bash
pytest --junitxml=junit-results/results.xml
```
### With Playwright for Python
To also capture screenshots and traces for failures:
```toml
# pyproject.toml
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = [
"--screenshot=on",
"--tracing=retain-on-failure",
"--junitxml=junit-results/results.xml",
]
```
## Mark tests with QA Sphere markers
Python function names cannot contain hyphens, so the CLI supports an **underscore-separated hyphenless marker**. The function name must start with `test` (the standard pytest convention); the marker can appear immediately after `test_` or at the end of the name.
Format: `test_PROJECTSEQUENCE_description` — where `PROJECT` is the project code and `SEQUENCE` is the test case number (minimum 3 digits, zero-padded if needed).
```python
# tests/test_ui_cart.py
from playwright.sync_api import Page
def test_bd023_cart_operations(page: Page, demo_base_url: str) -> None:
"""BD-023: User should see product list on the Checkout page."""
page.goto(f"{demo_base_url}/")
page.locator(".menu-item").first.locator(".add-to-cart").click()
page.locator(".cart-btn").click()
assert page.locator(".checkout-items").is_visible()
def test_bd022_order_with_cash_payment(page: Page, demo_base_url: str) -> None:
"""BD-022: User should place the order successfully with Cash payment."""
# ...
```
Valid function names:
* `test_bd023_cart_operations` — marker `bd023` at the start (after `test_`)
* `test_cart_operations_bd023` — marker `bd023` at the end
The underscore marker is matched case-insensitively: `test_bd023_...` and `test_BD023_...` both resolve to `BD-023`.
It's good practice to include the hyphenated form in the docstring for human readability while keeping the underscore marker in the function name for matching.
For all supported marker formats and matching rules, see [Result Upload — Test case matching](/docs/integrations/result-upload#test-case-matching).
## Upload results
```bash
# Run pytest (writes junit-results/results.xml via pyproject.toml)
pytest --browser chromium -v
# Upload
npx qas-cli junit-upload --project-code BD --attachments junit-results/results.xml
```
For the full option reference, run-name templates, and modes (new run vs existing), see [Result Upload](/docs/integrations/result-upload).
---
# WebdriverIO Integration
URL: /docs/cli-usage-webdriverio
See a working example: [bistro-e2e-wdio](https://github.com/Hypersequent/bistro-e2e-wdio) — WebdriverIO E2E tests with QA Sphere integration.
# WebdriverIO Integration
This guide covers WebdriverIO-specific setup. For install/auth/upload-command reference, see [Overview](/docs/cli), [Auth](/docs/cli/auth), and [Result Upload](/docs/integrations/result-upload).
## Prerequisites
* QAS CLI installed and authenticated — see the [Overview](/docs/cli). Node.js 22+ required for the CLI.
* WebdriverIO test project.
## Configure the JUnit reporter
```typescript
// wdio.conf.ts
import type { Options } from '@wdio/types';
export const config: Options.Testrunner = {
// ... other config
reporters: [
['junit', {
outputDir: './junit-results',
outputFileFormat: (options) => `results-${options.cid}-${options.capabilities.browserName}.xml`,
suiteNameFormat: /[^a-zA-Z0-9@\-:]+/ // Keeps alphanumeric, @, dash, colon
}]
],
};
```
WebdriverIO writes one JUnit XML per worker (e.g. `results-0-0.xml`, `results-0-1.xml`).
### Uploading multiple worker files
The upload commands accept multiple files. List them explicitly, or use a shell glob in bash/zsh:
```bash
npx qas-cli junit-upload junit-results/*.xml
```
## Mark tests with QA Sphere markers
WebdriverIO uses Mocha-style names, which support the hyphenated `PROJECT-SEQUENCE` marker. Place it at the start of the test name:
```typescript
// test/specs/cart-simple.e2e.ts
describe('Cart Functionality', () => {
it('BD-023: User should see product list on checkout page', async () => {
await browser.url('/checkout');
const products = await $$('.product-item');
expect(products.length).toBeGreaterThan(0);
});
it('BD-022: Order placement with valid data', async () => {
// ...
});
});
```
For all supported marker formats and matching rules, see [Result Upload — Test case matching](/docs/integrations/result-upload#test-case-matching).
## Attaching screenshots to failed tests
WebdriverIO doesn't reference screenshots in JUnit XML out of the box. Embed paths into the failure message via the `afterTest` hook, then `--attachments` picks them up:
```typescript
// wdio.conf.ts
import fs from 'fs/promises';
export const config: Options.Testrunner = {
// ... other config
afterTest: async function (test, context, { error, passed }) {
if (passed) return;
const testNamePrefix = test.title
.replace(/[^a-zA-Z0-9]+/g, '_')
.substring(0, 50);
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const finalScreenshot = `./screenshots/${testNamePrefix}_afterTest_${timestamp}.png`;
await browser.saveScreenshot(finalScreenshot);
const screenshotFiles = await fs.readdir('./screenshots');
const testCaseMatch = test.title.match(/^(BD-\d+)/);
const testCaseId = testCaseMatch ? testCaseMatch[1] : null;
const matchingScreenshots = screenshotFiles.filter(file =>
file.startsWith(testNamePrefix) || (testCaseId && file.includes(testCaseId))
);
if (error && matchingScreenshots.length > 0) {
const attachments = matchingScreenshots
.map(file => `[[ATTACHMENT|${file}]]`)
.join('\n');
error.message = `${error.message}\n\n${attachments}`;
}
},
};
```
The CLI recognizes the `[[ATTACHMENT|path]]` marker in failure messages and uploads the file alongside the result.
**Limitation**
This pattern only works for **failed** tests, since JUnit XML has no standard way to attach files to passing ones — the attachment marker lives inside `` / `` text.
Manual screenshots taken with `browser.saveScreenshot('./screenshots/BD-055_*.png')` during a test are matched by the test case ID and uploaded automatically when the test fails.
## Upload results
```bash
npm test
npx qas-cli junit-upload junit-results/*.xml
```
For the full option reference, run-name templates, and modes (new run vs existing), see [Result Upload](/docs/integrations/result-upload).
---
# December '24: 24W48
URL: /docs/24W48
QA Sphere 24W48 was released on Wednesday, December 10th 2024. It is available to all users of the platform.
## **New Features**
* **Custom Test Run Statuses**: You can now add up to four custom statuses for test run results (e.g., "Known Issue," "Retest," or "Passed w/remarks") to fit your workflow. Custom statuses are currently defined at the account level. They are fully supported across the product, including API and Reports.
* **Test Run Results**: A new setting, “Move to the next test case after adding the result,” simplifies filling out test runs by automatically advancing to the next test case.
* **Select Multiple Test Cases**: Use checkboxes to select multiple test cases on the test cases tab. For the test runs tab, you can hold the \[Shift] key to select multiple test cases. Checkboxes for this functionality will be added in the next release.
* **Improved Requirements Management**: You can now choose existing requirements from a dropdown list, making it easier to connect requirements with your test cases.
* **Enhanced Test Run Dialog**: A "Select/Deselect visible" checkbox is now available in the test run dialog, allowing you to include or exclude test cases based on tags or priorities.
* **Comment on Test Steps**: Mention a specific test step in your comments on test case results. Mentioned test steps will be highlighted for better visibility.
* **Clone Test Runs**: You can now clone a test run to create a similar test run without carrying over any results.
* **Improved Assignee Suggestions**: Users listed in the Project Overview Team block are now displayed at the top of the assignee dropdown in the test run creation dialog.
* **New REST APIs**:
* Retrieve user information: [Users API Documentation](https://docs.eu1.qasphere.com/docs/v0/users)
* Create non-live test runs with filters in addition to test case IDs: [Runs API Documentation](https://docs.eu1.qasphere.com/docs/v0/run)
* **Updated REST API Documentation**: We have updated the formatting of the API documentation, transition to use TypeScript instead of JSON schemas, and added basic examples.
* **Email in User List**: In the Team tab under Settings, user emails are now displayed below their names for better clarity.
## **Fixes**
This release also includes several important fixes:
* Improved PDF report rendering.
* Better page layout for smaller screens and browser windows.
* Refined text in UI message dialogs.
* General performance improvements.
* Fixes related to Filters and behavior related to certain UI components
***
We hope you enjoy the new features and enhancements in QA Sphere! Thank you for your continued support.
---
# December '24: 24W52
URL: /docs/24W52
QA Sphere 24W52 was released on Tuesday, December 31st 2024. It is available to all users of the platform.
We’re excited to kick off 2025 with an update packed with enhancements and fixes to make your QA experience even smoother.
## **New Features**
* **Dark Mode**: You asked, we listened! QA Sphere now supports **Dark Mode**. Choose between **Light**, **Dark**, or **System Default** from your **Settings**. Enjoy working your way, day or night.
* **Select Multiple Test Cases (Checkboxes)**: Selecting multiple test cases during a test run just got easier. Now you can use **checkboxes** for mouse-driven selection. Prefer the keyboard? The **Shift-key** functionality still works as before.
* **Test Run Configurations**: Add context to your test runs by specifying configurations like browser, OS, or hardware. Testers will know exactly what to use for their tasks.
* **Edit Test Result Comments**: Made a typo or need to add more details? You can now edit existing test result comments to ensure all relevant information is captured.
* **Export a Single Folder**: Need just one folder? The export dialog now allows targeted folder exports for more precise data sharing.
## **Fixes**
This release also includes critical fixes and improvements:
* Enhanced **API documentation** for better developer support.
* **Updated Reports** for improved clarity and usability.
* Optimized **performance** for a faster, more responsive platform.
* Resolved an issue with exporting test cases containing tables.
* Fixed drag-and-drop functionality issues for smoother interactions.
***
We’re thrilled to deliver these updates as part of our mission to make QA Sphere fast, efficient, and bloat-free. Have feedback? Let us know – we’re all ears!
Thank you for your continued support and trust.
---
# 2024 Release Notes
URL: /docs/release-notes/2024
* [December: 24W52](/docs/24W52)
* [November: 24W48](/docs/24W48)
---
# January '25: 25W03
URL: /docs/25W03
We’re starting the year with updates that focus on improving platform stability, user experience, and a few powerful new features to streamline your QA workflows.
## **New Features**
* **Alphabetical Folder Sorting for Large Projects**
Managing large projects is now easier! You can disable manual folder positioning and enable alphabetical sorting for a more organized workspace.
* **Expanded Public API**
Our API now includes [endpoints for querying the test case library](/docs/api/tcases/). Build deeper integrations and access your data more efficiently.
* **Improved Jira Integration**
When creating a new Jira issue from QA Sphere, the default issue type is now set to **Bug** for faster issue creation.
* **Streamlined Test Case Results Updates**
Updating test case results after submission is now clearer and more intuitive, reducing any friction in your QA process.
## **Performance and Fixes**
* **Database Optimizations**
Backend improvements make the platform faster and more responsive.
* **Dark Mode Fixes**
Several adjustments to enhance the dark mode experience.
* **Minor UX Improvements**
Numerous small updates to ensure a smoother and more enjoyable user experience.
***
We’re committed to building a tool that’s fast, reliable, and easy to use. Your feedback helps us grow, so don’t hesitate to reach out with your thoughts!
Thank you for being a part of QA Sphere.
---
# February '25: 25W07
URL: /docs/25W07
We're thrilled to announce our latest update, packed with AI enhancements, platform stability improvements, and a refined user experience. This release is all about making your test management smoother and more intuitive.
## **New Features**
* **Custom Fields for Test Cases**:
Tailor your test cases with new custom fields. You can now seamlessly filter, import, and export test cases using these fields.
* **AI-Powered JIRA Integration**:
Leverage AI to automatically generate detailed JIRA issue content from test case details and result comments, streamlining your bug reporting process effortlessly.
* **Milestone Archiving**:
Keep your workspace organized by archiving completed milestones, which automatically closes all associated test runs.
* **Time Tracking and Issue Management**:
Users can now update time tracking details and remove attached issues in test case results, along with updating comments.
* **Image Expansion in Editor**:
View images in full screen for a more detailed inspection.
* **Enhanced Navigation**:
Quickly jump from a test case in a test run to its original in the test case library — perfect for reviewing history or reorganizing your tests.
* **Persistent Edit Button**:
The edit button for test cases on the run page is now always available, allowing necessary changes even after results are added. If a result is already added, the test case in the run will need to be manually updated to the latest version, after the test is updated in the library.
* **User Profile Enhancements**:
Usernames and emails are now visible in the profile dropdown for easier account management.
## **Performance and Fixes**
* **Resolved Internal Errors**:
Fixed an internal error when navigating to the test case insights tab for test cases in closed runs that have been deleted from the project.
* **Safari UI Freeze**:
Addressed an issue where exporting a report caused the app to freeze on Safari.
* **UI Improvements**:
Multiple UI tweaks for a cleaner and more consistent look.
* **Backend Performance**:
Continuous improvements under the hood for a faster, more reliable experience.
***
We're committed to making QA Sphere the go-to tool for high-quality, efficient test management. Your feedback is invaluable, so keep it coming. Thank you for being a part of our journey!
---
# March '25: 25W10
URL: /docs/25W10
This March, we’ve focused on performance, polish, and unlocking the next step in AI-powered test management.
## **New Features**
* **Write Test Cases With AI (Beta)**: The new **Bulk Write With AI** feature is now available to everyone. Just outline your functional requirements, and let our assistant suggest structured test cases to get you started faster.
* **Smarter Onboarding Flow**: New users are now asked a few quick questions during onboarding. This helps us tailor the experience and support to their workflow more effectively.
* **Logged-In User Display**: A subtle detail—click your profile picture, and you'll now see the currently logged-in user. Small, but helpful in shared environments.
## **Fixes**
This release includes a round of stability and UI improvements:
* Newly created folders in the **Test Cases** page are now correctly highlighted for better visibility.
* Fixed horizontal scrolling issue and layout breaking in the **Custom Fields** page when field values or project names were long.
* Resolved an error when navigating to **Insights** for deleted test cases.
* Removed an unused custom field hint for a cleaner interface.
* Fixed scrolling behavior in **Bulk AI Create** so the system takes you directly to your new drafts.
* Plus dozens of under-the-hood tweaks to improve overall reliability.
***
We’re moving fast and listening closely. If something feels off or you're missing a key feature, don’t hesitate to reach out — we're here to build this with you.
---
# April '25: 25W13
URL: /docs/25W13
This month, we're introducing major updates that bring more power and clarity to your QA workflows. From test case parameterization to automation insights and smoother navigation—April is all about control and precision.
## **New Features**
* **Test Case Parameterization (Early Access)**:\
You can now write test cases with variables (e.g., `${os}`) and define value sets separately. QA Sphere will automatically generate "filled" test cases for each variation. We're rolling this out gradually—reach out if you'd like early access.
* **Automation Coverage Report**:\
Visualize how much of your test suite is automated. This new report uses the "Automation" custom field to break down coverage and identify gaps.
* **Smarter Search in Test Cases**:\
Press `/` to instantly open search. Navigate with arrow keys and select with Enter. We've also improved the logic—search now recognizes markers like `PRJ-73`, and shows full test case paths in results.
* **Time Tracking in Test Runs**:\
Test case durations are now easier to see and interpret directly in test run lists. Faster decisions, less guesswork.
* **Improved Status Dropdown**:\
The test case status selector in test runs now features clearer styles, visible active states, and dark mode compatibility improvements.
## **Fixes**
* Fixed folder structure ordering during project import/export
* Resolved layout alignment issues on Safari
* Improved phone number inputs with split fields for country code and number
* API documentation updated with custom field support and filtering examples
***
We're steadily building a reliable, user-friendly QA platform. If you'd like to try parameterization or share feedback, drop us a line at **[sorted@qasphere.com](mailto:sorted@qasphere.com)** — we're here to help.
---
# May '25: 25W17
URL: /docs/25W17
This release brings powerful upgrades to AI-driven workflows, a more fluid test run experience, and cleaner UI interactions. We're focused on helping you move faster—with less friction.
## **New Features**
* **AI-Powered Bulk Test Case Creation**\
The improved flow lets you preview test cases before generating, edit inline, choose between drafts or finalized output, auto-group by functional requirements, and reassign folders with a quick modal.
* **Test Case Preview in Test Run Picker**\
Quickly peek into a test case before adding it. The new **Preview** button opens a side panel on hover—with smooth animations and easy close via click-out or "×".
* **Smarter Handling for Empty Test Cases**\
Empty test cases now show a subtle indicator and come with a helpful, AI-generated prompt—so you're never starting from zero.
* **Parameter Value Suffixes in Filled Titles**\
When you fill parameterized test cases, we now append the used values directly into titles. Easier to scan. More precise.
* **Test Run Dialog: Smarter Folder Controls**\
You can now expand or collapse all folders at once, plus search for folders directly. Faster setup, less clicking.
* **Write Issues with AI (Custom Integrations)**\
Creating bug tickets for custom integrations? Now you can draft them with AI too—just like you do for Jira.
* **Rich Text: Better Image Uploads**\
Paste screenshots (Ctrl/Cmd + V), drag-and-drop them in, or upload up to **10 images at once**. Works anywhere rich text is supported.
## **Fixes**
This release also includes important fixes and minor improvements:
* Disabled fullscreen preview while editing rich text
* Reduced preview thumbnail size by 40% for cleaner layout
* Fixed auto-scroll bug in test case creation
* Single test case result via dropdown no longer deselects all others
* Multiple other bug fixes and UI improvements
***
QA Sphere is built for teams that care about speed and clarity. If you hit any snags or have ideas, drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**. We're here to help.
---
# June '25: 25W21
URL: /docs/25W21
This release introduces comprehensive test plan management, enhanced notifications, and improved workflow capabilities. We're making it easier than ever to organize, track, and execute your testing activities with greater visibility and control.
## **New Features**
* **Notifications**\
You can now get notified about key changes in test runs and plans - including when you're assigned or unassigned, and when test runs and plans are closed, deleted, or reopened. All alerts appear in a new notifications panel with unread filters and bulk mark-as-read.
* **Test Plans**\
Easily group related test runs into structured test plans. You can create plans via a simple form, add or clone test runs into them, and manage everything in one place — with configurations, assignments, and test cases all preserved.
* **Improved test run description field**\
Test run descriptions now support rich text formatting — including code blocks, images, and tables. On the run details page, long descriptions are collapsed by default with a "Show more" button that opens a pop-up. This helps keep the layout clean while still allowing detailed content. When exporting a run to PDF, the full description is included automatically.
* **Folder breadcrumbs in test run**\
Folder breadcrumbs in the Test Case view now show a clearer path with up to three levels of hierarchy, including icons and visible test case counts for the current folder. Long paths are smartly shortened with an ellipsis for better readability.
* **Reorder test steps with input field**\
Test case steps can now be reordered by entering a number directly into a step's position field.
* **Improved suffixes for filled test case titles**\
You can select which parameters should appear as suffixes when creating a parameterized case. If nothing is selected, the suffix will be skipped.
* **Convert template test cases to standalone**\
You can now turn a template test case into a standalone one with a single action from the dropdown menu. The system updates its type, removes linked filled versions.
* **Add dark mode toggle in menu**\
You can now switch between light and dark themes from the menu.
* **Added column sorting to Automation Report**\
You can now sort columns in the Automation Report in ascending, descending, or default order—making it easier to review automation status across cases.
* **More power to Test-Runners**\
The test-runner role now have access to create, edit, and delete test runs and plans.
* **Improved Jira integrations**\
You can now connect multiple Jira accounts to the same hostname using different user emails. This is helpful when teams need separate credentials for different projects. The UI now also shows which Jira user is linked to each integration—making it easier to manage and troubleshoot connections.
## **Fixes**
This release also includes important fixes and polish:
* Fixed folder selection logic in the Duplicate Test Case dialog — the current folder is now pre-selected, and the UI scrolls to it automatically.
* Fixed Jira integration error to help users identify permission-related issues directly.
* Fixed layout issues on the Test Run page where filter fields wrapped unnecessarily; filters now stay on one line when space allows.
* Fixed tag overflow in test case preview: long tag lists now collapse into a single row with a "+X" indicator to expand remaining items.
---
# June '25: 25W24
URL: /docs/25W24
This update is small but mighty — polish that makes everyday testing smoother and faster.
## **New Features**
* **Resize images inside text fields**: Drag the corners of any screenshot or diagram in test cases and results to get the perfect fit.
* **Rich text in folder comments**: Format comments with lists, links, and code. Lengthy notes open in a full-screen editor so you can focus.
* **“No value” filter for custom fields**: Spot gaps faster—choose **None** to find test cases where a field is blank.
* **Copy cases and folders across projects**: Duplicate test cases or entire folders to another project, complete with tags, requirements, and custom fields.
* **HEIC uploads**: Drop iPhone screenshots without a hitch—QA Sphere converts them to JPEG automatically.
* **Stickier search modal**: The search window now stays open until you choose to close it, preventing accidental dismissals.
* **Faster multi-select in test runs**: Clicking a row toggles its checkbox; details open only after you exit selection mode.
## **Fixes**
This release also ships essential fixes and polish:
* Resizing the left panel on **Test Cases** no longer spills over to **Test Runs**.
* Opening a test case in a new tab (Cmd/Ctrl + Click) no longer closes the search bar.
* Dozens of minor UX and UI tweaks to keep everything crisp.
***
QA Sphere is on a mission to make testing effortless and affordable. Your feedback keeps us on track—keep it coming!
---
# July '25: 25W27
URL: /docs/25W27
This mid-July update introduces helpful enhancements for working with test cases, enhanced filtering controls, and UI improvements. We've also fixed several bugs to keep things running smoothly.
## **New Features**
* **Attach images to bulk AI test case creation**: You can include up to 5 images (with a total file size of 20MB) when generating test cases with AI.
* **"Select All" test cases in test runs**: Easily select all visible test cases after filtering for quick bulk actions.
* **Clear all filters button**: A "Clear all filters" button now appears when multiple filters are applied. If space is limited, it shortens to just "Clear" with an icon.
* **Keep test case status when re-adding with same version to run**: Test case status now stays the same when it's re-added to a run with the same version. It only resets to "open" if the version is newer.
## **Fixes**
This release also includes important fixes:
* Fixed complete folder tree showing on the Test Run page when filters return no test cases.
* Fixed scrollbar placement in issue creation modals — now scrolls inside the input, not the entire modal.
* Fixed archived projects showing in issue tracker settings — now hidden.
* Fixed formatting issues in import/export: preserved new lines, underlines, and table structure.
* Fixed step auto-scroll after position change.
* Opening a test case in a new tab (Cmd/Ctrl + Click) no longer closes the search bar.
* A round of minor UX and UI tweaks to keep everything crisp.
***
We've done a lot of foundational work for upcoming releases – stay tuned!
---
# August '25: 25W32
URL: /docs/25W32
This release brings reusable steps, AI rule management, and rich-editing upgrades — all built to make your QA workflow faster, clearer, and more consistent.
## **New Features**
* **New Resources Section**
A single place to manage shared assets across a project: **Shared Steps**, **Test Run Configurations**, **Requirements**, **Tags**, and **AI Rules** — all centralized for consistency.
* **Shared Steps**
Create reusable step groups and insert them into multiple test cases. Edit a shared step once — it updates everywhere. Manage them from **Resources** or directly while editing a test case. Need a one-off? Detach to customize locally.
* **AI Rules in Resources & AI Forms**
Define reusable AI rules once and apply them when generating **test cases** or **issues** with AI for more consistent outputs.
* **Linear Integration**
Create and link Linear issues directly from QA Sphere to keep QA and delivery in sync.
* **Embed Video in the Editor**
Upload and embed MP4/WebM videos (up to 250 MB per video) directly in rich text fields to illustrate steps and defects clearly.
* **Basic Emoji Support**
Type `:` to trigger inline emoji autocomplete in the editor. An emoji picker dialog is available too.
* **See What Changed in Test Case Edits**
The revision dialog now highlights added and removed text when comparing versions. For complex content (images, tables), we show the updated block with a note if a diff isn’t available.
* **AND/OR Tag Filter**
Choose how tag filters behave: **OR** for any match, **AND** to require all selected tags.
* **Bulk Update for Custom Fields**
Update dropdown-type custom fields across many test cases at once. A new review modal ensures only selected values are changed.
* **Press Esc to Clear Selection**
Quickly clear selected test cases on **Test Cases** and **Test Runs** with the **Esc** key.
## **Fixes**
This release also includes important fixes:
* Corrected folder path ordering in **Search** results to match the test case page hierarchy.
* Restored preview for the latest test case edit in history. **View changes** now appears for the newest revision and is hidden only for the initial creation when it’s the sole entry.
* Restored bold styling for section titles (e.g., **Preconditions**) in generated **JIRA** issues.
***
We’re building a fast, affordable, and dependable test management system — and your feedback guides the roadmap. Got ideas or run into a snag? We’re listening.
---
# September '25: 25W36
URL: /docs/25W36
This release brings major workflow enhancements, deeper integrations, and improved collaboration tools —
built to help teams move faster with fewer clicks and clearer context.
## **New Features**
* **Restore & Duplicate from Revision History**\
You can now restore previous versions of test cases—or create new ones directly from older versions. Perfect for branching out or reusing historical flows.
* **Requirement Linking with Jira**\
Link functional requirements directly to Jira issues during test case creation or bulk edits. Keeps your test management aligned with your backlog.
* **Attach Files When Reporting Issues via Jira, GitHub, or Linear**\
Issue reporting now supports file uploads—up to 5 files, 100MB each, 250MB total. Add screenshots, videos, or logs for faster issue resolution.
* **Bulk Move for Test Cases and Folders**\
A new bulk move action is now available from the context menu. Relocate multiple test cases and folders in one go.
* **AI-Assisted Bulk Creation from PDFs**\
You can now upload a PDF to generate multiple test cases automatically. No need to manually fill in the “Requirements” field.
* **Unique Names for Test Runs and Plans**\
Test runs and plans must now be uniquely named within a milestone. (Exception: test runs inside the same test plan can still share names.)
* **Improved Filters UI and New Filter Options**\
Filters have been redesigned for clarity and speed. New filters include: **Author**, **Draft Status** and **Requirements**
* **Shared Step Updates are Now Versioned**\
Updating a shared step now creates a new version. Changes are automatically propagated to all test cases using that step.
* **Audit Logging for Project Archiving**\
Project delete, archive, and unarchive actions are now logged. Each log includes timestamp, user, browser, and IP.\
Navigate to **Settings → Audit Logs** to view.
## **Fixes**
This release also includes several important fixes:
* **File Upload Lock**: Disabled Save/Update buttons while files are still uploading in the rich text editor. This prevents incomplete attachments.
* **Jira Token Refresh**: You can now update expired Jira API tokens without redoing the entire integration.
* **UI Cleanup**: Fixed an issue where the pagination bar appeared unnecessarily in the Insights tab of test case/run previews.
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.\
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# October '25: 25W40
URL: /docs/25W40
This release brings keyboard shortcuts, enhanced diff views, improved integrations, and streamlined workflows — all designed to help teams work faster and more efficiently.
## New Features
* **Keyboard Shortcuts on Test Cases Page**\
You can now use keyboard shortcuts to speed up actions in the test cases library. All shortcuts are shown in the Hot keys panel in the sidebar.
* **Diff for parameterized test cases**\
The diff view now highlights changes in parameterized test cases — both in the parameter table and filled test cases.
* **Link Test Plans and Test Runs to Jira**\
You can now link test plans and test runs in QA Sphere to Jira. Easily manage links with the new "Link to Jira" option in the menu.
* **Link GitHub issues from Test Runs**\
You can now link GitHub issues directly from a test run — consistent with Jira and Linear.
* **Faster Quick Test Case Creation**\
Creating test cases via Quick Create is now faster — the form stays open, and new cases appear instantly without reload.
* **Improved Jira Integration Form**\
Simplified subdomain input, auto-trimmed https\:// and .atlassian.net, and improved error handling for invalid domains.
* **Audit Log Improvements**\
Audit Logs now display project information for delete/archive/unarchive actions, and support filtering and pagination for easier browsing.
* **UI improvements (icons, filters, interactions)**\
Updated icons in Settings, applied new filters on the Reports page, and enabled hover for filter sub-dropdowns
## Fixes
This release also includes dozens of targeted improvements across the board:
* Improved stability of AI streaming and markdown rendering in the Generate Issue modal.
* Enhanced rollback, export, and restore logic for shared and parameterized test cases.
* Resolved some design inconsistencies
* Improved validation and error handling in Jira integration and subscriptions.
* Fixed focus trap in modals for better accessibility and navigation.
---
# November '25: 25W45
URL: /docs/25W45
This update focuses on making everyday work in QA Sphere faster, clearer, and easier to navigate — especially for teams working with larger projects and Jira.
## New Features
* **Better layout for large screens**
On wide screens, you can now see the **folder tree**, **test case list**, and **test case preview** side by side.
You can also resize the drawer and content area by dragging the vertical separator to create the layout that works best for you.
* **Bulk Test Case creation (easier to find)**
The AI-powered **Bulk Test Case Creation** is now available directly under the **Create** button on the **Test Cases** page.
Click **Create → Bulk Create with AI** to generate multiple test cases at once. A keyboard shortcut is also available for even faster access.
* **Requirements support for Bulk Write with AI**
When using **Bulk Write with AI** on the **Test Cases** page, you can now paste **Jira links** into the **Functional Requirements** field.
If your project is connected to Jira, QA Sphere will automatically fetch the issue text and use it as input for AI-generated test cases — keeping everything linked to the original requirement.
* **Copy links for multiple Test Cases**
You can now quickly share test cases with your team using the new **Copy Links** option for multiple selections.
Select several test cases and choose **Copy Links** to copy them in either:
* **Markdown list**
* **Rich Text** (HTML-style links)
This makes it easier to paste clean, readable lists into docs, tickets, and chats.
* **Convert regular Test Case to Template**
You can now convert an existing **regular test case** into a **parameterized template** directly from the **Actions** menu.
This helps you reuse well-written cases as templates without recreating them from scratch.
* **Advanced import guidance**
We've updated the **Import** dialog to make available options clearer.
For **advanced imports** (for example, imports with attachments or migrations from other test management systems), you'll see guidance to contact our team — we'll help you get your data in correctly.
If you need help with a complex import, reach out to **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
* **Smarter Jira linking in Requirements**
While creating a **Requirement**, you can now:
* Search existing Jira issues by **title** or **ID**
* Avoid duplicates by reusing the right Jira issue
* Automatically pull the **title** from the linked Jira issue when you paste a link
This keeps your requirements cleaner and better aligned with your Jira structure.
* **Improved Jira Issue linking in Test Runs**
In **Test Runs**, the **Create Jira Issue** dialog now has smarter selectors for **Epic** and **Parent issue**:
* Search by **issue title** or enter a **Jira ID** (e.g. `KAN-100`)
* Epics are **sorted by creation date (newest first)**
This speeds up linking the right Jira issues, especially in large projects with many tickets.
* **Clearer Template behavior without variables**
When saving a **Template test case** without any variables, QA Sphere now shows a clear warning.
The message explains that such templates **won't be included in test runs**, helping you avoid confusion and coverage gaps.
You can choose between **Save Anyway** or **Cancel**.
* **Easier editing of Shared Steps from Test Case**
You can now edit **Shared Steps** directly from within a test case.
A new option in the step context menu lets you:
* Open the shared step in a **new tab**, or
* **Refresh** it in place after editing
No more hunting for the shared step elsewhere — edit once, reuse everywhere.
## Fixes
This release also includes dozens of targeted improvements across the app. Highlights:
* Prevented creation of **duplicate test case titles** within the same folder by showing a validation error during creation.
* Fixed inconsistent **test case placement** after moving folders — test cases now consistently appear at the bottom of the destination folder.
* Renamed **"Detach shared step"** to **"Convert to regular steps"** to make the action clearer.
* Fixed an issue where **emojis** were not highlighted as changes in the **Changes history** modal for test cases.
* Updated backend validation to prevent creating **test plans without test runs** via the public API.
---
# December '25: 25W48
URL: /docs/25W48
This update brings new filtering capabilities, layout customization options, and improvements to AI-powered test case creation — plus tighter access controls for enterprise teams.
## New Features
* **Switch Layout Density in Test Case List**
You can now adjust the row density of the test case list using a new layout selector in the top-right corner. Available options include **Default**, **Compact**, and **Comfortable**, allowing for a more tailored viewing experience based on screen space and preference.
* **Tag Exclusion Filter (NOT)**
The tags filter now supports a **NOT** operator that allows users to exclude test cases containing specific tags. This helps quickly narrow down the list to test cases that do not contain any of the selected tags.
* **Search Jira Issues in Bulk AI Creation**
You can now search and select Jira issues when using **Bulk Create with AI** — available when Jira integration is enabled. Selected issues are used to generate test cases linked to original tickets.
* **Moved Personal Settings to My Account**
User preferences like appearance (**Light/Dark/System**) and the **"Move to next test case after adding result"** option are now located under **My Account** instead of Customization. The Customization section is now only visible to admins and workspace owners. Also, the **"Profile"** menu item was renamed to **My Account** for clarity.
* **Text Attachments Support in AI Features**
You can now attach **.txt**, **.md**, and **.csv** files when configuring AI Rules or using Bulk Write with AI. The contents of these text files are read and used as input for AI-generated test cases.
* **Improved Jira Link Handling**
We now support Jira links that use the `selectedIssue` query parameter (e.g. links copied from Kanban boards). QA Sphere correctly extracts issue keys from both standard Jira URLs and these rare formats, ensuring consistent behavior across the platform.
* **Improved Range Selection on the Test Cases and Test Runs pages**
Improved multi-item selection on the **Test Cases** and **Test Runs** pages — users can now click once to select the first test case and then **Shift+click** to select the last one in a range. There's no need to hold Shift for the first item anymore.
* **Enforce Google Sign-In**
Admins on the **Business** plan can enforce Google Sign-In for all users in the workspace. When enabled, all users are logged out and password-based login is fully disabled — the login form hides the username and password fields.
## Fixes
This release also includes dozens of targeted improvements across the app.
* Fixed tag overflow tooltip in the test case preview pane to show **tag titles** instead of just the tag count.
* Improved error logging for AI-generated test case saving failures.
* Trimmed leading/trailing whitespace for **shared steps** and **shared preconditions** to match normal step behavior.
* Improved error messages during bulk creation with AI to clearly indicate which test case or field caused validation failures.
***
We're building QA Sphere to stay fast, reliable, and modern—without the bloat.\
Have questions or feedback? Drop us a note at **[sorted@qasphere.com](mailto:sorted@qasphere.com)**.
---
# 2025 Release Notes
URL: /docs/release-notes/2025
* [November: 25W48](/docs/25W48)
* [November: 25W45](/docs/25W45)
* [October: 25W40](/docs/25W40)
* [September: 25W36](/docs/25W36)
* [August: 25W32](/docs/25W32)
* [July: 25W27](/docs/25W27)
* [June: 25W24](/docs/25W24)
* [June: 25W21](/docs/25W21)
* [May: 25W17](/docs/25W17)
* [March: 25W13](/docs/25W13)
* [March: 25W10](/docs/25W10)
* [February: 25W07](/docs/25W07)
* [January: 25W03](/docs/25W03)
---
# Bitbucket Pipelines Integration
URL: /docs/integrations/ci-cd/bitbucket
Automatically upload test results from your Bitbucket Pipelines to QA Sphere using the QAS CLI tool. This integration eliminates manual result entry and provides instant visibility into your automated test results.
## What You'll Achieve
With this integration, every time your Bitbucket Pipeline runs:
* Test results automatically upload to QA Sphere
* New test runs are created with pipeline information
* Tests are matched to existing QA Sphere test cases
* Pass/fail status, execution time, and screenshots are recorded
* Test history and trends are tracked over time
## Prerequisites
Before starting, ensure you have:
* A Bitbucket repository with automated tests (Playwright, Cypress, Jest, etc.)
* Tests configured to generate **JUnit XML** format results
* A QA Sphere account with **Test Runner** role or higher
* Test cases in QA Sphere with **markers** (e.g., `BD-001`, `PRJ-123`)
## How It Works

1. Your pipeline runs automated tests
2. Tests generate JUnit XML results file
3. QAS CLI tool reads the XML file
4. CLI matches tests to QA Sphere cases using markers
5. Results are uploaded and appear in QA Sphere
## Setup Steps
### Step 1: Create QA Sphere API Key
1. Log into your QA Sphere account
2. Click the **gear icon** ⚙️ in the top right → **Settings**
3. Navigate to **API Keys**
4. Click **Create API Key**
5. **Copy and save the key** - you won't see it again!
Your API key format: `t123.ak456.abc789xyz`
### Step 2: Configure Bitbucket Variables
Add these secrets to your Bitbucket repository:
1. Go to your Bitbucket repository
2. Navigate to **Repository settings** → **Repository variables**
3. Click **Add variable** and create:
| Name | Value | Secured |
| ----------- | ------------------------------------------------------------- | ----------- |
| `QAS_TOKEN` | Your API key (e.g., `t123.ak456.abc789xyz`) | ✓ Checked |
| `QAS_URL` | Your QA Sphere URL (e.g., `https://company.eu1.qasphere.com`) | ☐ Unchecked |
4. Click **Add** to save each variable
**Security**
Never commit API keys to your repository. Always use Bitbucket Repository variables with the "Secured" option enabled.
### Step 3: Add Test Case Markers
Ensure your test names include QA Sphere markers in the format `PROJECT-SEQUENCE`:
These markers can be found in QA Sphere interface for each test case separately.
**Playwright Example:**
```typescript
test('BD-001: User can login with valid credentials', async ({ page }) => {
await page.goto('https://example.com/login');
await page.fill('#username', 'user@example.com');
await page.fill('#password', 'password123');
await page.click('#login-button');
await expect(page).toHaveURL('/dashboard');
});
test('BD-002: User sees error with invalid credentials', async ({ page }) => {
// test implementation
});
```
**Cypress Example:**
```javascript
describe('Login Flow', () => {
it('BD-001: should login successfully with valid credentials', () => {
cy.visit('/login');
cy.get('#username').type('user@example.com');
cy.get('#password').type('password123');
cy.get('#login-button').click();
cy.url().should('include', '/dashboard');
});
});
```
**Jest Example:**
```javascript
describe('API Tests', () => {
test('BD-015: GET /users returns user list', async () => {
const response = await fetch('/api/users');
expect(response.status).toBe(200);
const data = await response.json();
expect(data).toHaveLength(5);
});
});
```
### Step 4: Configure Test Framework
Configure your test framework to generate JUnit XML output:
#### Playwright Configuration
```javascript
// playwright.config.js
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 30000,
// JUnit reporter for CI/CD
reporter: [
['list'], // Console output
['junit', { outputFile: 'junit-results/results.xml' }] // For QA Sphere
],
use: {
headless: true,
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
{ name: 'firefox', use: { browserName: 'firefox' } },
{ name: 'webkit', use: { browserName: 'webkit' } },
],
});
```
#### Cypress Configuration
```javascript
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
reporter: 'cypress-multi-reporters',
reporterOptions: {
configFile: 'reporter-config.json'
}
}
});
```
```json
// reporter-config.json
{
"reporterEnabled": "spec, mocha-junit-reporter",
"mochaJunitReporterReporterOptions": {
"mochaFile": "junit-results/results.xml"
}
}
```
#### Jest Configuration
```javascript
// jest.config.js
module.exports = {
reporters: [
'default',
['jest-junit', {
outputDirectory: './junit-results',
outputName: 'results.xml',
classNameTemplate: '{classname}',
titleTemplate: '{title}'
}]
]
};
```
### Step 5: Create Bitbucket Pipeline
Create a `bitbucket-pipelines.yml` file in your repository root:
#### For Playwright Projects
```yaml
image: node:22
definitions:
steps:
- step: &test-and-upload-step
name: Run Playwright Tests and Upload to QA Sphere
# IMPORTANT: Use Playwright Docker image matching your @playwright/test version
image: mcr.microsoft.com/playwright:v1.62.1-jammy
caches:
- node
script:
- npm ci
- npx playwright test || true
- npm install -g qas-cli
- qasphere junit-upload --run-name "bitbucket-pipeline_{YYYY}-{MM}-{DD}" ./junit-results/results.xml
- echo "✅ Test results uploaded to QA Sphere"
artifacts:
- junit-results/**
- test-results/**
- playwright-report/**
pipelines:
default:
- step: *test-and-upload-step
branches:
main:
- step: *test-and-upload-step
develop:
- step: *test-and-upload-step
pull-requests:
'**':
- step: *test-and-upload-step
```
#### For Cypress Projects
```yaml
image: node:22
definitions:
steps:
- step: &test-step
name: Run Cypress Tests
image: cypress/browsers:node18.12.0-chrome107
caches:
- node
script:
- npm ci
- npx cypress run
artifacts:
- junit-results/**
- cypress/videos/**
- cypress/screenshots/**
- step: &upload-step
name: Upload Results to QA Sphere
image: node:22
script:
- npm install -g qas-cli
- qasphere junit-upload --attachments ./junit-results/results.xml
- echo "✅ Results uploaded to QA Sphere"
pipelines:
default:
- step: *test-step
- step: *upload-step
branches:
main:
- step: *test-step
- step: *upload-step
develop:
- step: *test-step
- step: *upload-step
pull-requests:
'**':
- step: *test-step
- step: *upload-step
```
#### For Jest Projects
```yaml
image: node:22
definitions:
caches:
node: node_modules
steps:
- step: &test-step
name: Run Jest Tests
caches:
- node
script:
- npm ci
- npm test
artifacts:
- junit-results/**
- coverage/**
- step: &upload-step
name: Upload Results to QA Sphere
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/results.xml
- echo "✅ Results uploaded to QA Sphere"
pipelines:
default:
- step: *test-step
- step: *upload-step
branches:
main:
- step: *test-step
- step: *upload-step
develop:
- step: *test-step
- step: *upload-step
pull-requests:
'**':
- step: *test-step
- step: *upload-step
```
### Step 6: Push and Verify
1. **Commit your changes**:
```bash
git add bitbucket-pipelines.yml playwright.config.js # or your config files
git commit -m "Add Bitbucket Pipelines with QA Sphere integration"
git push origin main
```
2. **Monitor the pipeline**:
* Go to Bitbucket → **Pipelines**
* Watch your pipeline execute
* Check both `Run Playwright Tests` and `Upload Results to QA Sphere` steps

3. **Verify in QA Sphere**:
* Log into QA Sphere
* Navigate to your project → **Test Runs**
* See the new run with your test results
## Viewing Your Automated Test Run in QA Sphere
After your pipeline uploads results, you can view and analyze the test run in QA Sphere.
### Navigating to Test Runs
1. **Log into QA Sphere** and select your project
2. Click **Test Runs** in the left sidebar
3. Find your automated run - it will be named based on your `--run-name` template or the default format:
* Default: `Automated test run - Jan 15, 2025, 02:30:45 PM`
* Custom: `Build #12345 - main` (if you configured a custom template)

Click on any test case to see:
1. **Execution History** - How this test performed over time
2. **Error Messages** - Full stack traces for failed tests
3. **Attachments** - Screenshots captured on failure
4. **Linked Test Case** - Jump to the original test case definition
## Advanced Usage
### Available CLI Options
The QAS CLI `junit-upload` command creates a new test run within a QA Sphere project from your JUnit XML files or uploads results to an existing run.
```bash
qasphere junit-upload [options]
```
**Options:**
* `-r, --run-url ` - Upload to an existing test run (otherwise creates a new run)
* `--run-name ` - Name template for creating new test runs (only used when `--run-url` is not specified)
* `--attachments` - Detect and upload attachments (screenshots, videos, logs)
* `--force` - Ignore API request errors, invalid test cases, or attachment issues
* `-h, --help` - Show command help
#### Run Name Template Placeholders
The `--run-name` option supports the following placeholders:
**Environment Variables:**
* `{env:VARIABLE_NAME}` - Any environment variable (e.g., `{env:BITBUCKET_BUILD_NUMBER}`, `{env:BITBUCKET_COMMIT}`)
**Date Placeholders:**
* `{YYYY}` - 4-digit year (e.g., 2025)
* `{YY}` - 2-digit year (e.g., 25)
* `{MMM}` - 3-letter month (e.g., Jan, Feb, Mar)
* `{MM}` - 2-digit month (e.g., 01, 02, 12)
* `{DD}` - 2-digit day (e.g., 01, 15, 31)
**Time Placeholders:**
* `{HH}` - 2-digit hour in 24-hour format (e.g., 00, 13, 23)
* `{hh}` - 2-digit hour in 12-hour format (e.g., 01, 12)
* `{mm}` - 2-digit minute (e.g., 00, 30, 59)
* `{ss}` - 2-digit second (e.g., 00, 30, 59)
* `{AMPM}` - AM/PM indicator
**Default Template:**
If `--run-name` is not specified, the default template is:
```
Automated test run - {MMM} {DD}, {YYYY}, {hh}:{mm}:{ss} {AMPM}
```
**Example Output:**
* `Automated test run - Jan 15, 2025, 02:30:45 PM`
The `--run-name` option is only used when creating new test runs (i.e., when `--run-url` is not specified).
**Usage Examples:**
```bash
# Create new run with default name template
qasphere junit-upload ./junit-results/results.xml
# Upload to existing run (--run-name is ignored)
qasphere junit-upload -r https://company.eu1.qasphere.com/project/BD/run/42 ./junit-results/results.xml
# Simple static name
qasphere junit-upload --run-name "v1.4.4-rc5" ./junit-results/results.xml
# With environment variables
qasphere junit-upload --run-name "Build #{env:BITBUCKET_BUILD_NUMBER} - {env:BITBUCKET_BRANCH}" ./junit-results/results.xml
# Output: "Build #12345 - main"
# With date placeholders
qasphere junit-upload --run-name "Release {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Release 2025-01-15"
# With date and time placeholders
qasphere junit-upload --run-name "Nightly Tests {MMM} {DD}, {YYYY} at {HH}:{mm}" ./junit-results/results.xml
# Output: "Nightly Tests Jan 15, 2025 at 22:34"
# Complex template with multiple placeholders
qasphere junit-upload --run-name "Build {env:BUILD_NUMBER} - {YYYY}/{MM}/{DD} {hh}:{mm} {AMPM}" ./junit-results/results.xml
# Output: "Build v1.4.4-rc5 - 2025/01/15 10:34 PM"
# With attachments
qasphere junit-upload --attachments ./junit-results/results.xml
# Multiple files
qasphere junit-upload ./junit-results/*.xml
# Force upload on errors
qasphere junit-upload --force ./junit-results/results.xml
```
### Upload to Existing Test Run
To update a specific test run instead of creating a new one:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- |
RUN_ID=42
qasphere junit-upload \
-r ${QAS_URL}/project/BD/run/${RUN_ID} \
./junit-results/results.xml
```
### Upload with Attachments
Include screenshots and logs with your results:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- qasphere junit-upload --attachments ./junit-results/results.xml
```
The CLI automatically detects and uploads:
* Screenshots from test failures
* Video recordings
* Log files
* Any files referenced in the JUnit XML
### Upload Multiple XML Files
If you have multiple test suites generating separate XML files:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/*.xml
```
### Branch-Specific Runs
Create different runs for different branches:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- |
if [ "$BITBUCKET_BRANCH" = "main" ]; then
# Upload to production run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/100 ./junit-results/results.xml
elif [ "$BITBUCKET_BRANCH" = "develop" ]; then
# Upload to development run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/101 ./junit-results/results.xml
else
# Create new run for feature branches
qasphere junit-upload ./junit-results/results.xml
fi
```
### Add Pipeline Metadata
Use the `--run-name` option to include Bitbucket pipeline information in test run titles:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- |
qasphere junit-upload \
--run-name "Build #{env:BITBUCKET_BUILD_NUMBER} - {env:BITBUCKET_BRANCH}" \
./junit-results/results.xml
# Output: "Build #12345 - main"
```
**Common Bitbucket Variables:**
* `{env:BITBUCKET_BUILD_NUMBER}` - Pipeline build number
* `{env:BITBUCKET_BRANCH}` - Branch name
* `{env:BITBUCKET_COMMIT}` - Full commit SHA
* `{env:BITBUCKET_TAG}` - Tag name (if applicable)
* `{env:BITBUCKET_REPO_SLUG}` - Repository name
* `{env:BITBUCKET_STEP_TRIGGERER_UUID}` - User who triggered the pipeline
**Examples:**
```yaml
# Pipeline with date and time
- script: qasphere junit-upload --run-name "Build #{env:BITBUCKET_BUILD_NUMBER} - {YYYY}-{MM}-{DD} {HH}:{mm}" ./junit-results/results.xml
# Branch and commit info
- script: qasphere junit-upload --run-name "{env:BITBUCKET_BRANCH} - {env:BITBUCKET_COMMIT}" ./junit-results/results.xml
# Complete metadata
- script: qasphere junit-upload --run-name "Build #{env:BITBUCKET_BUILD_NUMBER} ({env:BITBUCKET_BRANCH}) - {MMM} {DD}, {hh}:{mm} {AMPM}" ./junit-results/results.xml
```
### Force Upload on Errors
Continue uploading even if some tests can't be matched:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- qasphere junit-upload --force ./junit-results/results.xml
```
## Common Scenarios
### Scenario 1: Nightly Test Runs
Run tests on a schedule and upload results with descriptive names:
```yaml
image: node:22
definitions:
steps:
- step: &test-step
name: Run Nightly Tests
image: mcr.microsoft.com/playwright:v1.62.1-jammy
script:
- npm ci
- npx playwright test
artifacts:
- junit-results/**
- step: &upload-step
name: Upload Results
script:
- npm install -g qas-cli
# Create run with date in the name
- qasphere junit-upload --run-name "Nightly Tests - {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Nightly Tests - 2025-01-15"
pipelines:
# Scheduled pipeline (configure in Bitbucket UI)
custom:
nightly:
- step: *test-step
- step: *upload-step
```
To create the schedule:
1. Go to **Repository settings** → **Pipelines** → **Schedules**
2. Click **Create schedule**
3. Select the `nightly` custom pipeline
4. Set schedule (e.g., daily at 2 AM)
### Scenario 2: Parallel Test Execution
Run tests in parallel and upload all results:
```yaml
image: node:22
definitions:
steps:
- step: &test-unit
name: Unit Tests
script:
- npm ci
- npm run test:unit
artifacts:
- junit-results/unit-results.xml
- step: &test-integration
name: Integration Tests
script:
- npm ci
- npm run test:integration
artifacts:
- junit-results/integration-results.xml
- step: &upload-step
name: Upload All Results
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/*.xml
pipelines:
default:
- parallel:
- step: *test-unit
- step: *test-integration
- step: *upload-step
```
### Scenario 3: Multi-Environment Testing
Test against different environments:
```yaml
image: node:22
definitions:
steps:
- step: &test-staging
name: Test Staging
script:
- export TEST_ENV=staging
- export BASE_URL=https://staging.example.com
- npm ci
- npm test
artifacts:
- junit-results/staging-results.xml
- step: &test-production
name: Test Production
script:
- export TEST_ENV=production
- export BASE_URL=https://example.com
- npm ci
- npm test
artifacts:
- junit-results/production-results.xml
- step: &upload-step
name: Upload Results
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/*.xml
pipelines:
default:
- parallel:
- step: *test-staging
- step: *test-production
- step: *upload-step
```
### Scenario 4: Version/Release Tagging
Tag test runs with version numbers or release names:
```yaml
image: node:22
definitions:
steps:
- step: &test-step
name: Run Release Tests
image: mcr.microsoft.com/playwright:v1.62.1-jammy
script:
- npm ci
- npx playwright test
artifacts:
- junit-results/**
- step: &upload-step
name: Upload Results
script:
- npm install -g qas-cli
- |
if [ -n "$BITBUCKET_TAG" ]; then
# For git tags, use tag name
qasphere junit-upload --run-name "Release {env:BITBUCKET_TAG}" ./junit-results/results.xml
else
# For regular commits, use branch and commit
SHORT_SHA=$(echo "$BITBUCKET_COMMIT" | cut -c1-7)
qasphere junit-upload --run-name "{env:BITBUCKET_BRANCH} - ${SHORT_SHA}" ./junit-results/results.xml
fi
pipelines:
tags:
'v*':
- step: *test-step
- step: *upload-step
branches:
main:
- step: *test-step
- step: *upload-step
```
## Troubleshooting
### Issue: Tests Not Appearing in QA Sphere
**Symptoms:**
* Upload succeeds but no results in QA Sphere
* "Test case not found" warnings in logs
**Solutions:**
1. **Ensure test cases exist in QA Sphere:**
* Check that `BD-001`, `BD-002`, etc. exist in your QA Sphere project
* Verify the project code matches (BD, PRJ, etc.)
2. **Check marker format:**
* Must be `PROJECT-NUMBER` format
* Examples: `BD-001`, `PRJ-123`, `TEST-456`
### Issue: Authentication Failed (401 Error)
**Symptoms:**
```
Error: Authentication failed (401)
```
**Solutions:**
1. **Verify API key is correct:**
* Go to QA Sphere → Settings → API Keys
* Check the key hasn't been deleted
* Regenerate if needed
2. **Check Bitbucket variables:**
* Repository settings → Repository variables
* Verify `QAS_TOKEN` is set correctly
* Ensure no extra spaces or line breaks
* Verify the "Secured" checkbox is enabled
3. **Verify key permissions:**
* API key must have Test Runner role or higher
* Check user permissions in QA Sphere
### Issue: JUnit XML File Not Found
**Symptoms:**
```
Error: File ./junit-results/results.xml does not exist
```
**Solutions:**
1. **Check test step artifacts:**
```yaml
- step:
name: Run Tests
script:
- npm ci
- npx playwright test
artifacts:
- junit-results/** # Make sure this matches your output path
```
2. **Verify test framework configuration:**
* Playwright: Check `playwright.config.js` reporter
* Cypress: Check `reporter-config.json`
* Jest: Check `jest.config.js` reporters
3. **Add debug output:**
```yaml
- step:
name: Upload to QA Sphere
script:
- ls -la junit-results/ # List files
- cat junit-results/results.xml # Show content
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/results.xml
```
### Issue: Playwright Version Mismatch
**Symptoms:**
```
Error: Executable doesn't exist at /ms-playwright/chromium...
╔ - current: mcr.microsoft.com/playwright:v1.40.0-jammy
║ - required: mcr.microsoft.com/playwright:v1.62.1-jammy
```
**Solution:**
Match Docker image version to your Playwright package version:
```bash
# Check your Playwright version
npm list @playwright/test
# Output: @playwright/test@1.62.1
```
```yaml
# Update bitbucket-pipelines.yml
- step:
name: Run Playwright Tests
image: mcr.microsoft.com/playwright:v1.62.1-jammy # Match the version
```
### Issue: Pipeline Fails But Tests Pass
**Symptoms:**
* Tests execute successfully
* Artifacts are uploaded
* Step still marked as failed
**Solution:**
Ensure test failures don't block artifact upload:
```yaml
- step:
name: Run Tests
script:
- npm ci
- npx playwright test || true # Continue even if tests fail
artifacts:
- junit-results/**
```
Or handle exit codes explicitly:
```yaml
- step:
name: Run Tests
script:
- npm ci
- |
set +e
npx playwright test
TEST_EXIT=$?
set -e
echo "Tests completed with exit code: $TEST_EXIT"
exit 0 # Force success to allow artifact upload
artifacts:
- junit-results/**
```
### Issue: Upload Step Doesn't Run
**Symptoms:**
* Test step completes
* Upload step never starts
**Solutions:**
1. **Check pipeline structure:**
```yaml
pipelines:
default:
- step:
name: Run Tests
script:
- npm test
artifacts:
- junit-results/**
- step: # This should run after the previous step
name: Upload Results
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/results.xml
```
2. **Verify artifacts are defined:**
* Artifacts from the test step must be declared
* They're automatically available in subsequent steps
### Issue: Variables Not Available
**Symptoms:**
```
Error: QAS_TOKEN environment variable is not set
```
**Solutions:**
1. **Verify variables are defined:**
* Go to Repository settings → Repository variables
* Ensure `QAS_TOKEN` and `QAS_URL` exist
2. **Check variable usage in pipeline:**
```yaml
- step:
name: Upload to QA Sphere
script:
# Variables are automatically available as environment variables
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/results.xml
```
3. **For deployment variables:**
* If using deployment steps, ensure variables are available in that environment
* Check if variables need to be added to deployment environment settings
### Issue: Pipeline Doesn't Trigger
**Symptoms:**
* Push code but pipeline doesn't run
* Pipeline file exists but not executing
**Solutions:**
1. **Verify pipeline file location:**
```
bitbucket-pipelines.yml ✅ Correct (in repository root)
.bitbucket-pipelines.yml ❌ Wrong (no dot prefix)
pipelines/bitbucket-pipelines.yml ❌ Wrong (should be in root)
```
2. **Check YAML syntax:**
```bash
# Validate YAML locally
npx js-yaml bitbucket-pipelines.yml
```
3. **Verify pipelines are enabled:**
* Repository settings → Pipelines → Settings
* Ensure "Enable Pipelines" is checked
4. **Check branch configuration:**
```yaml
pipelines:
branches:
main: # Check branch names match exactly
- step:
name: Test
script:
- npm test
```
## Best Practices
### 1. Always Use Markers
Include QA Sphere markers in all automated tests:
```typescript
// ✅ Good
test('BD-001: User can login successfully', async ({ page }) => {});
// ❌ Bad - no marker
test('User can login successfully', async ({ page }) => {});
```
### 2. Upload on Every Pipeline Run
Configure upload to run even when tests fail by using `|| true` or proper exit code handling:
```yaml
- step:
name: Run Tests
script:
- npm ci
- npx playwright test || true
artifacts:
- junit-results/**
- step:
name: Upload Results
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/results.xml
```
This ensures you track both passing and failing test results.
### 3. Use Descriptive Run Names
Use the `--run-name` option to create meaningful test run titles:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- |
qasphere junit-upload \
--run-name "Build #{env:BITBUCKET_BUILD_NUMBER} - {env:BITBUCKET_BRANCH}" \
./junit-results/results.xml
```
For branch-specific runs, you can also upload to existing runs:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- |
if [ "$BITBUCKET_BRANCH" = "main" ]; then
# Upload to production run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/100 ./junit-results/results.xml
elif [ "$BITBUCKET_BRANCH" = "develop" ]; then
# Upload to development run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/101 ./junit-results/results.xml
else
# Create new run for feature branches
SHORT_COMMIT=$(echo "$BITBUCKET_COMMIT" | cut -c1-7)
qasphere junit-upload --run-name "{env:BITBUCKET_BRANCH} - ${SHORT_COMMIT}" ./junit-results/results.xml
fi
```
### 4. Secure Your API Keys
* ✅ Store in Bitbucket Repository variables
* ✅ Enable "Secured" checkbox for sensitive values
* ✅ Rotate keys periodically
* ❌ Never commit to repository
* ❌ Never log or print in pipeline
### 5. Upload Attachments for Failures
Help debug failures by including screenshots:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- qasphere junit-upload --attachments ./junit-results/results.xml
```
### 6. Match Playwright Versions
Always keep Docker image version in sync with npm package:
```json
// package.json
{
"devDependencies": {
"@playwright/test": "1.62.1"
}
}
```
```yaml
# bitbucket-pipelines.yml
- step:
name: Run Tests
image: mcr.microsoft.com/playwright:v1.62.1-jammy
```
### 7. Use Caching for Faster Builds
Cache dependencies to speed up pipeline runs:
```yaml
definitions:
caches:
node: node_modules
- step:
name: Run Tests
caches:
- node
script:
- npm ci
- npx playwright test
```
### 8. Test Locally First
Before pushing to Bitbucket, test the integration locally:
```bash
# Set environment variables
export QAS_TOKEN=your.api.key
export QAS_URL=https://company.eu1.qasphere.com
# Run tests
npm test
# Upload results
npx qas-cli junit-upload ./junit-results/results.xml
```
### 9. Monitor Upload Success
Add error handling to track upload status:
```yaml
- step:
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- |
if qasphere junit-upload ./junit-results/results.xml; then
echo "✅ Successfully uploaded results to QA Sphere"
else
echo "❌ Failed to upload results to QA Sphere"
exit 1
fi
```
### 10. Use Step Definitions
Define reusable steps for cleaner pipelines:
```yaml
definitions:
steps:
- step: &test
name: Run Tests
image: mcr.microsoft.com/playwright:v1.62.1-jammy
caches:
- node
script:
- npm ci
- npx playwright test
artifacts:
- junit-results/**
- step: &upload
name: Upload to QA Sphere
script:
- npm install -g qas-cli
- qasphere junit-upload --attachments ./junit-results/results.xml
pipelines:
default:
- step: *test
- step: *upload
```
## Complete Working Example
Here's a complete, production-ready configuration:
```yaml
# bitbucket-pipelines.yml
image: node:22
definitions:
caches:
node: node_modules
steps:
- step: &test
name: Run Playwright Tests
image: mcr.microsoft.com/playwright:v1.62.1-jammy
caches:
- node
script:
- npm ci
- npx playwright test || true # Continue even if tests fail
artifacts:
- junit-results/**
- test-results/**
- playwright-report/**
- step: &upload
name: Upload Results to QA Sphere
script:
- npm install -g qas-cli
# Verify results file exists
- test -f junit-results/results.xml || (echo "Results file not found" && exit 1)
# Upload with descriptive run name and attachments
- |
SHORT_COMMIT=$(echo "$BITBUCKET_COMMIT" | cut -c1-7)
qasphere junit-upload \
--run-name "Build #{env:BITBUCKET_BUILD_NUMBER} - {env:BITBUCKET_BRANCH} (${SHORT_COMMIT})" \
--attachments \
./junit-results/results.xml
- echo "✅ Test results uploaded to QA Sphere"
- echo "View at: ${QAS_URL}/project/BD/runs"
pipelines:
default:
- step: *test
- step: *upload
branches:
main:
- step: *test
- step: *upload
develop:
- step: *test
- step: *upload
pull-requests:
'**':
- step: *test
- step: *upload
custom:
nightly:
- step: *test
- step:
<<: *upload
name: Upload Nightly Results
script:
- npm install -g qas-cli
- test -f junit-results/results.xml || (echo "Results file not found" && exit 1)
- qasphere junit-upload --run-name "Nightly Tests - {YYYY}-{MM}-{DD}" --attachments ./junit-results/results.xml
```
## Next Steps
Once you have the basic integration working:
1. **Add More Tests** - Expand your test coverage with proper markers
2. **Set Up Schedules** - Run tests nightly using Bitbucket's scheduled pipelines
3. **Create Dashboards** - Use QA Sphere reports to track quality trends
4. **Configure Notifications** - Get alerts for test failures
5. **Integrate with Jira** - Link test failures to bug tickets (Bitbucket and Jira integrate natively)
## Additional Resources
* [QA Sphere CLI Documentation - Playwright Integration](/docs/cli-usage-playwright)
* [QA Sphere CLI Documentation - WebdriverIO Integration](/docs/cli-usage-webdriverio)
* [QA Sphere API Documentation](/docs/api/api_intro)
* [Authentication Guide](/docs/api/authentication)
* [Bitbucket Pipelines Documentation](https://support.atlassian.com/bitbucket-cloud/docs/get-started-with-bitbucket-pipelines/)
* [Playwright Documentation](https://playwright.dev/)
## Getting Help
If you encounter issues:
1. Check the [Troubleshooting](#troubleshooting) section above
2. Review pipeline logs in Bitbucket
3. Test CLI locally with same configuration
4. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Summary:** You now have everything you need to integrate QA Sphere with Bitbucket Pipelines. The QAS CLI tool automatically handles test result uploads, making test management seamless and automated. Every pipeline run will now update QA Sphere with the latest test results.
---
# GitHub Actions Integration
URL: /docs/integrations/ci-cd/github-actions
Automatically upload test results from your GitHub Actions workflows to QA Sphere using the QAS CLI tool. This integration eliminates manual result entry and provides instant visibility into your automated test results.
## What You'll Achieve
With this integration, every time your GitHub Actions workflow runs:
* Test results automatically upload to QA Sphere
* New test runs are created with workflow information
* Tests are matched to existing QA Sphere test cases
* Pass/fail status, execution time, and screenshots are recorded
* Test history and trends are tracked over time
## Prerequisites
Before starting, ensure you have:
* A GitHub repository with automated tests (Playwright, Cypress, Jest, etc.)
* Tests configured to generate **JUnit XML** format results
* A QA Sphere account with **Test Runner** role or higher
* Test cases in QA Sphere with **markers** (e.g., `BD-001`, `PRJ-123`)
## How It Works
1. Your workflow runs automated tests
2. Tests generate JUnit XML results file
3. QAS CLI tool reads the XML file
4. CLI matches tests to QA Sphere cases using markers
5. Results are uploaded and appear in QA Sphere
## Setup Steps
### Step 1: Create QA Sphere API Key
1. Log into your QA Sphere account
2. Click the **gear icon** ⚙️ in the top right → **Settings**
3. Navigate to **API Keys**
4. Click **Create API Key**
5. **Copy and save the key** - you won't see it again!
Your API key format: `t123.ak456.abc789xyz`
### Step 2: Configure GitHub Secrets
Add these secrets to your GitHub repository:
1. Go to your GitHub repository
2. Navigate to **Settings** → **Secrets and variables** → **Actions**
3. Click **New repository secret** and create:
| Name | Value |
| ----------- | ------------------------------------------------------------- |
| `QAS_TOKEN` | Your API key (e.g., `t123.ak456.abc789xyz`) |
| `QAS_URL` | Your QA Sphere URL (e.g., `https://company.eu1.qasphere.com`) |
4. Click **Add secret** to save each one
**Security**
Never commit API keys to your repository. Always use GitHub Secrets.
### Step 3: Add Test Case Markers
Ensure your test names include QA Sphere markers in the format `PROJECT-SEQUENCE`:
These markers can be found in QA Sphere interface for each test case separately.
**Playwright Example:**
```typescript
test('BD-001: User can login with valid credentials', async ({ page }) => {
await page.goto('https://example.com/login');
await page.fill('#username', 'user@example.com');
await page.fill('#password', 'password123');
await page.click('#login-button');
await expect(page).toHaveURL('/dashboard');
});
test('BD-002: User sees error with invalid credentials', async ({ page }) => {
// test implementation
});
```
**Cypress Example:**
```javascript
describe('Login Flow', () => {
it('BD-001: should login successfully with valid credentials', () => {
cy.visit('/login');
cy.get('#username').type('user@example.com');
cy.get('#password').type('password123');
cy.get('#login-button').click();
cy.url().should('include', '/dashboard');
});
});
```
**Jest Example:**
```javascript
describe('API Tests', () => {
test('BD-015: GET /users returns user list', async () => {
const response = await fetch('/api/users');
expect(response.status).toBe(200);
const data = await response.json();
expect(data).toHaveLength(5);
});
});
```
### Step 4: Configure Test Framework
Configure your test framework to generate JUnit XML output:
#### Playwright Configuration
```javascript
// playwright.config.js
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 30000,
// JUnit reporter for CI/CD
reporter: [
['list'], // Console output
['junit', { outputFile: 'junit-results/results.xml' }] // For QA Sphere
],
use: {
headless: true,
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
{ name: 'firefox', use: { browserName: 'firefox' } },
{ name: 'webkit', use: { browserName: 'webkit' } },
],
});
```
#### Cypress Configuration
```javascript
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
reporter: 'cypress-multi-reporters',
reporterOptions: {
configFile: 'reporter-config.json'
}
}
});
```
```json
// reporter-config.json
{
"reporterEnabled": "spec, mocha-junit-reporter",
"mochaJunitReporterReporterOptions": {
"mochaFile": "junit-results/results.xml"
}
}
```
#### Jest Configuration
```javascript
// jest.config.js
module.exports = {
reporters: [
'default',
['jest-junit', {
outputDirectory: './junit-results',
outputName: 'results.xml',
classNameTemplate: '{classname}',
titleTemplate: '{title}'
}]
]
};
```
### Step 5: Create GitHub Actions Workflow
Create a workflow file `.github/workflows/qa-sphere-tests.yml` in your repository:
#### For Playwright Projects
```yaml
name: QA Sphere Integration
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch: # Allows manual triggering
env:
PLAYWRIGHT_VERSION: "1.62.1"
jobs:
test:
name: Run Playwright Tests
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.62.1-jammy
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run Playwright tests
run: npx playwright test
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: junit-results
path: junit-results/
retention-days: 7
- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 7
upload-to-qasphere:
name: Upload Results to QA Sphere
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
name: junit-results
path: junit-results/
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: qasphere junit-upload ./junit-results/results.xml
- name: Summary
if: always()
run: echo "✅ Test results uploaded to QA Sphere"
```
#### For Cypress Projects
```yaml
name: QA Sphere Integration
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
jobs:
test:
name: Run Cypress Tests
runs-on: ubuntu-latest
container:
image: cypress/browsers:node18.12.0-chrome107
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run Cypress tests
run: npx cypress run
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: junit-results
path: junit-results/
retention-days: 7
- name: Upload videos
uses: actions/upload-artifact@v4
if: always()
with:
name: cypress-videos
path: cypress/videos/
retention-days: 7
- name: Upload screenshots
uses: actions/upload-artifact@v4
if: always()
with:
name: cypress-screenshots
path: cypress/screenshots/
retention-days: 7
upload-to-qasphere:
name: Upload Results to QA Sphere
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
name: junit-results
path: junit-results/
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: qasphere junit-upload ./junit-results/results.xml
- name: Summary
run: echo "✅ Results uploaded to QA Sphere"
```
#### For Jest Projects
```yaml
name: QA Sphere Integration
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
jobs:
test:
name: Run Jest Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install dependencies
run: npm ci
- name: Run Jest tests
run: npm test
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: junit-results
path: junit-results/
retention-days: 7
- name: Upload coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage
path: coverage/
retention-days: 7
upload-to-qasphere:
name: Upload Results to QA Sphere
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
name: junit-results
path: junit-results/
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: qasphere junit-upload ./junit-results/results.xml
- name: Summary
run: echo "✅ Results uploaded to QA Sphere"
```
### Step 6: Push and Verify
1. **Commit your changes**:
```bash
git add .github/workflows/qa-sphere-tests.yml playwright.config.js # or your config files
git commit -m "Add GitHub Actions with QA Sphere integration"
git push origin main
```
2. **Monitor the workflow**:
* Go to GitHub → **Actions** tab
* Watch your workflow execute
* Check both `Run Playwright Tests` and `Upload Results to QA Sphere` jobs
3. **Verify in QA Sphere**:
* Log into QA Sphere
* Navigate to your project → **Test Runs**
* See the new run with your test results
## Advanced Usage
### Available CLI Options
The QAS CLI `junit-upload` command creates a new test run within a QA Sphere project from your JUnit XML files or uploads results to an existing run.
```bash
qasphere junit-upload [options]
```
**Options:**
* `-r, --run-url ` - Upload to an existing test run (otherwise creates a new run)
* `--run-name ` - Name template for creating new test runs (only used when `--run-url` is not specified)
* `--attachments` - Detect and upload attachments (screenshots, videos, logs)
* `--force` - Ignore API request errors, invalid test cases, or attachment issues
* `-h, --help` - Show command help
#### Run Name Template Placeholders
The `--run-name` option supports the following placeholders:
**Environment Variables:**
* `{env:VARIABLE_NAME}` - Any environment variable (e.g., `{env:GITHUB_RUN_NUMBER}`, `{env:GITHUB_SHA}`)
**Date Placeholders:**
* `{YYYY}` - 4-digit year (e.g., 2025)
* `{YY}` - 2-digit year (e.g., 25)
* `{MMM}` - 3-letter month (e.g., Jan, Feb, Mar)
* `{MM}` - 2-digit month (e.g., 01, 02, 12)
* `{DD}` - 2-digit day (e.g., 01, 15, 31)
**Time Placeholders:**
* `{HH}` - 2-digit hour in 24-hour format (e.g., 00, 13, 23)
* `{hh}` - 2-digit hour in 12-hour format (e.g., 01, 12)
* `{mm}` - 2-digit minute (e.g., 00, 30, 59)
* `{ss}` - 2-digit second (e.g., 00, 30, 59)
* `{AMPM}` - AM/PM indicator
**Default Template:**
If `--run-name` is not specified, the default template is:
```
Automated test run - {MMM} {DD}, {YYYY}, {hh}:{mm}:{ss} {AMPM}
```
**Example Output:**
* `Automated test run - Jan 15, 2025, 02:30:45 PM`
The `--run-name` option is only used when creating new test runs (i.e., when `--run-url` is not specified).
**Usage Examples:**
```bash
# Create new run with default name template
qasphere junit-upload ./junit-results/results.xml
# Upload to existing run (--run-name is ignored)
qasphere junit-upload -r https://company.eu1.qasphere.com/project/BD/run/42 ./junit-results/results.xml
# Simple static name
qasphere junit-upload --run-name "v1.4.4-rc5" ./junit-results/results.xml
# With environment variables
qasphere junit-upload --run-name "Run #{env:GITHUB_RUN_NUMBER} - {env:GITHUB_REF_NAME}" ./junit-results/results.xml
# Output: "Run #12345 - main"
# With date placeholders
qasphere junit-upload --run-name "Release {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Release 2025-01-15"
# With date and time placeholders
qasphere junit-upload --run-name "Nightly Tests {MMM} {DD}, {YYYY} at {HH}:{mm}" ./junit-results/results.xml
# Output: "Nightly Tests Jan 15, 2025 at 22:34"
# Complex template with multiple placeholders
qasphere junit-upload --run-name "Build {env:BUILD_NUMBER} - {YYYY}/{MM}/{DD} {hh}:{mm} {AMPM}" ./junit-results/results.xml
# Output: "Build v1.4.4-rc5 - 2025/01/15 10:34 PM"
# With attachments
qasphere junit-upload --attachments ./junit-results/results.xml
# Multiple files
qasphere junit-upload ./junit-results/*.xml
# Force upload on errors
qasphere junit-upload --force ./junit-results/results.xml
```
### Upload to Existing Test Run
To update a specific test run instead of creating a new one:
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
RUN_ID=42
qasphere junit-upload \
-r ${QAS_URL}/project/BD/run/${RUN_ID} \
./junit-results/results.xml
```
### Upload with Attachments
Include screenshots and logs with your results:
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: qasphere junit-upload --attachments ./junit-results/results.xml
```
The CLI automatically detects and uploads:
* Screenshots from test failures
* Video recordings
* Log files
* Any files referenced in the JUnit XML
### Upload Multiple XML Files
If you have multiple test suites generating separate XML files:
```yaml
- name: Upload to QA Sphere
run: qasphere junit-upload ./junit-results/*.xml
```
### Branch-Specific Runs
Create different runs for different branches:
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
# Upload to production run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/100 ./junit-results/results.xml
elif [ "${{ github.ref_name }}" = "develop" ]; then
# Upload to development run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/101 ./junit-results/results.xml
else
# Create new run for feature branches
qasphere junit-upload ./junit-results/results.xml
fi
```
### Add Workflow Metadata
Use the `--run-name` option to include GitHub workflow information in test run titles:
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
qasphere junit-upload \
--run-name "Run #{env:GITHUB_RUN_NUMBER} - {env:GITHUB_REF_NAME}" \
./junit-results/results.xml
# Output: "Run #12345 - main"
```
**Common GitHub Variables:**
* `{env:GITHUB_RUN_NUMBER}` - Workflow run number
* `{env:GITHUB_REF_NAME}` - Branch or tag name
* `{env:GITHUB_SHA}` - Commit SHA (full)
* `{env:GITHUB_ACTOR}` - User who triggered the workflow
* `{env:GITHUB_JOB}` - Current job name
* `{env:GITHUB_WORKFLOW}` - Workflow name
**Examples:**
```yaml
# Workflow with date and time
- run: qasphere junit-upload --run-name "Run #{env:GITHUB_RUN_NUMBER} - {YYYY}-{MM}-{DD} {HH}:{mm}" ./junit-results/results.xml
# Branch and commit info
- run: qasphere junit-upload --run-name "{env:GITHUB_REF_NAME} - {env:GITHUB_SHA}" ./junit-results/results.xml
# Complete metadata
- run: qasphere junit-upload --run-name "Build #{env:GITHUB_RUN_NUMBER} ({env:GITHUB_REF_NAME}) - {MMM} {DD}, {hh}:{mm} {AMPM}" ./junit-results/results.xml
```
### Force Upload on Errors
Continue uploading even if some tests can't be matched:
```yaml
- name: Upload to QA Sphere
run: qasphere junit-upload --force ./junit-results/results.xml
```
## Common Scenarios
### Scenario 1: Nightly Test Runs
Run tests on a schedule and upload results with descriptive names:
```yaml
name: Nightly Tests
on:
schedule:
- cron: '0 2 * * *' # Run at 2 AM UTC daily
workflow_dispatch:
jobs:
test:
name: Run Nightly Tests
runs-on: ubuntu-latest
# ... test steps ...
upload-to-qasphere:
name: Upload Results
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
name: junit-results
path: junit-results/
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
# Create run with date in the name
qasphere junit-upload --run-name "Nightly Tests - {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Nightly Tests - 2025-01-15"
# Or with time included
qasphere junit-upload --run-name "Nightly {MMM} {DD}, {YYYY} at {HH}:{mm}" ./junit-results/results.xml
# Output: "Nightly Jan 15, 2025 at 22:30"
```
### Scenario 2: Parallel Test Execution
Run tests in parallel using matrix strategy and upload all results:
```yaml
name: Parallel Tests
on:
push:
branches: [main, develop]
jobs:
test:
name: Test - ${{ matrix.suite }}
runs-on: ubuntu-latest
strategy:
matrix:
suite: [unit, integration, e2e]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install dependencies
run: npm ci
- name: Run ${{ matrix.suite }} tests
run: npm run test:${{ matrix.suite }}
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: junit-results-${{ matrix.suite }}
path: junit-results/
retention-days: 7
upload-to-qasphere:
name: Upload Results to QA Sphere
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download all test results
uses: actions/download-artifact@v4
with:
pattern: junit-results-*
path: junit-results/
merge-multiple: true
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: qasphere junit-upload ./junit-results/*.xml
```
### Scenario 3: Multi-Environment Testing
Test against different environments:
```yaml
name: Multi-Environment Tests
on:
push:
branches: [main, develop]
jobs:
test:
name: Test - ${{ matrix.environment }}
runs-on: ubuntu-latest
strategy:
matrix:
environment: [staging, production]
include:
- environment: staging
base_url: https://staging.example.com
- environment: production
base_url: https://example.com
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install dependencies
run: npm ci
- name: Run tests
env:
BASE_URL: ${{ matrix.base_url }}
TEST_ENV: ${{ matrix.environment }}
run: npm test
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: junit-results-${{ matrix.environment }}
path: junit-results/
retention-days: 7
upload-to-qasphere:
name: Upload Results
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download all test results
uses: actions/download-artifact@v4
with:
pattern: junit-results-*
path: junit-results/
merge-multiple: true
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: qasphere junit-upload ./junit-results/*.xml
```
### Scenario 4: Version/Release Tagging
Tag test runs with version numbers or release names:
```yaml
name: Release Tests
on:
push:
tags:
- 'v*'
workflow_dispatch:
env:
VERSION: ${{ github.ref_name }}
jobs:
test:
name: Run Release Tests
runs-on: ubuntu-latest
# ... test steps ...
upload-to-qasphere:
name: Upload Results
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
name: junit-results
path: junit-results/
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
# Simple version tag
qasphere junit-upload --run-name "Release {env:VERSION}" ./junit-results/results.xml
# Output: "Release v1.4.5"
# Version with date
qasphere junit-upload --run-name "Release {env:VERSION} - {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Release v1.4.5 - 2025-01-15"
```
For different handling of tags vs branches:
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
# For git tags, use tag name
qasphere junit-upload --run-name "Release {env:GITHUB_REF_NAME}" ./junit-results/results.xml
else
# For regular commits, use branch and commit
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
qasphere junit-upload --run-name "{env:GITHUB_REF_NAME} - ${SHORT_SHA}" ./junit-results/results.xml
fi
```
## Troubleshooting
### Issue: Tests Not Appearing in QA Sphere
**Symptoms:**
* Upload succeeds but no results in QA Sphere
* "Test case not found" warnings in logs
**Solutions:**
1. **Ensure test cases exist in QA Sphere:**
* Check that `BD-001`, `BD-002`, etc. exist in your QA Sphere project
* Verify the project code matches (BD, PRJ, etc.)
2. **Check marker format:**
* Must be `PROJECT-NUMBER` format
* Examples: `BD-001`, `PRJ-123`, `TEST-456`
### Issue: Authentication Failed (401 Error)
**Symptoms:**
```
Error: Authentication failed (401)
```
**Solutions:**
1. **Verify API key is correct:**
* Go to QA Sphere → Settings → API Keys
* Check the key hasn't been deleted
* Regenerate if needed
2. **Check GitHub Secrets:**
* Settings → Secrets and variables → Actions
* Verify `QAS_TOKEN` is set correctly
* Ensure no extra spaces or line breaks
3. **Verify key permissions:**
* API key must have Test Runner role or higher
* Check user permissions in QA Sphere
### Issue: JUnit XML File Not Found
**Symptoms:**
```
Error: File ./junit-results/results.xml does not exist
```
**Solutions:**
1. **Check artifact upload configuration:**
```yaml
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: junit-results
path: junit-results/ # Make sure this matches your output path
```
2. **Verify test framework configuration:**
* Playwright: Check `playwright.config.js` reporter
* Cypress: Check `reporter-config.json`
* Jest: Check `jest.config.js` reporters
3. **Add debug output:**
```yaml
- name: Debug - List files
run: |
ls -la junit-results/
cat junit-results/results.xml
- name: Upload to QA Sphere
run: qasphere junit-upload ./junit-results/results.xml
```
### Issue: Artifact Not Found
**Symptoms:**
```
Error: Unable to find any artifacts for the associated workflow
```
**Solutions:**
1. **Ensure artifact names match:**
```yaml
# In test job
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: junit-results # Must match
# In upload job
- name: Download test results
uses: actions/download-artifact@v4
with:
name: junit-results # Must match
```
2. **Check job dependencies:**
```yaml
upload-to-qasphere:
needs: test # Must reference the correct job name
if: always() # Run even if test job fails
```
### Issue: Playwright Version Mismatch
**Symptoms:**
```
Error: Executable doesn't exist at /ms-playwright/chromium...
```
**Solution:**
Match Docker image version to your Playwright package version:
```bash
# Check your Playwright version
npm list @playwright/test
# Output: @playwright/test@1.62.1
```
```yaml
# Update workflow file
jobs:
test:
container:
image: mcr.microsoft.com/playwright:v1.62.1-jammy # Match the version
```
### Issue: Secrets Not Available
**Symptoms:**
```
Error: QAS_TOKEN environment variable is not set
```
**Solutions:**
1. **Verify secrets are defined:**
* Go to repository Settings → Secrets and variables → Actions
* Ensure `QAS_TOKEN` and `QAS_URL` exist
2. **Check secret usage in workflow:**
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }} # Correct syntax
QAS_URL: ${{ secrets.QAS_URL }}
run: qasphere junit-upload ./junit-results/results.xml
```
3. **For organization secrets:**
* Ensure repository has access to organization secrets
* Check secret visibility settings
### Issue: Workflow Doesn't Trigger
**Symptoms:**
* Push code but workflow doesn't run
* Workflow file exists but not visible in Actions tab
**Solutions:**
1. **Verify workflow file location:**
```
.github/workflows/qa-sphere-tests.yml ✅ Correct
.github/workflow/qa-sphere-tests.yml ❌ Wrong (missing 's')
github/workflows/qa-sphere-tests.yml ❌ Wrong (missing '.')
```
2. **Check YAML syntax:**
```bash
# Validate YAML locally
npx js-yaml .github/workflows/qa-sphere-tests.yml
```
3. **Verify trigger configuration:**
```yaml
on:
push:
branches: [main, develop] # Check branch names match
pull_request:
branches: [main, develop]
```
4. **Check branch protection rules:**
* Repository Settings → Branches
* Ensure Actions aren't blocked by branch protection
## Best Practices
### 1. Always Use Markers
Include QA Sphere markers in all automated tests:
```typescript
// ✅ Good
test('BD-001: User can login successfully', async ({ page }) => {});
// ❌ Bad - no marker
test('User can login successfully', async ({ page }) => {});
```
### 2. Upload on Every Workflow Run
Configure upload to run even when tests fail:
```yaml
upload-to-qasphere:
needs: test
if: always() # Run even if test job fails
```
This ensures you track both passing and failing test results.
### 3. Use Descriptive Run Names
Use the `--run-name` option to create meaningful test run titles:
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
qasphere junit-upload \
--run-name "Run #{env:GITHUB_RUN_NUMBER} - {env:GITHUB_REF_NAME}" \
./junit-results/results.xml
```
For branch-specific runs, you can also upload to existing runs:
```yaml
- name: Upload to QA Sphere
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
# Upload to production run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/100 ./junit-results/results.xml
elif [ "${{ github.ref_name }}" = "develop" ]; then
# Upload to development run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/101 ./junit-results/results.xml
else
# Create new run for feature branches
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
qasphere junit-upload --run-name "{env:GITHUB_REF_NAME} - ${SHORT_SHA}" ./junit-results/results.xml
fi
```
### 4. Secure Your API Keys
* ✅ Store in GitHub Secrets
* ✅ Use repository or organization secrets
* ✅ Rotate keys periodically
* ❌ Never commit to repository
* ❌ Never log or print in workflow
### 5. Upload Attachments for Failures
Help debug failures by including screenshots:
```yaml
- name: Upload to QA Sphere
run: qasphere junit-upload --attachments ./junit-results/results.xml
```
### 6. Match Playwright Versions
Always keep Docker image version in sync with npm package:
```json
// package.json
{
"devDependencies": {
"@playwright/test": "1.62.1"
}
}
```
```yaml
# .github/workflows/qa-sphere-tests.yml
jobs:
test:
container:
image: mcr.microsoft.com/playwright:v1.62.1-jammy
```
### 7. Use Caching for Faster Builds
Cache dependencies to speed up workflow runs:
```yaml
- name: Cache node modules
uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
```
### 8. Use Concurrency Controls
Prevent redundant workflow runs for the same branch:
```yaml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
```
### 9. Test Locally First
Before pushing to GitHub, test the integration locally:
```bash
# Set environment variables
export QAS_TOKEN=your.api.key
export QAS_URL=https://company.eu1.qasphere.com
# Run tests
npm test
# Upload results
npx qas-cli junit-upload ./junit-results/results.xml
```
### 10. Monitor Upload Success
Add error handling to track upload status:
```yaml
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
if qasphere junit-upload ./junit-results/results.xml; then
echo "✅ Successfully uploaded results to QA Sphere"
else
echo "❌ Failed to upload results to QA Sphere"
exit 1
fi
```
### 11. Set Appropriate Artifact Retention
Balance storage costs with retention needs:
```yaml
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: junit-results
path: junit-results/
retention-days: 7 # Adjust based on your needs (1-90 days)
```
## Complete Working Example
Here's a complete, production-ready configuration:
```yaml
# .github/workflows/qa-sphere-tests.yml
name: QA Sphere Integration
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
# Prevent redundant runs for the same branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
PLAYWRIGHT_VERSION: "1.62.1"
jobs:
test:
name: Run Playwright Tests
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.62.1-jammy
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Cache node modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- name: Install dependencies
run: npm ci
- name: Run Playwright tests
run: npx playwright test
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: junit-results
path: junit-results/
retention-days: 7
- name: Upload test artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: test-artifacts
path: |
test-results/
playwright-report/
retention-days: 7
upload-to-qasphere:
name: Upload Results to QA Sphere
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
name: junit-results
path: junit-results/
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install QAS CLI
run: npm install -g qas-cli
- name: Verify results file exists
run: test -f junit-results/results.xml || (echo "Results file not found" && exit 1)
- name: Upload to QA Sphere
env:
QAS_TOKEN: ${{ secrets.QAS_TOKEN }}
QAS_URL: ${{ secrets.QAS_URL }}
run: |
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
qasphere junit-upload \
--run-name "Run #{env:GITHUB_RUN_NUMBER} - {env:GITHUB_REF_NAME} (${SHORT_SHA})" \
--attachments \
./junit-results/results.xml
- name: Workflow Summary
if: always()
run: |
echo "## QA Sphere Upload Summary" >> $GITHUB_STEP_SUMMARY
echo "✅ Test results uploaded to QA Sphere" >> $GITHUB_STEP_SUMMARY
echo "**View results:** ${{ secrets.QAS_URL }}/project/BD/runs" >> $GITHUB_STEP_SUMMARY
echo "**Workflow:** Run #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY
echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
```
## Additional Resources
* [QA Sphere CLI Documentation - Playwright Integration](/docs/cli-usage-playwright)
* [QA Sphere CLI Documentation - WebdriverIO Integration](/docs/cli-usage-webdriverio)
* [QA Sphere API Documentation](/docs/api/api_intro)
* [Authentication Guide](/docs/api/authentication)
* [GitHub Actions Documentation](https://docs.github.com/en/actions)
* [Playwright Documentation](https://playwright.dev/)
## Getting Help
If you encounter issues:
1. Check the [Troubleshooting](#troubleshooting) section above
2. Review workflow logs in GitHub Actions
3. Test CLI locally with same configuration
4. Check GitHub Actions workflow syntax
5. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Summary:** You now have everything you need to integrate QA Sphere with GitHub Actions. The QAS CLI tool automatically handles test result uploads, making test management seamless and automated. Every workflow run will now update QA Sphere with the latest test results.
---
# GitLab CI/CD Integration
URL: /docs/integrations/ci-cd/gitlab
Automatically upload test results from your GitLab CI/CD pipelines to QA Sphere using the QAS CLI tool. This integration eliminates manual result entry and provides instant visibility into your automated test results.
## What You'll Achieve
With this integration, every time your GitLab pipeline runs:
* Test results automatically upload to QA Sphere
* New test runs are created with pipeline information
* Tests are matched to existing QA Sphere test cases
* Pass/fail status, execution time, and screenshots are recorded
* Test history and trends are tracked over time
## Prerequisites
Before starting, ensure you have:
* A GitLab project with automated tests (Playwright, Cypress, Jest, etc.)
* Tests configured to generate **JUnit XML** format results
* A QA Sphere account with **Test Runner** role or higher
* Test cases in QA Sphere with **markers** (e.g., `BD-001`, `PRJ-123`)
## How It Works
1. Your pipeline runs automated tests
2. Tests generate JUnit XML results file
3. QAS CLI tool reads the XML file
4. CLI matches tests to QA Sphere cases using markers
5. Results are uploaded and appear in QA Sphere
## Setup Steps
### Step 1: Create QA Sphere API Key
1. Log into your QA Sphere account
2. Click the **gear icon** ⚙️ in the top right → **Settings**
3. Navigate to **API Keys**
4. Click **Create API Key**
5. **Copy and save the key** - you won't see it again!
Your API key format: `t123.ak456.abc789xyz`
### Step 2: Configure GitLab Variables
Add these secrets to your GitLab project:
1. Go to your GitLab project
2. Navigate to **Settings** → **CI/CD** → **Variables**
3. Click **Add variable** and create:
| Key | Value | Flags |
| ----------- | ------------------------------------------------------------- | ----------------- |
| `QAS_TOKEN` | Your API key (e.g., `t123.ak456.abc789xyz`) | Protected, Masked |
| `QAS_URL` | Your QA Sphere URL (e.g., `https://company.eu1.qasphere.com`) | Protected |
4. Click **Add variable** to save
**Security**
Never commit API keys to your repository. Always use GitLab CI/CD variables.
### Step 3: Add Test Case Markers
Ensure your test names include QA Sphere markers in the format `PROJECT-SEQUENCE`.
These markers can be found in QA Sphere interface for each test case separately.
**Playwright Example:**
```typescript
test('BD-001: User can login with valid credentials', async ({ page }) => {
await page.goto('https://example.com/login');
await page.fill('#username', 'user@example.com');
await page.fill('#password', 'password123');
await page.click('#login-button');
await expect(page).toHaveURL('/dashboard');
});
test('BD-002: User sees error with invalid credentials', async ({ page }) => {
// test implementation
});
```
**Cypress Example:**
```javascript
describe('Login Flow', () => {
it('BD-001: should login successfully with valid credentials', () => {
cy.visit('/login');
cy.get('#username').type('user@example.com');
cy.get('#password').type('password123');
cy.get('#login-button').click();
cy.url().should('include', '/dashboard');
});
});
```
**Jest Example:**
```javascript
describe('API Tests', () => {
test('BD-015: GET /users returns user list', async () => {
const response = await fetch('/api/users');
expect(response.status).toBe(200);
const data = await response.json();
expect(data).toHaveLength(5);
});
});
```
### Step 4: Configure Test Framework
Configure your test framework to generate JUnit XML output:
#### Playwright Configuration
```javascript
// playwright.config.js
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 30000,
// JUnit reporter for CI/CD
reporter: [
['list'], // Console output
['junit', { outputFile: 'junit-results/results.xml' }] // For QA Sphere
],
use: {
headless: true,
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
{ name: 'firefox', use: { browserName: 'firefox' } },
{ name: 'webkit', use: { browserName: 'webkit' } },
],
});
```
#### Cypress Configuration
```javascript
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
reporter: 'cypress-multi-reporters',
reporterOptions: {
configFile: 'reporter-config.json'
}
}
});
```
```json
// reporter-config.json
{
"reporterEnabled": "spec, mocha-junit-reporter",
"mochaJunitReporterReporterOptions": {
"mochaFile": "junit-results/results.xml"
}
}
```
#### Jest Configuration
```javascript
// jest.config.js
module.exports = {
reporters: [
'default',
['jest-junit', {
outputDirectory: './junit-results',
outputName: 'results.xml',
classNameTemplate: '{classname}',
titleTemplate: '{title}'
}]
]
};
```
### Step 5: Create GitLab Pipeline
Create or update `.gitlab-ci.yml` in your repository root:
#### For Playwright Projects
```yaml
stages:
- test
- report
variables:
# Disable Husky git hooks in CI
HUSKY: 0
# Run Playwright tests
test:
stage: test
# IMPORTANT: Match image version to your @playwright/test package version
image: mcr.microsoft.com/playwright:v1.62.1-jammy
script:
- npm ci
- npx playwright test
artifacts:
when: always # Upload artifacts even if tests fail
paths:
- junit-results/
- test-results/
- playwright-report/
reports:
junit: junit-results/results.xml
expire_in: 1 week
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Upload results to QA Sphere
upload-to-qasphere:
stage: report
image: node:22
needs:
- job: test
artifacts: true
before_script:
- npm install -g qas-cli
script:
# Upload test results (automatically creates new run)
- qasphere junit-upload ./junit-results/results.xml
- echo "✅ Test results uploaded to QA Sphere"
when: always
allow_failure: true
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
```
#### For Cypress Projects
```yaml
stages:
- test
- report
test:
stage: test
image: cypress/browsers:node18.12.0-chrome107
script:
- npm ci
- npx cypress run
artifacts:
when: always
paths:
- junit-results/
- cypress/videos/
- cypress/screenshots/
reports:
junit: junit-results/results.xml
expire_in: 1 week
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
upload-to-qasphere:
stage: report
image: node:22
needs:
- job: test
artifacts: true
before_script:
- npm install -g qas-cli
script:
- qasphere junit-upload ./junit-results/results.xml
- echo "✅ Results uploaded to QA Sphere"
when: always
allow_failure: true
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
```
#### For Jest Projects
```yaml
stages:
- test
- report
test:
stage: test
image: node:22
script:
- npm ci
- npm test
artifacts:
when: always
paths:
- junit-results/
- coverage/
reports:
junit: junit-results/results.xml
expire_in: 1 week
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
upload-to-qasphere:
stage: report
image: node:22
needs:
- job: test
artifacts: true
before_script:
- npm install -g qas-cli
script:
- qasphere junit-upload ./junit-results/results.xml
- echo "✅ Results uploaded to QA Sphere"
when: always
allow_failure: true
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
```
### Step 6: Push and Verify
1. **Commit your changes**:
```bash
git add .gitlab-ci.yml playwright.config.js # or your config files
git commit -m "Add GitLab CI/CD with QA Sphere integration"
git push origin main
```
2. **Monitor the pipeline**:
* Go to GitLab → **Build** → **Pipelines**
* Watch your pipeline execute
* Check both `test` and `upload-to-qasphere` stages
3. **Verify in QA Sphere**:
* Log into QA Sphere
* Navigate to your project → **Test Runs**
* See the new run with your test results
## Advanced Usage
### Available CLI Options
The QAS CLI `junit-upload` command creates a new test run within a QA Sphere project from your JUnit XML files or uploads results to an existing run.
```bash
qasphere junit-upload [options]
```
**Options:**
* `-r, --run-url ` - Upload to an existing test run (otherwise creates a new run)
* `--run-name ` - Name template for creating new test runs (only used when `--run-url` is not specified)
* `--attachments` - Detect and upload attachments (screenshots, videos, logs)
* `--force` - Ignore API request errors, invalid test cases, or attachment issues
* `-h, --help` - Show command help
#### Run Name Template Placeholders
The `--run-name` option supports the following placeholders:
**Environment Variables:**
* `{env:VARIABLE_NAME}` - Any environment variable (e.g., `{env:CI_PIPELINE_ID}`, `{env:CI_COMMIT_SHA}`)
**Date Placeholders:**
* `{YYYY}` - 4-digit year (e.g., 2025)
* `{YY}` - 2-digit year (e.g., 25)
* `{MMM}` - 3-letter month (e.g., Jan, Feb, Mar)
* `{MM}` - 2-digit month (e.g., 01, 02, 12)
* `{DD}` - 2-digit day (e.g., 01, 15, 31)
**Time Placeholders:**
* `{HH}` - 2-digit hour in 24-hour format (e.g., 00, 13, 23)
* `{hh}` - 2-digit hour in 12-hour format (e.g., 01, 12)
* `{mm}` - 2-digit minute (e.g., 00, 30, 59)
* `{ss}` - 2-digit second (e.g., 00, 30, 59)
* `{AMPM}` - AM/PM indicator
**Default Template:**
If `--run-name` is not specified, the default template is:
```
Automated test run - {MMM} {DD}, {YYYY}, {hh}:{mm}:{ss} {AMPM}
```
**Example Output:**
* `Automated test run - Jan 15, 2025, 02:30:45 PM`
The `--run-name` option is only used when creating new test runs (i.e., when `--run-url` is not specified).
**Usage Examples:**
```bash
# Create new run with default name template
qasphere junit-upload ./junit-results/results.xml
# Upload to existing run (--run-name is ignored)
qasphere junit-upload -r https://company.eu1.qasphere.com/project/BD/run/42 ./junit-results/results.xml
# Simple static name
qasphere junit-upload --run-name "v1.4.4-rc5" ./junit-results/results.xml
# With environment variables
qasphere junit-upload --run-name "Pipeline #{env:CI_PIPELINE_ID} - {env:CI_COMMIT_REF_NAME}" ./junit-results/results.xml
# Output: "Pipeline #12345 - main"
# With date placeholders
qasphere junit-upload --run-name "Release {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Release 2025-01-15"
# With date and time placeholders
qasphere junit-upload --run-name "Nightly Tests {MMM} {DD}, {YYYY} at {HH}:{mm}" ./junit-results/results.xml
# Output: "Nightly Tests Jan 15, 2025 at 22:34"
# Complex template with multiple placeholders
qasphere junit-upload --run-name "Build {env:BUILD_NUMBER} - {YYYY}/{MM}/{DD} {hh}:{mm} {AMPM}" ./junit-results/results.xml
# Output: "Build v1.4.4-rc5 - 2025/01/15 10:34 PM"
# With attachments
qasphere junit-upload --attachments ./junit-results/results.xml
# Multiple files
qasphere junit-upload ./junit-results/*.xml
# Force upload on errors
qasphere junit-upload --force ./junit-results/results.xml
```
### Upload to Existing Test Run
To update a specific test run instead of creating a new one:
```yaml
upload-to-qasphere:
script:
- |
RUN_ID=42 # Your run ID
qasphere junit-upload \
-r ${QAS_URL}/project/BD/run/${RUN_ID} \
./junit-results/results.xml
```
### Upload with Attachments
Include screenshots and logs with your results:
```yaml
upload-to-qasphere:
script:
- qasphere junit-upload --attachments ./junit-results/results.xml
```
The CLI automatically detects and uploads:
* Screenshots from test failures
* Video recordings
* Log files
* Any files referenced in the JUnit XML
### Upload Multiple XML Files
If you have multiple test suites generating separate XML files:
```yaml
upload-to-qasphere:
script:
- qasphere junit-upload ./junit-results/*.xml
```
### Branch-Specific Runs
Create different runs for different branches:
```yaml
upload-to-qasphere:
script:
- |
if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
# Upload to production run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/100 ./junit-results/results.xml
elif [ "$CI_COMMIT_REF_NAME" = "develop" ]; then
# Upload to development run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/101 ./junit-results/results.xml
else
# Create new run for feature branches
qasphere junit-upload ./junit-results/results.xml
fi
```
### Add Pipeline Metadata
Use the `--run-name` option to include GitLab pipeline information in test run titles:
```yaml
upload-to-qasphere:
script:
# Include pipeline ID and branch name
- |
qasphere junit-upload \
--run-name "Pipeline #{env:CI_PIPELINE_ID} - {env:CI_COMMIT_REF_NAME}" \
./junit-results/results.xml
# Output: "Pipeline #12345 - main"
```
**Common GitLab Variables:**
* `{env:CI_PIPELINE_ID}` - Pipeline ID number
* `{env:CI_COMMIT_REF_NAME}` - Branch or tag name
* `{env:CI_COMMIT_SHORT_SHA}` - Short commit SHA
* `{env:CI_COMMIT_SHA}` - Full commit SHA
* `{env:GITLAB_USER_NAME}` - User who triggered the pipeline
* `{env:CI_JOB_NAME}` - Current job name
**Examples:**
```yaml
# Pipeline with date and time
- qasphere junit-upload --run-name "Pipeline #{env:CI_PIPELINE_ID} - {YYYY}-{MM}-{DD} {HH}:{mm}" ./junit-results/results.xml
# Branch and commit info
- qasphere junit-upload --run-name "{env:CI_COMMIT_REF_NAME} - {env:CI_COMMIT_SHORT_SHA}" ./junit-results/results.xml
# Complete metadata
- qasphere junit-upload --run-name "Build #{env:CI_PIPELINE_ID} ({env:CI_COMMIT_REF_NAME}) - {MMM} {DD}, {hh}:{mm} {AMPM}" ./junit-results/results.xml
```
### Force Upload on Errors
Continue uploading even if some tests can't be matched:
```yaml
upload-to-qasphere:
script:
- qasphere junit-upload --force ./junit-results/results.xml
```
## Common Scenarios
### Scenario 1: Nightly Test Runs
Run tests on a schedule and upload results with descriptive names:
```yaml
test:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" # Only run on scheduled pipelines
- if: $CI_COMMIT_BRANCH == "main"
upload-to-qasphere:
script:
# Create run with date in the name
- qasphere junit-upload --run-name "Nightly Tests - {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Nightly Tests - 2025-01-15"
# Or with time included
- qasphere junit-upload --run-name "Nightly {MMM} {DD}, {YYYY} at {HH}:{mm}" ./junit-results/results.xml
# Output: "Nightly Jan 15, 2025 at 22:30"
```
Create the schedule in GitLab: **CI/CD** → **Schedules** → **New schedule**
### Scenario 2: Parallel Test Execution
Run tests in parallel and upload all results:
```yaml
test-unit:
stage: test
script:
- npm run test:unit
artifacts:
paths:
- junit-results/unit-results.xml
test-integration:
stage: test
script:
- npm run test:integration
artifacts:
paths:
- junit-results/integration-results.xml
upload-to-qasphere:
stage: report
needs:
- job: test-unit
artifacts: true
- job: test-integration
artifacts: true
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/*.xml
```
### Scenario 3: Multi-Environment Testing
Test against different environments:
```yaml
test-staging:
variables:
TEST_ENV: "staging"
BASE_URL: "https://staging.example.com"
script:
- npm test
artifacts:
paths:
- junit-results/staging-results.xml
test-production:
variables:
TEST_ENV: "production"
BASE_URL: "https://example.com"
script:
- npm test
artifacts:
paths:
- junit-results/production-results.xml
upload-to-qasphere:
script:
- npm install -g qas-cli
- qasphere junit-upload ./junit-results/*.xml
```
### Scenario 4: Version/Release Tagging
Tag test runs with version numbers or release names:
```yaml
variables:
VERSION: "v1.4.5"
upload-to-qasphere:
script:
# Simple version tag
- qasphere junit-upload --run-name "Release {env:VERSION}" ./junit-results/results.xml
# Output: "Release v1.4.5"
# Version with date
- qasphere junit-upload --run-name "Release {env:VERSION} - {YYYY}-{MM}-{DD}" ./junit-results/results.xml
# Output: "Release v1.4.5 - 2025-01-15"
# Pre-release/RC builds
- qasphere junit-upload --run-name "{env:VERSION}-rc{env:CI_PIPELINE_ID}" ./junit-results/results.xml
# Output: "v1.4.5-rc12345"
```
For tagged releases in GitLab:
```yaml
upload-to-qasphere:
script:
- |
if [ -n "$CI_COMMIT_TAG" ]; then
# For git tags, use tag name
qasphere junit-upload --run-name "Release {env:CI_COMMIT_TAG}" ./junit-results/results.xml
else
# For regular commits, use branch and commit
qasphere junit-upload --run-name "{env:CI_COMMIT_REF_NAME} - {env:CI_COMMIT_SHORT_SHA}" ./junit-results/results.xml
fi
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH == "main"
```
## Troubleshooting
### Issue: Tests Not Appearing in QA Sphere
**Symptoms:**
* Upload succeeds but no results in QA Sphere
* "Test case not found" warnings in logs
**Solutions:**
1. **Ensure test cases exist in QA Sphere:**
* Check that `BD-001`, `BD-002`, etc. exist in your QA Sphere project
* Verify the project code matches (BD, PRJ, etc.)
2. **Check marker format:**
* Must be `PROJECT-NUMBER` format
* Examples: `BD-001`, `PRJ-123`, `TEST-456`
### Issue: Authentication Failed (401 Error)
**Symptoms:**
```
Error: Authentication failed (401)
```
**Solutions:**
1. **Verify API key is correct:**
* Go to QA Sphere → Settings → API Keys
* Check the key hasn't been deleted
* Regenerate if needed
2. **Check GitLab variables:**
* Settings → CI/CD → Variables
* Verify `QAS_TOKEN` is set correctly
* Ensure no extra spaces or line breaks
3. **Verify key permissions:**
* API key must have Test Runner role or higher
* Check user permissions in QA Sphere
### Issue: JUnit XML File Not Found
**Symptoms:**
```
Error: File ./junit-results/results.xml does not exist
```
**Solutions:**
1. **Check test job artifacts:**
```yaml
test:
artifacts:
paths:
- junit-results/ # Make sure this matches your output path
```
2. **Verify test framework configuration:**
* Playwright: Check `playwright.config.js` reporter
* Cypress: Check `reporter-config.json`
* Jest: Check `jest.config.js` reporters
3. **Add debug output:**
```yaml
upload-to-qasphere:
script:
- ls -la junit-results/ # List files
- cat junit-results/results.xml # Show content
- qasphere junit-upload ./junit-results/results.xml
```
### Issue: Playwright Version Mismatch
**Symptoms:**
```
Error: Executable doesn't exist at /ms-playwright/chromium...
║ - current: mcr.microsoft.com/playwright:v1.40.0-jammy
║ - required: mcr.microsoft.com/playwright:v1.62.1-jammy
```
**Solution:**
Match Docker image version to your Playwright package version:
```bash
# Check your Playwright version
npm list @playwright/test
# Output: @playwright/test@1.62.1
```
```yaml
# Update .gitlab-ci.yml
test:
image: mcr.microsoft.com/playwright:v1.62.1-jammy # Match the version
```
### Issue: Pipeline Fails But Tests Pass
**Symptoms:**
* Tests execute successfully
* Artifacts are uploaded
* Job still marked as failed
**Solution:**
Force job success while preserving test results:
```yaml
test:
script:
- npm ci
- |
set +e
npx playwright test
TEST_EXIT=$?
set -e
echo "Tests completed with exit code: $TEST_EXIT"
exit 0 # Force success
artifacts:
when: always
paths:
- junit-results/
```
### Issue: Upload Job Doesn't Run
**Symptoms:**
* Test job completes
* Upload job never starts
**Solutions:**
1. **Check needs configuration:**
```yaml
upload-to-qasphere:
needs:
- job: test # Must match test job name exactly
artifacts: true
```
2. **Verify branch rules:**
```yaml
upload-to-qasphere:
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
```
3. **Check `when` clause:**
```yaml
upload-to-qasphere:
when: always # Run even if test job fails
```
## Best Practices
### 1. Always Use Markers
Include QA Sphere markers in all automated tests:
```typescript
// ✅ Good
test('BD-001: User can login successfully', async ({ page }) => {});
// ❌ Bad - no marker
test('User can login successfully', async ({ page }) => {});
```
### 2. Upload on Every Pipeline Run
Configure upload to run even when tests fail:
```yaml
upload-to-qasphere:
when: always
allow_failure: true
```
This ensures you track both passing and failing test results.
### 3. Use Descriptive Run Names
Use the `--run-name` option to create meaningful test run titles:
```yaml
upload-to-qasphere:
script:
# Include pipeline and branch information
- |
qasphere junit-upload \
--run-name "Pipeline #{env:CI_PIPELINE_ID} - {env:CI_COMMIT_REF_NAME}" \
./junit-results/results.xml
```
For branch-specific runs, you can also upload to existing runs:
```yaml
script:
- |
if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
# Upload to production run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/100 ./junit-results/results.xml
elif [ "$CI_COMMIT_REF_NAME" = "develop" ]; then
# Upload to development run
qasphere junit-upload -r ${QAS_URL}/project/BD/run/101 ./junit-results/results.xml
else
# Create new run for feature branches
qasphere junit-upload --run-name "{env:CI_COMMIT_REF_NAME} - {env:CI_COMMIT_SHORT_SHA}" ./junit-results/results.xml
fi
```
### 4. Secure Your API Keys
* Store in GitLab CI/CD variables
* Mark as Protected and Masked
* Rotate keys periodically
* Never commit to repository
* Never log or print in pipeline
### 5. Upload Attachments for Failures
Help debug failures by including screenshots:
```yaml
script:
- qasphere junit-upload --attachments ./junit-results/results.xml
```
### 6. Match Playwright Versions
Always keep Docker image version in sync with npm package:
```json
// package.json
{
"devDependencies": {
"@playwright/test": "1.62.1"
}
}
```
```yaml
# .gitlab-ci.yml
image: mcr.microsoft.com/playwright:v1.62.1-jammy
```
### 7. Test Locally First
Before pushing to GitLab, test the integration locally:
```bash
# Set environment variables
export QAS_TOKEN=your.api.key
export QAS_URL=https://company.eu1.qasphere.com
# Run tests
npm test
# Upload results
npx qas-cli junit-upload ./junit-results/results.xml
```
### 8. Monitor Upload Success
Add logging to track upload status:
```yaml
upload-to-qasphere:
script:
- npm install -g qas-cli
- |
if qasphere junit-upload ./junit-results/results.xml; then
echo "✅ Successfully uploaded results to QA Sphere"
else
echo "❌ Failed to upload results to QA Sphere"
exit 1
fi
```
## Complete Working Example
Here's a complete, production-ready configuration:
```yaml
# .gitlab-ci.yml
stages:
- test
- report
variables:
HUSKY: 0
PLAYWRIGHT_VERSION: "1.62.1"
# Cache node modules for faster builds
cache:
paths:
- node_modules/
# Run Playwright tests
test:
stage: test
image: mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-jammy
before_script:
- npm ci
script:
- npx playwright test
artifacts:
when: always
paths:
- junit-results/
- test-results/
- playwright-report/
reports:
junit: junit-results/results.xml
expire_in: 1 week
retry:
max: 1
when:
- runner_system_failure
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
tags:
- docker
# Upload results to QA Sphere
upload-to-qasphere:
stage: report
image: node:22
needs:
- job: test
artifacts: true
before_script:
- npm install -g qas-cli
script:
# Verify file exists
- test -f junit-results/results.xml || (echo "Results file not found" && exit 1)
# Upload with descriptive run name and attachments
- |
qasphere junit-upload \
--run-name "Pipeline #{env:CI_PIPELINE_ID} - {env:CI_COMMIT_REF_NAME} ({env:CI_COMMIT_SHORT_SHA})" \
--attachments \
./junit-results/results.xml
- echo "✅ Test results uploaded to QA Sphere"
- echo "View at: ${QAS_URL}/project/BD/runs"
when: always
allow_failure: true
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
tags:
- docker
```
## Next Steps
Once you have the basic integration working:
1. **Add More Tests** - Expand your test coverage with proper markers
2. **Set Up Schedules** - Run tests nightly using GitLab's scheduled pipelines
3. **Create Dashboards** - Use QA Sphere reports to track quality trends
4. **Configure Notifications** - Get alerts for test failures
5. **Integrate with Jira** - Link test failures to bug tickets
## Additional Resources
* [QA Sphere CLI Documentation - Playwright Integration](/docs/cli-usage-playwright)
* [QA Sphere CLI Documentation - WebdriverIO Integration](/docs/cli-usage-webdriverio)
* [QA Sphere API Documentation](/docs/api/api_intro)
* [Authentication Guide](/docs/api/authentication)
* [GitLab CI/CD Documentation](https://docs.gitlab.com/ee/ci/)
* [Playwright Documentation](https://playwright.dev/)
## Getting Help
If you encounter issues:
1. Check the [Troubleshooting](#troubleshooting) section above
2. Review pipeline logs in GitLab
3. Test CLI locally with same configuration
4. Contact QA Sphere support: [sorted@qasphere.com](mailto:sorted@qasphere.com)
***
**Summary:** You now have everything you need to integrate QA Sphere with GitLab CI/CD. The QAS CLI tool automatically handles test result uploads, making test management seamless and automated. Every pipeline run will now update QA Sphere with the latest test results.
---
# CI/CD Examples
URL: /docs/integrations/ci-cd
Integrate QA Sphere with your continuous integration and deployment pipelines to automatically upload test results after every build.
Each guide provides step-by-step instructions for configuring the QA Sphere CLI tool with your CI/CD platform:
* **[GitHub Actions](https://qasphere.com/docs/integrations/ci-cd/github-actions)** - Automate test result uploads from GitHub Actions workflows
* **[GitLab CI/CD](https://qasphere.com/docs/integrations/ci-cd/gitlab)** - Integrate with GitLab pipelines
* **[Bitbucket Pipelines](https://qasphere.com/docs/integrations/ci-cd/bitbucket)** - Connect Bitbucket Pipelines to QA Sphere
## How It Works
All CI/CD integrations follow the same pattern:
1. Configure your test framework to generate **JUnit XML** reports
2. Add QA Sphere credentials as CI/CD secrets/variables
3. Install the QA Sphere CLI (`qas-cli`) in your pipeline
4. Run `qasphere junit-upload` to send results to QA Sphere
## Prerequisites
Before setting up any integration, ensure you have:
* Tests configured to generate JUnit XML format results
* A QA Sphere account with Test Runner role or higher
* Test cases in QA Sphere with markers (e.g., `BD-001`, `PRJ-123`)
* An API key from QA Sphere Settings
## Quick Reference
| Platform | Secrets Location | Documentation |
| ------------------- | ------------------------------------------ | ---------------------------------- |
| GitHub Actions | Settings → Secrets → Actions | [View Guide](https://qasphere.com/docs/integrations/ci-cd/github-actions) |
| GitLab CI/CD | Settings → CI/CD → Variables | [View Guide](https://qasphere.com/docs/integrations/ci-cd/gitlab) |
| Bitbucket Pipelines | Repository settings → Repository variables | [View Guide](https://qasphere.com/docs/integrations/ci-cd/bitbucket) |