CI Results Integration
Push test results from your CI pipeline to TestIntel after each test run. Results appear in the Reporting tab with pass/fail trends, health score, and flaky test detection.
Quick Start
Add one curl command after your test step. TestIntel accepts JUnit XML (the universal format — almost every test framework can output it).
curl -X POST "http://your-testintel-server:8000/results/webhook?project=your-project" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/xml" \
--data-binary @results.xml
Parameters
| Parameter | Required | Description |
|---|---|---|
project | Recommended | Project name in TestIntel. Without this, results go to root scope ("No project"). |
source | Optional | Label for the pipeline run (e.g. Jenkins Build #42, GitHub Actions #15). Shown in the Test Runs table. |
app_version | Optional | Version or commit SHA of the application under test. Used for flaky detection correlation. |
environment | Optional | Environment name (e.g. ci, staging, production). Useful for filtering. |
Example with all parameters:
curl -X POST "http://your-server:8000/results/webhook?project=my-app&source=Jenkins+Build+%2342&app_version=v2.1.0&environment=staging" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/xml" \
--data-binary @results.xml
GitHub Actions
name: Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: pip install -e ".[test]"
- name: Run tests
run: pytest --junitxml=results.xml
- name: Push results to TestIntel
if: always()
run: |
curl -s -X POST "${{ secrets.TESTINTEL_URL }}/results/webhook?project=my-app&source=GitHub+Actions+%23${{ github.run_number }}&environment=ci" \
-H "x-api-key: ${{ secrets.TESTINTEL_API_KEY }}" \
-H "Content-Type: application/xml" \
--data-binary @results.xml || echo "TestIntel upload skipped"
Setup:
- Go to your repo → Settings → Secrets and variables → Actions
- Add
TESTINTEL_URL— your TestIntel server URL (e.g.http://52.1.2.3:8000orhttps://testintel.yourcompany.com). No trailing slash.
- Add
TESTINTEL_API_KEY— your TestIntel API key
Jenkins (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'pytest --junitxml=results.xml'
}
post {
always {
// Standard Jenkins JUnit reporting
junit 'results.xml'
// Push to TestIntel
sh '''
curl -s -X POST "${TESTINTEL_URL}/results/webhook?project=my-app&source=Jenkins+Build+%23${BUILD_NUMBER}&environment=ci" \
-H "x-api-key: ${TESTINTEL_API_KEY}" \
-H "Content-Type: application/xml" \
--data-binary @results.xml || echo "TestIntel upload skipped"
'''
}
}
}
}
}
Setup:
- Add
TESTINTEL_URLandTESTINTEL_API_KEYas Jenkins credentials (Secret text)
- Bind them as environment variables in your pipeline or use
withCredentials
GitLab CI
test:
stage: test
script:
- pip install -e ".[test]"
- pytest --junitxml=results.xml
after_script:
- |
curl -s -X POST "$TESTINTEL_URL/results/webhook?project=my-app&source=GitLab+Pipeline+%23$CI_PIPELINE_ID&environment=ci" \
-H "x-api-key: $TESTINTEL_API_KEY" \
-H "Content-Type: application/xml" \
--data-binary @results.xml || echo "TestIntel upload skipped"
artifacts:
reports:
junit: results.xml
Setup:
- Go to your project → Settings → CI/CD → Variables
- Add
TESTINTEL_URLandTESTINTEL_API_KEY(masked)
Generating JUnit XML
Most test frameworks support JUnit XML output:
| Framework | Command | |
|---|---|---|
| pytest | pytest --junitxml=results.xml | |
| Jest | jest --reporters=jest-junit (install jest-junit) | |
| Playwright | Add ['junit', { outputFile: 'results.xml' }] to reporter config | |
| Cypress | Use cypress-junit-reporter | |
| JUnit/TestNG | Built-in via Maven Surefire / Gradle | |
| NUnit | dotnet test --logger "junit;LogFilePath=results.xml" | |
| Go | `go test -v ./... 2>&1 \ | go-junit-report > results.xml` |
| behave | behave --junit --junit-directory=./results |
What Happens After Upload
- Results appear in Reporting — each upload creates a new entry in the Test Runs table
- Inventory updated — tests that match by name or ID get their
test_resultandlast_runupdated
- Health score recalculates — based on pass rate, run frequency, failure trends, and flaky rate
- Flaky detection — tests that flip between pass/fail across runs are flagged
Troubleshooting
{"detail":"Not Found"} error:
Your TESTINTEL_URL has a trailing slash. Remove it — the URL must not end with /.
- ✅
http://your-ec2:8000 - ✅
https://testintel.yourcompany.com - ❌
http://your-ec2:8000/ - ❌
https://testintel.yourcompany.com/
A trailing slash causes the path to become //results/webhook which doesn't match any route.
"Empty request body" error:
The results.xml file doesn't exist or is empty. Make sure your test step generates it before the upload step.
"Invalid API key" error:
Check that TESTINTEL_API_KEY matches a valid key on your TestIntel instance.
Results don't appear in the project:
Verify the ?project= parameter matches the exact project name in TestIntel (case-sensitive).
Connection refused:
Ensure your CI runner can reach the TestIntel server. For EC2 deployments, check the security group allows inbound traffic from your CI provider's IP range.
Upload succeeds but no tests matched:
This is normal for the first upload if your inventory is empty. Results are still stored for reporting. Once you add tests to the inventory (via Zephyr Pull, Xray Pull, or Staging promotion), future results will match by name.