Nexus · test management for Jira
Menu
Get Nexus

Connect your automation tools to Nexus

Keep running tests with the tools you already use. Send their results to Nexus to record executions against your Jira Test Cases. Your computer or CI runner executes the tests; Nexus receives the report and matches each result using its Automation Key.

Start with one existing test. Configure Nexus once, follow the section for your tool, then check that its result appears in Jira. When that works, use the CI setup guide to automate delivery after every pipeline run.

For the complete cycle workflow, see running test automation from Jira. For planning manual and automated evidence together, see Jira test management with Nexus.

Choose a focused walkthrough for Playwright results in Jira, GitHub Actions testing or GitLab pipeline results. The configuration reference below provides the reporter settings and pipeline examples.

1. Prepare Nexus

  1. Open your Jira project's Project settings → Nexus → CI. Ask your project administrator for access if needed.
  2. Create an API key and tick Send results (the options are Send results, CI API and Runner). Give it a recognisable label, such as Web tests — staging. Copy it when shown; the full key is only displayed once.
  3. Copy the results URL from the same page. Use this complete address, not your Jira project URL or the separate CI API URL.
  4. Open an existing Test Case, set its Automation Key to a unique value such as NEX-12, and make sure it is Ready. The examples below use NEX-12; replace it with your actual Automation Key. Setting a test's name alone does not create its matching Test Case.
  5. Note your Jira project key, such as NEX. Optionally note the Test Set (cycle) key you want results recorded against.

2. Make the connection values available

All methods below read these environment variables. Keep the API key outside source files and test configuration.

Variable Value
NEXUS_URL The complete results URL copied from Nexus
NEXUS_API_KEY Your Nexus ingest key, not an Atlassian account token
NEXUS_PROJECT Your Jira project key, for example NEX
NEXUS_ENVIRONMENT An environment label, for example staging
NEXUS_TEST_SET Optional existing Test Set/cycle key

For a local check, set the values in the terminal that will run your tests. These examples prompt for credentials rather than placing them in command history.

Bash:

read -r -s -p 'Nexus results URL: ' NEXUS_URL
printf '\n'
read -r -s -p 'Nexus ingest key: ' NEXUS_API_KEY
printf '\n'
export NEXUS_URL NEXUS_API_KEY
export NEXUS_PROJECT='NEX'
export NEXUS_ENVIRONMENT='staging'

PowerShell 7:

$env:NEXUS_URL = Read-Host 'Nexus results URL' -MaskInput
$env:NEXUS_API_KEY = Read-Host 'Nexus ingest key' -MaskInput
$env:NEXUS_PROJECT = 'NEX'
$env:NEXUS_ENVIRONMENT = 'staging'

Replace NEX with your project key. Close this terminal after your check. In CI, store the URL and key in the provider's secret store and expose them to the test or upload step; the CI guide explains each provider.

3. Choose one delivery method

Your test tool Recommended route Who sends the results?
Playwright Nexus Playwright reporter The reporter at the end of the run
Selenium with pytest Nexus pytest plugin The plugin at the end of the session
Cypress JUnit XML + upload CLI A separate upload step
Cucumber Cucumber JSON + upload CLI A separate upload step
JUnit / Maven Surefire XML + upload CLI A separate upload step
Mocha Mocha JSON + upload CLI A separate upload step

Send each report once. If you use the Playwright reporter or pytest plugin, do not also upload that run's report from your pipeline. A second submission can create duplicate executions.

For the four file-upload routes, run the upload CLI straight from npm with npx @resyncnz/nexus-upload (version 0.3.8), or download the standalone upload CLI, save it as nexus-upload.mjs in the root of your test project and run it with Node.js 22. The downloaded file needs no package installation. This is the same file used in the CI guide. Keep the API key out of this file. Checksums are available for download verification.

Open the instructions for your framework below. These steps extend an existing working test suite; keep its browser, test dependencies and application setup.

Playwright

Install the Nexus reporter in your existing Playwright project:

npm install --save-dev @resyncnz/nexus-playwright-reporter

Or install the downloaded package (version 0.2.6):

npm install --save-dev https://nexus.resync.nz/downloads/nexus-playwright-reporter-0.2.6.tgz

Add this reporter setting to your existing defineConfig in playwright.config.ts, retaining your other settings:

reporter: [
  ['list'],
  ['@resyncnz/nexus-playwright-reporter', {
    failOnUploadError: true,
  }],
],

Rename one existing test to begin with its Automation Key: NEX-12: valid user signs in. Put the key on the individual test title, not just the enclosing describe.

npx playwright test --grep "NEX-12:"

The reporter reads your environment variables and sends the results automatically. failOnUploadError: true makes a failed upload visible as a failed run; without it, upload errors only produce warnings. See Playwright's reporter documentation for combining reporters.

Selenium with pytest

Selenium drives the browser; pytest supplies the results. In the environment where your existing pytest suite runs, install the Nexus plugin:

pip install pytest-nexus

Or install the downloaded wheel (version 0.2.5):

pip install https://nexus.resync.nz/downloads/pytest_nexus-0.2.5-py3-none-any.whl

Rename an existing test function to include test_NEX_12_valid_user_signs_in. Nexus recognises the code-safe NEX_12 as Automation Key NEX-12.

pytest -k NEX_12 --nexus-fail-on-upload-error

The plugin loads automatically, creates a temporary JUnit report and sends it. If you already use --junitxml, it sends that file instead. No separate upload is needed. For Selenium suites using another test runner, generate a supported report and use the CLI route.

Cypress

Start an existing test's title with NEX-12:. Use Cypress's built-in JUnit reporter; [hash] keeps different spec files from overwriting each other's reports.

npx cypress run --reporter junit --reporter-options "mochaFile=results/cypress-[hash].xml,toConsole=true"

Upload each XML file generated by this run separately. The CLI takes one filename, not a wildcard. For example, replacing the filename with an actual generated file:

node nexus-upload.mjs results/cypress-REPORT_HASH.xml --format junit-xml

Use a clean results directory for each run so stale files are not uploaded again. See Cypress reporting.

Cucumber

Start an existing scenario's name with NEX-12: or tag that scenario @NEX-12. For an existing Cucumber.js project, generate its legacy JSON report:

npx cucumber-js --format "json:results.json"
node nexus-upload.mjs results.json --format cucumber-json

Choose JSON, not the message formatter: newline-delimited Cucumber Messages are a different format. The JSON report is an array of features. Other Cucumber implementations can use the same upload command once configured to produce that report. See Cucumber.js formatters.

JUnit with Maven

In your existing JUnit suite, include NEX_12 in a test method name, for example NEX_12_validUserSignsIn. Nexus normalises this to NEX-12.

mvn test

Maven Surefire writes XML reports under target/surefire-reports/. Upload each newly generated TEST-*.xml file separately, using its actual filename:

node nexus-upload.mjs target/surefire-reports/TEST-com.example.LoginTest.xml --format junit-xml

Use XML reports, not the .txt summaries or HTML pages. Check the XML test name includes your key if your JUnit configuration changes display names.

Mocha

Start an existing it title with NEX-12:. Generate a report directly to a file, then upload it:

npx mocha --reporter json --reporter-option output=results.json
node nexus-upload.mjs results.json --format mocha-json

Mocha's JSON reporter writes the report even when tests fail. Use json, not json-stream.

4. Verify the first result

Run the test command and upload command as separate steps. If a test fails, still send the report it produced. In CI, configure the upload to run after failed tests without hiding the original test failure; see the provider examples.

  1. Look for HTTP 202 in the sender's output. This means accepted for background processing, not that every result has been recorded.
  2. Return to Project settings → Nexus → CI and inspect the delivery log. Confirm the result is matched to the expected Test Case.
  3. Open that Test Case's execution and check its status and environment. If you supplied NEXUS_TEST_SET, also check the intended cycle.

Optional: start the pipeline from a cycle ("Run in CI")

If your pipeline runs on GitHub Actions, GitLab.com, Azure DevOps Pipelines or Bitbucket Pipelines, a project admin can connect it in Project settings → Nexus → CI → step 6 "Run a cycle from Nexus". People with Create Issues then get Run in CI on the cycle page. Self-hosted Jenkins or GitLab use the Nexus runner instead (Project settings → Automation).

  • Token. Each connection holds that service's own token: a GitHub token with Actions read and write, a GitLab pipeline trigger token, an Azure DevOps PAT with Build read and execute, or a Bitbucket repository access token with Pipelines read and write. Nexus keeps it in Forge secret storage, never shows it again and never logs it. Use Replace token to change it. Removing the connection deletes the stored token.
  • What is sent. Only the values the admin ticks: nexus_project, nexus_cycle, nexus_cycle_label, nexus_environment, nexus_build and nexus_results_url (the results URL with project and testSet). Nexus never sends your Nexus API key: your pipeline keeps its own key as a CI secret and posts results to the results URL, as in section 3.
  • GitHub: the workflow needs a workflow_dispatch trigger declaring those names under inputs. GitHub does not return a run id for this request, so open the Actions tab. Azure DevOps: the values are sent as run-time variables, so each must be settable at queue time. Bitbucket: name a custom pipeline in bitbucket-pipelines.yml; the values arrive as variables. GitLab: the values arrive as pipeline variables.

Setting up your service

  • GitLab: in your GitLab project, set Settings > CI/CD > Variables > Minimum role to use pipeline variables to Developer or higher, or GitLab refuses the values Nexus sends. GitLab shows the values (and the request) on the pipeline's page, so treat that page as sensitive.
  • Azure DevOps: define nexus_project, nexus_cycle, nexus_environment and nexus_build (and any other value you tick) as pipeline variables with "Let users override this value when running this pipeline" switched on. Azure refuses values it does not know.
  • GitHub: declare each value you tick as a workflow_dispatch input with the same name (nexus_project, nexus_cycle, …). GitHub refuses inputs the workflow does not declare.
  • Bitbucket: Nexus starts a custom pipeline: add it under pipelines: custom: in bitbucket-pipelines.yml and enter its name in the connection.
  • All: use the values in your pipeline, for example nexus-upload … --test-set $nexus_cycle --environment $nexus_environment, so the results land in the cycle you ran.
  • Closing the dialog. After a successful request the dialog closes and the cycle page shows "Requested in …". To see the recent CI runs of the cycle, open More Actions → "Run in CI…" again.
  • Limits. One request per cycle per pipeline every 60 seconds, 30 per project per hour. Nexus tries once and never retries. Every request is in the Audit Log.

Example pipelines

Run in CI has been verified live with GitHub Actions, GitLab.com, Azure DevOps Pipelines and Bitbucket Pipelines on the development build. These examples show how to connect the pipeline inputs to result uploads. Keep your own build and test steps. NEXUS_URL and NEXUS_API_KEY are secrets you define in the CI service (see section 2); never write their values into the file. nexus-upload.mjs is the upload tool from the Nexus downloads page.

Bitbucket Pipelines — add a custom pipeline and enter its name (nexus) on the connection:

pipelines:
  custom:
    # Started by Nexus "Run this cycle in CI" (connection pipeline name: nexus). Nexus passes
    # nexus_project, nexus_cycle, nexus_environment and nexus_build; results go into that cycle.
    nexus:
      - variables:
          - name: nexus_project
            default: NEX
          - name: nexus_cycle
          - name: nexus_environment
            default: ci-bitbucket
          - name: nexus_build
      - step:
          name: Test and send results to the Nexus cycle
          script:
            - npm test
          after-script:
            - node tools/nexus-upload.mjs results.xml --project "${nexus_project:-NEX}" --component bitbucket-ci --environment "${nexus_environment:-ci-bitbucket}" ${nexus_cycle:+--test-set "$nexus_cycle"} ${nexus_build:+--build "$nexus_build"}

GitLab.com — also set Settings > CI/CD > Variables > Minimum role to use pipeline variables to Developer or higher:

# Runs the tests, then sends the JUnit results to Nexus even when a test fails.
# NEXUS_URL and NEXUS_API_KEY are masked CI/CD variables (Settings > CI/CD > Variables).
# When Nexus "Run this cycle in CI" starts the pipeline it passes nexus_project, nexus_cycle,
# nexus_environment and nexus_build, and the results go into that cycle; a normal push uses
# the defaults below. (Project setting: Minimum role to use pipeline variables = Developer.)
test:
  image: node:22
  script:
    - npm test || echo "tests failed" > .tests-failed
    - node tools/nexus-upload.mjs results.xml --project "${nexus_project:-NEX}" --component gitlab-ci --environment "${nexus_environment:-ci-gitlab}" ${nexus_cycle:+--test-set "$nexus_cycle"} ${nexus_build:+--build "$nexus_build"}
    - test ! -f .tests-failed
  artifacts:
    when: always
    reports:
      junit: results.xml

Azure DevOps Pipelines — define nexus_project, nexus_cycle, nexus_environment and nexus_build as pipeline variables with Let users override this value when running this pipeline switched on, then map them into the upload step:

  # Nexus "Run this cycle in CI" passes nexus_project, nexus_cycle, nexus_environment and
  # nexus_build as pipeline variables (defined on the pipeline as overridable at queue time);
  # a normal push leaves them empty and the defaults apply.
  - script: node nexus-upload.mjs results.xml --project "${RUN_PROJECT:-NEX}" --format junit-xml --environment "${RUN_ENVIRONMENT:-ci-azure}" --component azure-pipelines ${RUN_CYCLE:+--test-set "$RUN_CYCLE"} ${RUN_BUILD:+--build "$RUN_BUILD"}
    displayName: Send results to Nexus
    condition: always()
    env:
      NEXUS_URL: $(NEXUS_URL)
      NEXUS_API_KEY: $(NEXUS_API_KEY)
      RUN_PROJECT: $(nexus_project)
      RUN_CYCLE: $(nexus_cycle)
      RUN_ENVIRONMENT: $(nexus_environment)
      RUN_BUILD: $(nexus_build)

GitHub Actions — a workflow that declares the values as workflow_dispatch inputs (enter its file name on the connection):

name: Nexus Run in CI

# Started by Nexus "Run this cycle in CI" (connection workflow: nexus-run-in-ci.yml).
# Nexus passes the inputs below; the results are recorded into that cycle.
on:
  workflow_dispatch:
    inputs:
      nexus_project:
        description: Jira project key (from Nexus)
        required: false
        default: NEX
      nexus_cycle:
        description: Cycle (Test Set key) to record the results into (from Nexus)
        required: false
      nexus_cycle_label:
        description: Cycle label (from Nexus, informational)
        required: false
      nexus_environment:
        description: Environment label (from Nexus)
        required: false
        default: ci-github
      nexus_build:
        description: Build (from Nexus)
        required: false
      nexus_results_url:
        description: Nexus results URL (not used; this repo uses its own secret)
        required: false

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - name: Run tests
        run: npm test
      - name: Send results to the Nexus cycle
        if: ${{ always() }}
        uses: ./.github/actions/nexus-upload
        with:
          url: ${{ secrets.NEXUS_URL }}
          api-key: ${{ secrets.NEXUS_API_KEY }}
          project: ${{ inputs.nexus_project || 'NEX' }}
          file: results.xml
          format: junit-xml
          environment: ${{ inputs.nexus_environment || 'ci-github' }}
          test-set: ${{ inputs.nexus_cycle }}

Large suites (more than 500 tests)

Nexus accepts at most 500 results and 5 MB in one request. You do not have to split anything yourself with the Nexus tools: the Playwright reporter, the pytest plugin, the Cypress plugin, nexus-upload, the Azure DevOps task and the GitHub Action cut a bigger report into parts of at most 500 results, keep each part in the report's own format (each test stays inside its own suite), and send the parts one after another to the same project, cycle, build and environment. The log shows each part ("part 3 of 10: 500 results accepted") and one summary at the end. If one part fails, the others are still sent and the step fails at the end; a wrong key, a bad request or an inactive licence stops at once. Run the whole job again and the same parts are sent again, and Nexus ignores what it already recorded.

Supported for splitting: JUnit, xUnit.net, NUnit, TestNG, Robot, Playwright JSON, Cucumber JSON, Mocha, mochawesome and Nexus JSON. A Postman/Newman report over 500 requests is refused with a clear message: split the Newman run (for example per folder) or convert to JUnit. Per-result detail (matched, unmatched, skipped) is in the delivery log under Project Settings > CI, one entry per part.

The tools also wait and resend when Nexus asks them to slow down (a rate limit), up to a cap.

If something does not appear

What you see What to check
Missing configuration Variables must be set in the same terminal or CI step as the sender.
HTTP 401 Check the ingest key, its scope and project; replace revoked keys.
Unmatched result Check the Automation Key field and the name inside the actual report.
Skipped result Read the delivery-log reason and check the Test Case's state.
Missing report Confirm the test command ran, the output path and the working directory.
Invalid format / HTTP 400 Send the actual XML/JSON report, using the matching format above.
Report too large / HTTP 413 Nexus takes at most 500 results and 5 MB per request. The Nexus tools split a larger report for you (see "Large suites"). If you send with your own curl, split the report yourself; a 413 can also mean more than 120 requests in a minute.
Duplicate executions Keep only one sender per run; exclude old report files.

Once one test matches correctly, apply the naming convention to the rest of your suite and follow Connect your CI pipeline for repeatable delivery.