Getting automated test results into Jira

Your runner already writes JUnit XML. One curl line puts those results into a Jira test cycle — pass, fail, duration and the failure message — with no plugin inside your pipeline.

The ideaPlaywrightCypress pytestJUnit / TestNGJest & Vitest Robot, NewmanCI systemsGotchas

The idea

JUnit XML is the one format nearly every runner can emit. CaseRun gives your Jira project an ingest URL; your pipeline posts the XML file to it after the tests run. Results appear in a test cycle, and tests that don't exist yet are created from the XML, so you don't have to pre-register anything.

curl -X POST "$CASERUN_INGEST_URL&cycle=Nightly&env=staging&version=$BUILD_NUMBER" \
     -H "Content-Type: application/xml" \
     --data-binary @results.xml
ParameterWhat it does
cycle (required)Name of the test cycle. If it doesn't exist, it's created.
envFree text — staging, prod, chrome. Shown in the ingest log.
versionBuild or release identifier.

The URL itself (including the project and a secret token) is shown on the CI tab inside the app. Keep it in your CI secret store; you can rotate it from that same tab.

Playwright

Add the JUnit reporter alongside your usual one:

// playwright.config.ts
export default defineConfig({
  reporter: [['list'], ['junit', { outputFile: 'results.xml' }]],
});

Or without touching the config: npx playwright test --reporter=junit (writes to stdout — redirect it with PLAYWRIGHT_JUNIT_OUTPUT_NAME=results.xml).

Cypress

npm i -D mocha-junit-reporter

// cypress.config.js
module.exports = defineConfig({
  reporter: 'mocha-junit-reporter',
  reporterOptions: { mochaFile: 'results/[hash].xml', toConsole: true },
});

Cypress writes one file per spec. Post them in a loop, or merge them first — CaseRun accepts either, and posting several files into the same cycle just adds to it.

pytest

pytest --junitxml=results.xml

Class names come through as the test's grouping, so tests/test_login.py::test_valid stays readable in the cycle.

JUnit 5 / TestNG (Maven, Gradle)

Maven Surefire already writes JUnit XML — no configuration needed:

mvn test
# XML lands in target/surefire-reports/*.xml
curl -X POST "$CASERUN_INGEST_URL&cycle=CI" -H "Content-Type: application/xml" \
     --data-binary @target/surefire-reports/TEST-*.xml

Gradle: build/test-results/test/*.xml. TestNG emits its own format as well, but the junitreports folder holds the JUnit-shaped files — use those.

Jest and Vitest

npm i -D jest-junit
npx jest --reporters=default --reporters=jest-junit   # writes junit.xml

npx vitest run --reporter=junit --outputFile=results.xml

Robot Framework and Newman (Postman)

robot --xunit results.xml tests/

newman run collection.json -r junit --reporter-junit-export results.xml

Wiring it into your CI

GitHub Actions

- name: Run tests
  run: npx playwright test
  continue-on-error: true          # still report failures

- name: Send results to Jira
  if: always()
  run: |
    curl -X POST "$CASERUN_INGEST_URL&cycle=main&env=ci&version=${{ github.run_number }}" \
      -H "Content-Type: application/xml" --data-binary @results.xml
  env:
    CASERUN_INGEST_URL: ${{ secrets.CASERUN_INGEST_URL }}

if: always() matters — otherwise a failing suite skips the very step that reports the failures.

GitLab CI

test:
  script:
    - pytest --junitxml=results.xml || true
    - curl -X POST "$CASERUN_INGEST_URL&cycle=$CI_COMMIT_REF_NAME&env=ci&version=$CI_PIPELINE_IID"
           -H "Content-Type: application/xml" --data-binary @results.xml
  artifacts:
    reports: { junit: results.xml }

Jenkins (declarative)

post {
  always {
    sh '''curl -X POST "$CASERUN_INGEST_URL&cycle=nightly&env=ci&version=$BUILD_NUMBER" \
            -H "Content-Type: application/xml" --data-binary @results.xml'''
  }
}

Bitbucket Pipelines

- step:
    script:
      - pytest --junitxml=results.xml || true
      - curl -X POST "$CASERUN_INGEST_URL&cycle=main&env=ci&version=$BITBUCKET_BUILD_NUMBER"
             -H "Content-Type: application/xml" --data-binary @results.xml

Gotchas worth knowing

What it looks like afterwards

Failed tests carry the failure message from the XML, so the report can answer "what actually broke" without opening the CI logs. The tests that fail most often are ranked on the Reports tab with their last failure message.

Runner not listed here? If it can write JUnit XML, it works. Send the file to support@caserun.dev and we'll tell you what it will produce — or fix the parser if it trips on something.