TestRail CLI
A powerful Python-based CLI for complete TestRail REST API access with CSV-driven case management.
Features
- Complete API Coverage: Access all TestRail REST API endpoints through intuitive commands
- Multi-Profile Support: Manage multiple TestRail instances with named profiles
- CSV Import/Export: Bulk import test cases from CSV with field mapping
- Flexible Output: JSON, table, or filtered field output formats
- CI/CD Ready: Perfect for automation pipelines and scripting
- Type-Safe: Full type hints and mypy validation
- Well-Tested: Comprehensive test coverage with pytest
- Modern Tooling: Built with Poetry, Ruff, and pre-commit hooks
Installation
Using pip
pip install py-testrail-cli
Using pipx (recommended for CLI tools)
pipx install py-testrail-cli
Using Poetry
poetry add py-testrail-cli
The installed executable remains
testrail.
From source
git clone https://github.com/mokson/testrail-cli.git
cd testrail-cli
poetry install
Quick Start
Interactive Configuration
testrail config init
This will prompt you for your TestRail URL, email, and API key, then create ~/.testrail-cli.yaml.
Environment Variables
export TESTRAIL_URL=https://your-org.testrail.io
export TESTRAIL_EMAIL=your-email@example.com
export TESTRAIL_PASSWORD=your-api-key
testrail projects list
Configuration File
Create ~/.testrail-cli.yaml:
profiles:
default:
url: https://your-org.testrail.io
email: your-email@example.com
password: your-api-key
timeout: 30
verify: true
staging:
url: https://staging.testrail.io
email: staging@example.com
password: staging-api-key
Use profiles with --profile flag:
testrail --profile staging projects list
Configuration Precedence: CLI flags > Environment variables > Config file
See examples/example-config.yaml for all configuration options.
Common Use Cases
Managing Projects and Suites
# List all projects
testrail projects list
# Create a new project
testrail projects add --name "My New Project" --announcement "Welcome!"
# List suites for a project
testrail suites list --project-id 1
# List sections within a suite
testrail sections list --project-id 1 --suite-id 5
Working with Test Cases
# List all test cases
testrail cases list --project-id 1 --suite-id 5
# Filter by priority and creation date
testrail cases list --project-id 1 --priority-id 1,2 --created-after 2024-01-01
# Filter by specific case IDs
testrail cases list --project-id 1 --case-ids 123,124,125
# Add a new test case
testrail cases add \
--section-id 10 \
--title "Test user login with valid credentials" \
--priority-id 2 \
--estimate "5m" \
--refs "JIRA-123"
# Add a new test case using a JSON file
testrail cases add --json new_case.json
# Update existing test case
testrail cases update 123 --title "Updated test title" --priority-id 1
# Update using a JSON file (for complex fields)
testrail cases update 123 --json update.json
# Update via stdin
echo '{"custom_preconds": "New preconditions"}' | testrail cases update 123 --file -
# Delete test case (soft delete)
testrail cases delete 123 --soft 1 --yes
CSV Import: Bulk Test Case Creation
The CSV import feature is perfect for migrating test cases or bulk creation:
testrail cases import \
--project-id 1 \
--suite-id 5 \
--csv test-cases.csv \
--section-path "API/Authentication" \
--template-id 2 \
--steps-field custom_steps_separated \
--create-missing-sections \
--mapping field-mapping.yaml
Example CSV (one row per step, case_id required) (test-cases.csv):
case_id,title,section,priority_id,type_id,template_id,estimate,refs,step,expected,additional_info,mission,goals,preconds
,Checkout happy path,Checkout/Payments,2,1,3m,REQ-400,Open checkout,Form renders,,,
,Checkout happy path,Checkout/Payments,2,1,3m,REQ-400,Enter valid card,Payment succeeds,,,
,Exploratory Session,Exploratory,2,1,30m,REQ-600,,,,,Test App,Find Bugs,
case_idcolumn is mandatory; leave it blank to create, set it to update/overwrite (including steps).- Specify the TestRail template via
--template-id(overrides any CSV value). - Each step is a separate CSV row repeating the case fields; the importer groups rows by
case_id(ortitle+sectionwhencase_idis empty). --steps-fieldcontrols which TestRail field receives the steps (custom_steps_separatedby default, orcustom_steps/custom_gherkinfor text/BDD templates).- Supported Template Fields: The importer automatically maps standard CSV columns to TestRail custom fields:
mission->custom_mission(Exploratory templates)goals->custom_goals(Exploratory templates)preconds/preconditions->custom_preconds(Steps templates)
Export to CSV (same format as import):
testrail cases export \
--project-id 1 \
--suite-id 5 \
--csv exported-cases.csv \
--priority-id 1,2
You can export by filters (suite/section/priority/type) or explicit --case-ids, edit the CSV, and re-import with cases import.
See examples/example-cases.csv and examples/example-mapping.yaml for the reference format.
Test Runs and Results
# Create a new test run
testrail runs add \
--project-id 1 \
--suite-id 5 \
--name "Sprint 10 Regression" \
--include-all true \
--assignedto-id 5
# Add a single test result
testrail results add \
--test-id 1001 \
--status-id 1 \
--comment "Test passed successfully" \
--elapsed "5m"
# Bulk add results from JSON file
testrail results add-bulk --run-id 50 --results-file results.json
# Close a test run
testrail runs close 50
Bulk Results Format (results.json):
[
{
"test_id": 1001,
"status_id": 1,
"comment": "Test passed",
"elapsed": "2m"
},
{
"test_id": 1002,
"status_id": 5,
"comment": "Test failed: timeout",
"defects": "BUG-456",
"elapsed": "5m"
}
]
Test Plans and Milestones
# List milestones
testrail milestones list --project-id 1
# Create a milestone
testrail milestones add \
--project-id 1 \
--name "Release 2.0" \
--description "Q4 2024 Release" \
--due-on 2024-12-31
# List test plans
testrail plans list --project-id 1 --is-completed 0
# Close a test plan
testrail plans close 25
Output Formats and Filtering
# JSON output (default)
testrail projects list --output json
# Table output
testrail projects list --output table
# Table with specific fields only
testrail projects list --output table --fields id,name,is_completed
# Filter specific fields in JSON
testrail cases list --project-id 1 --suite-id 5 --fields id,title,priority_id
Raw API Access
For endpoints not yet covered by specific commands, use the raw command:
# GET request
testrail raw --endpoint get_projects --method GET
# POST with inline data
testrail raw \
--endpoint add_case/123 \
--method POST \
--data title="New test case" \
--data priority_id=2
# POST with JSON file
testrail raw \
--endpoint add_run/1 \
--method POST \
--payload-file run.json
CI/CD Integration
GitHub Actions Example
name: TestRail Integration
on:
workflow_run:
workflows: ["Tests"]
types: [completed]
jobs:
upload-results:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install TestRail CLI
run: pipx install testrail-cli
- name: Upload test results
env:
TESTRAIL_URL: ${{ secrets.TESTRAIL_URL }}
TESTRAIL_EMAIL: ${{ secrets.TESTRAIL_EMAIL }}
TESTRAIL_PASSWORD: ${{ secrets.TESTRAIL_API_KEY }}
run: |
testrail results add-bulk --run-id ${{ secrets.RUN_ID }} --results-file results.json
testrail runs close ${{ secrets.RUN_ID }}
Jenkins Pipeline Example
pipeline {
agent any
stages {
stage('Upload Results') {
steps {
withCredentials([
string(credentialsId: 'testrail-url', variable: 'TESTRAIL_URL'),
string(credentialsId: 'testrail-email', variable: 'TESTRAIL_EMAIL'),
string(credentialsId: 'testrail-key', variable: 'TESTRAIL_PASSWORD')
]) {
sh '''
testrail results add-bulk --run-id ${RUN_ID} --results-file results.json
[ $? -eq 0 ] && testrail runs close ${RUN_ID}
'''
}
}
}
}
}
Shell Script Example
#!/bin/bash
set -e
RUN_ID=$1
RESULTS_FILE="test-results.json"
# Upload results to TestRail
echo "Uploading test results to TestRail run ${RUN_ID}..."
testrail results add-bulk --run-id "${RUN_ID}" --results-file "${RESULTS_FILE}"
# Close the run if upload succeeded
if [ $? -eq 0 ]; then
echo "Closing test run ${RUN_ID}..."
testrail runs close "${RUN_ID}"
echo "Test run closed successfully"
else
echo "Failed to upload results"
exit 1
fi
Available Commands
Core Resources
projects- Manage projectssuites- Manage test suitessections- Manage test sectionscases- Manage test cases (includes CSV import)runs- Manage test runsplans- Manage test planstests- View individual testsresults- Add and manage test resultsmilestones- Manage milestonesattachments- Manage attachments
Administrative
users- List usersstatuses- List test statusespriorities- List prioritiescase-types- List case typescase-fields- List custom case fieldsresult-fields- List custom result fields
Utilities
config- Initialize and manage configurationraw- Direct API endpoint access
Use testrail <command> --help for detailed options on any command.
Getting Your TestRail API Key
- Log in to your TestRail instance
- Click on your profile icon (top right)
- Select "My Settings"
- Go to the "API Keys" section
- Click "Add Key"
- Copy the generated API key (treat it like a password)
Documentation
- Installation Guide
- Configuration Guide
- Command Reference
- CSV Import Guide
- Development Guide
- Contributing Guidelines
Development
Setup
# Clone the repository
git clone https://github.com/mokson/testrail-cli.git
cd testrail-cli
# Install dependencies
poetry install
# Set up pre-commit hooks
make pre-commit
Running Tests
# Run all tests
make test
# Run with coverage
poetry run pytest --cov
# Run specific test file
poetry run pytest tests/unit/test_config.py
Code Quality
# Format code
make format
# Run linter
make lint
# Type check
make type-check
# Run all checks
make lint && make type-check && make test
See CONTRIBUTING.md for detailed development guidelines.
Contributing
We welcome contributions! Please see our Contributing Guidelines and Code of Conduct.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: docs/
Changelog
See CHANGELOG.md for a list of changes in each release.
Acknowledgments
- Built with Typer for CLI framework
- Uses Rich for beautiful terminal output
- API wrapper provided by testrail-api
Metadata
Release files for py-testrail-cli 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| py_testrail_cli-0.2.1.tar.gz | 35.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| py_testrail_cli-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 79.2 kB
Release files / py_testrail_cli-0.2.1.tar.gz
| Download URL | py_testrail_cli-0.2.1.tar.gz |
|---|---|
| Size | 35.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b02716746ece26153aa70340c671fa03a778cfa0ef635785e3ff4fe051822f8b
|
|
BLAKE2b-256 checksum How to use checksums |
2a17cb6a99d3e9e6c4ce16c02ade1af943ecbe63b85a25b4833a40df39605618
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.13.9 Darwin/24.6.0
|
Release files / py_testrail_cli-0.2.1-py3-none-any.whl
| Download URL | py_testrail_cli-0.2.1-py3-none-any.whl |
|---|---|
| Size | 43.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3aa313ce3b41a7dbd84965aa84a1a9f570788e692a5c5430b03d30ba0ab25d95
|
|
BLAKE2b-256 checksum How to use checksums |
8cefc155b0442af72d5ed6fca1c4bc45cb900f96d007a29955eccb80d4d5bc84
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.13.9 Darwin/24.6.0
|