On this page
This guide shows how to create a TestCollab plan in GitHub Actions, run automated tests, and upload their JUnit XML or Mochawesome JSON results with the current TestCollab CLI.
The core reporting workflow is createTestPlan → tests →
report. It does not require a build record or quality gate. See
Automated Testing in a CI/CD Pipeline with TestCollab
for the core path and optional extensions.
Prerequisites
A TestCollab API token from your profile settings
Your numeric TestCollab project ID
-
A tag applied to the cases that should be included in the CI plan, plus that tag's ID
The API token owner's user ID, used as the plan assignee
-
Test names whose generated result contains an explicit TestCollab ID such as
[TC-42] Login should succeed -
Node.js 22 and your test framework's dependencies, installed by the workflow examples below
Step 1: Add Repository Secrets
Open your GitHub repository, then go to Settings > Secrets and variables > Actions. Add these repository secrets:
Secret name |
Value |
|---|---|
|
|
Your TestCollab API token |
|
|
Your TestCollab project ID |
|
|
The tag ID used to select cases for CI |
|
|
The API token owner's user ID |
Step 2: Add a Workflow
Create .github/workflows/tests.yml and choose the example for your framework. Each
example is a complete workflow, not a fragment.
Playwright with JUnit XML
Playwright's JUnit reporter writes to standard output unless you give it an output file. This
workflow sets PLAYWRIGHT_JUNIT_OUTPUT_NAME, so tc report receives a real
results.xml file.
name: Playwright tests and TestCollab report
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
env:
TESTCOLLAB_TOKEN: ${{ secrets.TESTCOLLAB_TOKEN }}
TC_PROJECT_ID: ${{ secrets.TC_PROJECT_ID }}
TC_CI_TAG_ID: ${{ secrets.TC_CI_TAG_ID }}
TC_ASSIGNEE_ID: ${{ secrets.TC_ASSIGNEE_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install project dependencies
run: npm ci
- name: Install TestCollab CLI
run: npm install -g @testcollab/cli
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Create TestCollab test plan
run: |
tc createTestPlan \
--project "$TC_PROJECT_ID" \
--ci-tag-id "$TC_CI_TAG_ID" \
--assignee-id "$TC_ASSIGNEE_ID"
- name: Load TestCollab plan ID
run: cat tmp/tc_test_plan >> $GITHUB_ENV
- name: Run Playwright and write JUnit XML
env:
PLAYWRIGHT_JUNIT_OUTPUT_NAME: results.xml
run: npx playwright test --reporter=junit
- name: Upload results to TestCollab
if: always()
run: |
tc report \
--project "$TC_PROJECT_ID" \
--test-plan-id "$TESTCOLLAB_TEST_PLAN_ID" \
--format junit \
--result-file ./results.xml
Cypress with Mochawesome JSON
Cypress can write one Mochawesome JSON file per spec. This workflow installs
mochawesome-merge, merges every generated JSON file, and uploads the combined file
that the current CLI expects.
name: Cypress tests and TestCollab report
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
env:
TESTCOLLAB_TOKEN: ${{ secrets.TESTCOLLAB_TOKEN }}
TC_PROJECT_ID: ${{ secrets.TC_PROJECT_ID }}
TC_CI_TAG_ID: ${{ secrets.TC_CI_TAG_ID }}
TC_ASSIGNEE_ID: ${{ secrets.TC_ASSIGNEE_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install project dependencies
run: npm ci
- name: Install reporting tools and TestCollab CLI
run: |
npm install --no-save mochawesome mochawesome-merge
npm install -g @testcollab/cli
- name: Create TestCollab test plan
run: |
tc createTestPlan \
--project "$TC_PROJECT_ID" \
--ci-tag-id "$TC_CI_TAG_ID" \
--assignee-id "$TC_ASSIGNEE_ID"
- name: Load TestCollab plan ID
run: cat tmp/tc_test_plan >> $GITHUB_ENV
- name: Run Cypress and write Mochawesome JSON
run: |
npx cypress run \
--reporter mochawesome \
--reporter-options reportDir=results,overwrite=false,html=false,json=true
- name: Merge Mochawesome files
if: always()
run: npx mochawesome-merge "./results/*.json" --output ./results/mochawesome.json
- name: Upload results to TestCollab
if: always()
run: |
tc report \
--project "$TC_PROJECT_ID" \
--test-plan-id "$TESTCOLLAB_TEST_PLAN_ID" \
--format mochawesome \
--result-file ./results/mochawesome.json
pytest with JUnit XML
pytest has built-in JUnit XML output, so it does not need an additional reporter package.
name: pytest and TestCollab report
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
env:
TESTCOLLAB_TOKEN: ${{ secrets.TESTCOLLAB_TOKEN }}
TC_PROJECT_ID: ${{ secrets.TC_PROJECT_ID }}
TC_CI_TAG_ID: ${{ secrets.TC_CI_TAG_ID }}
TC_ASSIGNEE_ID: ${{ secrets.TC_ASSIGNEE_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Python dependencies
run: pip install -r requirements.txt
- name: Install TestCollab CLI
run: npm install -g @testcollab/cli
- name: Create TestCollab test plan
run: |
tc createTestPlan \
--project "$TC_PROJECT_ID" \
--ci-tag-id "$TC_CI_TAG_ID" \
--assignee-id "$TC_ASSIGNEE_ID"
- name: Load TestCollab plan ID
run: cat tmp/tc_test_plan >> $GITHUB_ENV
- name: Run pytest and write JUnit XML
run: pytest --junitxml=results.xml
- name: Upload results to TestCollab
if: always()
run: |
tc report \
--project "$TC_PROJECT_ID" \
--test-plan-id "$TESTCOLLAB_TEST_PLAN_ID" \
--format junit \
--result-file ./results.xml
How the Workflows Work
-
Create the plan -
tc createTestPlanadds the cases carrying your CI tag, assigns them, starts the first run, and writesTESTCOLLAB_TEST_PLAN_ID=<id>totmp/tc_test_plan. -
Load the plan ID - appending that file to
GITHUB_ENVmakesTESTCOLLAB_TEST_PLAN_IDavailable to later steps in the same job. -
Run the tests - the framework creates JUnit XML or Mochawesome JSON.
-
Upload the results -
tc reportparses the file and updates matching executions in the plan.
if: always() lets the upload step run after a test failure. GitHub Actions still
keeps the earlier test step's failed result, so uploading evidence does not turn a failing
workflow green.
Test Case ID Mapping
The generated result must contain the TestCollab case ID in its test name or
classname. The recommended form is:
[TC-42] Login should succeed
The CLI also recognizes TC-42, id-42, and testcase-42,
without case sensitivity. Explicit markers take priority, so technical text such as
UTF-8 or SHA-256 does not override [TC-42].
See JUnit XML Format Explained for result elements, attachments, and configuration IDs.
EU Region
For an EU-hosted TestCollab account, add this option to both tc createTestPlan and
tc report in the selected workflow:
--api-url https://api-eu.testcollab.io
Optional Enhancements: Build Traceability and Quality Gates
After the core reporting workflow works, you can optionally connect results to a version by
recording it with
tc createBuild
and passing its ID or version to tc createTestPlan --build.
Independently, you can stop a deployment when the reported plan does not meet your rules by adding
tc gate
after tc report.
Neither enhancement is required to create a plan or upload test results, and you can adopt either one without the other.
Troubleshooting
The result file is missing
-
For Playwright, keep
PLAYWRIGHT_JUNIT_OUTPUT_NAME=results.xmlor configure the JUnit reporter with an explicit output file. -
For Cypress, make sure the merge step runs and produces
./results/mochawesome.json. -
For pytest, confirm the command includes
--junitxml=results.xml.
Test cases are not matched
-
Confirm every generated test name contains an explicit marker such as
[TC-42]. -
Confirm the case carries the CI tag and was added to the new plan.
-
Use the API token owner's user ID as
TC_ASSIGNEE_ID.
Authentication or permission errors
-
Confirm
TESTCOLLAB_TOKENexists in repository secrets and is available to this workflow. Confirm the token owner and assignee can access the project.
-
For pull requests from forks, remember that GitHub does not pass repository secrets to an untrusted fork workflow.


