CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/testrail-integration

Syncs test runs / results / cases between an automated test suite and TestRail (Gurock / Idera) - opens a Test Run for the build (`add_run`), batches per-case results back via `add_results_for_cases` (preferred over per-test `add_result_for_case` - N+1 API calls vs 1), maps the test framework's pass/fail/skip to TestRail status IDs, and attaches build URL + version + elapsed time. Use when the team's test management is standalone TestRail (not a Jira app) and automated suites must update it without a human copy-paste step; when the TCM is instead a Jira app use xray-integration (Xray) or zephyr-integration (Zephyr Scale), and for hosted cross-run flakiness analytics rather than TCM sync use currents-integration.

79

Quality

99%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

ci-and-fields.mdreferences/

TestRail per-result fields, CI wiring, and untested-case handling

Deep reference for the testrail-integration SKILL.md. Consult for the full per-result field list, the end-to-end GitHub Actions workflow, and how to surface tests that carry no TestRail case ID.

Per-result fields

Fields accepted on each entry in the add_results_for_cases results array (Step 4):

FieldUse
case_idRequired. The TestRail case ID.
status_idRequired. Per the status-ID convention in Step 4.
commentThe test framework's failure message + stack trace.
elapsedFormat: '1h 30m 45s' or '45s'. Optional.
versionBuild version / commit SHA. Searchable in the UI.
defectsComma-separated Jira / GitHub issue keys.
assignedto_idAuto-assign failures to a specific user.

Wire into a CI pipeline

- name: Run tests
  run: npm test -- --reporters=jest-junit
  env:
    JEST_JUNIT_OUTPUT_FILE: junit.xml

- name: Sync to TestRail
  if: always()
  env:
    TESTRAIL_HOST: ${{ secrets.TESTRAIL_HOST }}
    TESTRAIL_USER: ${{ secrets.TESTRAIL_USER }}
    TESTRAIL_API_KEY: ${{ secrets.TESTRAIL_API_KEY }}
    TESTRAIL_PROJECT_ID: '42'
    TESTRAIL_SUITE_ID: '7'
    BUILD_VERSION: ${{ github.sha }}
  run: python scripts/testrail_sync.py junit.xml

The sync script:

  1. Parses junit.xml (see junit-xml-analysis).
  2. Extracts case IDs from test names (Step 2).
  3. Opens a run named <branch> · <sha-short> (Step 3).
  4. Batches results (Step 4).
  5. Optionally closes the run (Step 5) - typically only on main.

Handling untested case IDs

Tests that have no TestRail case ID (case removed; new test; intentional sync-skip) need explicit handling:

unmapped = [t for t in tests if extract_case_id(t['name']) is None]
if unmapped:
    print(f"Warning: {len(unmapped)} tests have no TestRail case ID:")
    for t in unmapped:
        print(f"  - {t['name']}")

Don't silently drop unmapped tests - they're candidates for either new TestRail cases or naming-pattern fixes.

SKILL.md

tile.json