This guide shows how to integrate GitLab CI/CD with TestCollab using the TestCollab CLI (@testcollab/cli). After your tests run in a GitLab pipeline, the CLI automatically uploads results to TestCollab — creating a test plan, mapping results, and updating statuses.
How It Works
The TestCollab CLI follows a simple 3-step workflow inside your .gitlab-ci.yml:
Create a Test Plan —
tc createTestPlancreates a new test plan in TestCollab and writes the plan ID totmp/tc_test_planRun Tests — Your test framework runs and produces a result file (JUnit XML, Mochawesome JSON, etc.)
Upload Results —
tc reportparses the result file and updates test case statuses in TestCollab
Prerequisites
A TestCollab account with a project containing test cases
Your TestCollab Project ID, a Tag ID to filter test cases for CI, and the Assignee User ID
A GitLab repository with CI/CD enabled
Step 1: Configure GitLab CI/CD Variables
Go to your GitLab project → Settings → CI/CD → Variables and add the following variables (mark them as Masked where appropriate):
Variable | Description |
| Your TestCollab API token (mark as Masked) |
| Your TestCollab project ID |
| Tag ID used to filter test cases for CI |
| User ID to assign test executions to |
Example: Playwright (JUnit XML)
stages:
- test
- report
run-tests:
stage: test
image: mcr.microsoft.com/playwright:v1.52.0-noble
script:
- npm ci
- npx playwright install --with-deps
- npx playwright test --reporter=junit || true
artifacts:
when: always
paths:
- results.xml
expire_in: 1 week
upload-results:
stage: report
image: node:20
needs:
- job: run-tests
artifacts: true
script:
- npm install -g @testcollab/cli
- tc createTestPlan --project $TC_PROJECT_ID --ci-tag-id $TC_CI_TAG_ID --assignee-id $TC_ASSIGNEE_ID
- source tmp/tc_test_plan
- tc report --project $TC_PROJECT_ID --test-plan-id $TESTCOLLAB_TEST_PLAN_ID --format junit --result-file results.xml
when: always
Example: Cypress (Mochawesome JSON)
stages:
- test
- report
run-tests:
stage: test
image: cypress/browsers:node-20.18.3-chrome-134.0.6998.35-1-ff-137.0-edge-134.0.3124.39-1
script:
- npm ci
- npx cypress run --reporter mochawesome --reporter-options reportDir=mochawesome-report,overwrite=true,json=true || true
artifacts:
when: always
paths:
- mochawesome-report/
expire_in: 1 week
upload-results:
stage: report
image: node:20
needs:
- job: run-tests
artifacts: true
script:
- npm install -g @testcollab/cli
- tc createTestPlan --project $TC_PROJECT_ID --ci-tag-id $TC_CI_TAG_ID --assignee-id $TC_ASSIGNEE_ID
- source tmp/tc_test_plan
- tc report --project $TC_PROJECT_ID --test-plan-id $TESTCOLLAB_TEST_PLAN_ID --format mochawesome --result-file mochawesome-report/mochawesome.json
when: always
Example: pytest (JUnit XML)
stages:
- test
- report
run-tests:
stage: test
image: python:3.12
script:
- pip install pytest
- pytest --junitxml=results.xml || true
artifacts:
when: always
paths:
- results.xml
expire_in: 1 week
upload-results:
stage: report
image: node:20
needs:
- job: run-tests
artifacts: true
script:
- npm install -g @testcollab/cli
- tc createTestPlan --project $TC_PROJECT_ID --ci-tag-id $TC_CI_TAG_ID --assignee-id $TC_ASSIGNEE_ID
- source tmp/tc_test_plan
- tc report --project $TC_PROJECT_ID --test-plan-id $TESTCOLLAB_TEST_PLAN_ID --format junit --result-file results.xml
when: always
Example: Java / Maven (JUnit XML)
stages:
- test
- report
run-tests:
stage: test
image: maven:3.9-eclipse-temurin-17
script:
- mvn test || true
artifacts:
when: always
paths:
- target/surefire-reports/*.xml
expire_in: 1 week
upload-results:
stage: report
image: node:20
needs:
- job: run-tests
artifacts: true
script:
- npm install -g @testcollab/cli
- tc createTestPlan --project $TC_PROJECT_ID --ci-tag-id $TC_CI_TAG_ID --assignee-id $TC_ASSIGNEE_ID
- source tmp/tc_test_plan
- tc report --project $TC_PROJECT_ID --test-plan-id $TESTCOLLAB_TEST_PLAN_ID --format junit --result-file target/surefire-reports/TEST-*.xml
when: always
Key Concepts
|| true— Appended to the test command so the pipeline continues even if tests fail. Without this, GitLab would skip the upload stage on test failures.when: always— Ensures the upload-results job runs regardless of whether the test job passed or failed.artifacts— Test result files are passed between stages using GitLab artifacts. Thewhen: alwayson artifacts ensures they are saved even on failure.needs— The upload job explicitly depends on the test job to receive its artifacts.source tmp/tc_test_plan— Loads theTESTCOLLAB_TEST_PLAN_IDenvironment variable written bytc createTestPlan, making it available for thetc reportcommand.$CI_PIPELINE_IID— A GitLab predefined variable (project-level pipeline number) that can be used to give each test plan a unique name if needed.
Custom API URL
If your TestCollab instance uses a custom API URL, add the --api-url flag to both CLI commands:
tc createTestPlan --api-url https://your-api-url.example.com --project $TC_PROJECT_ID --ci-tag-id $TC_CI_TAG_ID --assignee-id $TC_ASSIGNEE_ID
tc report --api-url https://your-api-url.example.com --project $TC_PROJECT_ID --test-plan-id $TESTCOLLAB_TEST_PLAN_ID --format junit --result-file results.xml
Troubleshooting
Results not uploading — Check that your test result file path in
--result-filematches the actual output location. Useartifactswithwhen: alwaysto ensure files are available.Upload stage skipped — Make sure you have
|| trueon your test command orallow_failure: trueon the test job, andwhen: alwayson the upload job.Authentication errors — Verify your
TESTCOLLAB_TOKENvariable is set correctly in GitLab CI/CD settings. If using a custom API URL, ensure the--api-urlflag is included.Test cases not matched — Ensure your test names include TestCollab test case IDs in the expected format. See the main CLI documentation for mapping details.
For the full CLI reference and additional options, see Uploading Test Results Using TestCollab CLI.
For any queries or feedback, contact us at [email protected].
