GitLab CI/CD Integration with QA Sphere
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

- Your pipeline runs automated tests
- Tests generate JUnit XML results file
- QAS CLI tool reads the XML file
- CLI matches tests to QA Sphere cases using markers
- Results are uploaded and appear in QA Sphere
Setup Steps
Step 1: Create QA Sphere API Key
- Log into your QA Sphere account
- Click the gear icon ⚙️ in the top right → Settings
- Navigate to API Keys
- Click Create API Key
- 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:
- Go to your GitLab project
- Navigate to Settings → CI/CD → Variables
- 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 |
- 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:
test('BD-001: User can login with valid credentials', async ({ page }) => {
await page.goto('https://example.com/login');
await page.fill('#username', '[email protected]');
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:
describe('Login Flow', () => {
it('BD-001: should login successfully with valid credentials', () => {
cy.visit('/login');
cy.get('#username').type('[email protected]');
cy.get('#password').type('password123');
cy.get('#login-button').click();
cy.url().should('include', '/dashboard');
});
});
Jest Example:
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
// 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' } },
],
});