Import test cases into TestRail
This skill imports the reviewed CSV for a feature into TestRail in a single action. There are no modes — running it creates a section named after themfeature and adds the whole structure and every test case inside that section.
The importer never modifies the reviewed CSV, manifest, or review report.
Invocation
/testrail-importer <feature_name>
Example:
/testrail-importer google-lens
The importer is a thin wrapper over scripts/testrail_import.py. Run:
python3 scripts/testrail_import.py <feature_name>
Input files
Resolve paths from <feature_name>:
- Input directory:
work/outputs/<feature_name>/ - CSV:
work/outputs/<feature_name>/<feature_name>-testcases.csv. If that exact name is absent, use the single*.csvin the directory (ignore files starting with~or.). Stop with an error if zero or more than one CSV exists.
Never modify any input file.
Generated output:
work/outputs/<feature_name>/testrail_import_report.md
Environment variables
Required:
TESTRAIL_URL
TESTRAIL_USER
TESTRAIL_API_KEY
TESTRAIL_PROJECT_ID
TESTRAIL_SUITE_ID # target suite for Critical / High / Medium priority cases
TESTRAIL_SUITE_ID_LOW # target suite for Low priority cases (required only when the CSV contains any Low-priority case)
Priority-based suite routing: cases with Critical, High, or Medium priority are created in TESTRAIL_SUITE_ID; cases with Low priority are created in TESTRAIL_SUITE_ID_LOW. Each suite gets its own root section + section structure. If the CSV has Low-priority cases and TESTRAIL_SUITE_ID_LOW is not set, the import fails before creating anything.
Optional (with defaults):
TESTRAIL_TEMPLATE_ID
TESTRAIL_USE_SEPARATED_STEPS = false
TESTRAIL_EXTERNAL_ID_FIELD = custom_external_id
TESTRAIL_PRECONDITIONS_FIELD = custom_preconds
TESTRAIL_STEPS_FIELD = custom_steps
TESTRAIL_EXPECTED_FIELD = custom_expected
TESTRAIL_SEPARATED_STEPS_FIELD = custom_steps_separated
TESTRAIL_SUB_TEST_SUITE_FIELD = custom_sub_test_suites
TESTRAIL_REFERENCES_FIELD = refs
TESTRAIL_REQUEST_TIMEOUT = 30
TESTRAIL_MAX_RETRIES = 3
Sub Test Suite(s): the CSV Sub Test Suite(s) labels (e.g. Special Case, Regression, Telemetry) are mapped to the option ids of the TESTRAIL_SUB_TEST_SUITE_FIELD multi-select case field and imported. If that field does not exist in the project it is skipped; any label that isn't a valid option is skipped with a warning (the case is still created).
A local .env is loaded automatically when python-dotenv is installed.
Never print the API key or write it to any file.
Steps rendering: set TESTRAIL_USE_SEPARATED_STEPS=true together with a
separated-steps TESTRAIL_TEMPLATE_ID (e.g. "Test Case (Steps)") to store each
step paired with its expected result. Otherwise Steps and Expected Results are
written to the plain-text fields (custom_steps / custom_expected), which
requires a text template.
CSV format
Eight columns (order may vary; headers matched by alias):
Section (Folder), Title, Preconditions, Steps, Expected Results, Priority, Type, Sub Test Suite(s)
Section (Folder)may use/,>, or::to express nested sub-sections.StepsandExpected Resultsuse matching line indices (1.,2., …).Priorityis one ofCritical,High,Medium,Low(P0–P3 aliases accepted); it drives suite routing (see Environment variables).Sub Test Suite(s)is a comma-separated list of tags (e.g.Special Case, Regression, Telemetry).
What the importer does
- Parse and validate the CSV (required columns present; every row has a section, title, steps, expected results, priority, and type; steps pair with expected results).
- Connect to TestRail and read priorities, case types, case fields, templates, and existing sections.
- Verify the configured content custom fields exist. The External ID and Sub Test Suite fields are optional — if they do not exist, they are skipped.
- Split cases by priority:
Critical/High/Medium→TESTRAIL_SUITE_ID;Low→TESTRAIL_SUITE_ID_LOW. - In each target suite that has cases, create a root section named after
the feature (e.g.
Google Lens). - Recreate the CSV's section structure inside that root section (per suite), reusing any sections that already exist and creating parents before children.
- Create every test case inside its section in its routed suite, mapping
Priority and Type to TestRail ids (with
P0..P3aliases and optional defaults). - Write
testrail_import_report.mdsummarizing, per suite, sections created, cases created, and any failures.
The feature name is turned into the root section's display name by splitting on
-/_/space and capitalizing each word (google-lens → Google Lens).
Report
work/outputs/<feature_name>/testrail_import_report.md records the target
project/suite, the root section, counts (sections created, cases created, cases
failed), the created case ids, and any failures. Status is COMPLETED or
COMPLETED_WITH_ERRORS.
Notes
- Re-running imports again; it does not deduplicate. To reimport cleanly, remove the previously created feature section in TestRail first.
- Deletions and updates are out of scope — the importer only creates.