On this page
Connect CircleCI to TestCollab with @testcollab/cli to create a test plan before a
job runs and upload its JUnit results afterward. CircleCI can still display the same XML in its
Tests tab, while TestCollab keeps the automated results with your manual testing, builds, and
releases.
The core workflow is createTestPlan → tests → report. It needs
neither a build record nor a quality gate. For the zero-setup option and all CLI commands, start
with
TestCollab CLI: Install and First Run.
Prerequisites
- A TestCollab project with the automated test cases you want to run.
- A CI tag applied to those cases. Note the project ID and tag ID from TestCollab.
- The user ID of the person or service account that will own the executions.
- A TestCollab API token for that same user. The user must have access to the project and permission to create and assign test plans.
-
A test reporter that writes JUnit XML. The complete example below uses Jest with
jest-junit.
Name each automated test with its TestCollab case ID, such as
[TC-42] customer can sign in. The ID lets the CLI update the right execution in the
new test plan.
Add environment variables in CircleCI
Open your CircleCI project, go to Project Settings > Environment Variables, and add these values:
| Variable | Value | Secret? |
|---|---|---|
TESTCOLLAB_TOKEN |
Your TestCollab API token | Yes |
TC_PROJECT_ID |
Your TestCollab project ID | No |
TC_CI_TAG_ID |
The tag ID used for CI cases | No |
TC_ASSIGNEE_ID |
The execution owner in TestCollab | No |
Do not place TESTCOLLAB_TOKEN directly in .circleci/config.yml. If you
still need a token, follow
Getting an API Token generated.
Complete .circleci/config.yml
This job creates a TestCollab test plan, runs Jest, stores the JUnit report in CircleCI, and
uploads the same report to TestCollab. Add jest-junit to your development
dependencies before using it.
npm install --save-dev jest-junit
version: 2.1
jobs:
test:
docker:
- image: cimg/node:22.16
steps:
- checkout
- restore_cache:
keys:
- npm-v1-{{ checksum "package-lock.json" }}
- run:
name: Install dependencies
command: npm ci
- save_cache:
key: npm-v1-{{ checksum "package-lock.json" }}
paths:
- ~/.npm
- run:
name: Create TestCollab test plan
command: |
npx @testcollab/cli createTestPlan \
--project "$TC_PROJECT_ID" \
--ci-tag-id "$TC_CI_TAG_ID" \
--assignee-id "$TC_ASSIGNEE_ID"
- run:
name: Run Jest and generate JUnit XML
command: |
mkdir -p test-results
JEST_JUNIT_OUTPUT_DIR=./test-results \
JEST_JUNIT_OUTPUT_NAME=results.xml \
npm test -- --ci --reporters=default --reporters=jest-junit
- store_test_results:
path: test-results
- run:
name: Upload results to TestCollab
when: always
command: |
source tmp/tc_test_plan
npx @testcollab/cli report \
--project "$TC_PROJECT_ID" \
--test-plan-id "$TESTCOLLAB_TEST_PLAN_ID" \
--format junit \
--result-file ./test-results/results.xml
workflows:
test-and-report:
jobs:
- test
The upload step uses when: always, so it runs after passing and failing test
commands. A failed test job still stays failed; the upload only records its result in TestCollab.
How the workflow works
-
createTestPlancreates a plan from the cases carrying your CI tag and writes its ID totmp/tc_test_plan. - Jest runs and writes
test-results/results.xml. -
store_test_resultslets CircleCI read that XML for its Tests tab and timing data. -
The final step sources
tmp/tc_test_planand sends the same results to the matching executions in TestCollab.
Keep both store_test_results and tc report. CircleCI gives developers
feedback inside the pipeline run. TestCollab provides the shared test-management record, including
manual and automated cases in the same plan.
Map CircleCI tests to TestCollab cases
Put an explicit marker in each test title. Matching is case-insensitive, and the CLI recognizes
[TC-42], TC-42, id-42, and testcase-42.
describe('Authentication', () => {
test('[TC-42] customer can sign in', async () => {
// Test steps and assertions
});
});
The number is the TestCollab test case ID, not the test plan ID. The case must be included in the plan created from your CI tag.
Optional build traceability and quality gates
tc createBuild recognizes CircleCI automatically. It reads the build number, commit
SHA, and CircleCI build URL from CIRCLE_BUILD_NUM, CIRCLE_SHA1, and
CIRCLE_BUILD_URL.
CircleCI exposes CIRCLE_REPOSITORY_URL as a Git remote, which may be SSH rather than
a browser URL. The CLI deliberately does not turn it into a repository or commit link. Pass
verified web URLs explicitly when you want those links on the TestCollab build:
npx @testcollab/cli createBuild \
--project "$TC_PROJECT_ID" \
--repo-url "$TC_REPOSITORY_WEB_URL" \
--commit-url "$TC_COMMIT_WEB_URL"
Add TC_REPOSITORY_WEB_URL and TC_COMMIT_WEB_URL as project environment
variables or construct them from a known GitHub, GitLab, or Bitbucket web URL. See
Creating Builds from Your CI/CD Pipeline
before linking the test plan to that build.
Independently, you can add
a quality gate
after tc report when a later deployment must meet defined result criteria. Neither
option is required for the copyable workflow above, and you can add either one without the other.
Use the EU region
EU accounts must add this option to every TestCollab CLI command in the workflow:
--api-url https://api-eu.testcollab.io
For example, the upload command ends with:
npx @testcollab/cli report \
--project "$TC_PROJECT_ID" \
--test-plan-id "$TESTCOLLAB_TEST_PLAN_ID" \
--format junit \
--result-file ./test-results/results.xml \
--api-url https://api-eu.testcollab.io
Troubleshooting
No API key provided
Confirm the variable is named TESTCOLLAB_TOKEN and is available to this job.
Environment variables from restricted contexts may not be exposed to untrusted forked builds.
The result file does not exist
Check that jest-junit is installed and that the test command writes to
./test-results/results.xml. The upload path is relative to the job's working
directory.
Tests run, but cases are not updated
Inspect the generated XML and confirm each <testcase name="..."> contains the
intended [TC-42] marker. Also confirm the CI tag selected that case when the plan was
created and the token belongs to the assigned execution owner.
The upload step did not run after a failure
when: always belongs on the CircleCI run step, at the same indentation
level as name and command. Keep test execution and result upload in
separate steps.


