Appearance
TestRail migration
WARNING
MIGRATION AVAILABLE FOR ALLURE TESTOPS VERSION > 4.26.0
Prerequisites
Make sure that API calls are enabled on your TestRail instance and that you have generated a valid API token.
Enable API
Open https://COMPANY.testrail.io/index.php?/admin/site_settings and turn the API on.

Generate the API token and save it right away, TestRail does not show it again.

Configuration file example
Create the json file with content like:
Click to see full configuration file example
json
{
"type": "testrail",
"debug": true,
"requestLog": false,
"oneByOne": false,
"allureConfig": {
"endpoint": "https://demo.testops.cloud/",
"token": "allure-testops-token",
"sslTrustAll": true,
"projectId": 6,
"migrationTagPrefix": "testrail",
"folderCfPrefix": "Section",
"issueTrackerId": 3
},
"testrailConfig": {
"endpoint": "https://testrail-endpoint/",
"username": "username/email to connect testrail",
"password": "j8YLcMqPQy.khJ2LGW2M-RouSqHtedR3qbY/k1e.t",
"sslTrustAll": true,
"projectId": 1,
"suiteIds": [1, 2],
"caseIds": [1, 2, 3],
"suitePattern": "{suite_name}",
"htmlFields": false,
"oldAttachmentApi": false,
"oldBulkApi": false,
"descriptionFieldName": "custom_description",
"preconditionStructure": [
{
"customFieldName": "custom_preconds",
"displayName": ""
}
],
"stepsSeparatedFieldName": "custom_steps_separated",
"useParentDescription": false,
"stepsAsPrecondition": true,
"requiredCfMapping": true,
"createdByAsOwner": false,
"withDeleted": false,
"statusMapping": [
{
"name": "custom_status",
"workflowId": 1,
"values": {
"1": "Draft",
"2": "Active"
}
},
{
"name": "custom_status_auto",
"workflowId": 2,
"values": {
"1": "Start",
"2": "Automated"
}
}
],
"customFields": {
"suite_id": "Suite",
"priority_id": "Priority",
"custom_tester": "Owner",
"custom_system": "System"
},
"customFieldsMapping": [
{
"name": "priority_id",
"values": {
"1": "Low",
"2": "Medium",
"3": "High",
"4": "Critical"
}
},
{
"name": "custom_tester",
"values": {
"1": "Tester QA1",
"2": "Tester QA2",
"3": "Tester QA3",
"4": "Tester QA4"
}
}
]
}
}WARNING
Edit this config file before running the migration!
You can download a reference config with every available parameter, comments and mapping examples here. Delete the header, the comments and the parameters you do not need before using it, the migration tool parses strict JSON.
Additional settings
- Migrate custom tags into TestOps tags:
Add the property into the customFields settings area:
json
"custom_tag": "TESTOPS_TAG",In this case the values will be migrated as tags and not as a custom field.
- To migrate a TestRail custom field as the TestOps test layer, add the property into the
customFieldssettings area:
json
"type_id": "TESTOPS_TEST_LAYER",- To migrate a TestRail custom field as a TestOps comment, add the property into the
customFieldssettings area:
json
"custom_comment": "TESTOPS_COMMENT",- The TestRail
created_byfield is migrated as a TestOps member (owner) whencreatedByAsOwneris set to true. This needs an additional mapping in thecustomFieldsMappingarea:
json
{
"name": "created_by",
"values": {
"1": "username1",
"2": "username2"
}
},The value pattern is "TestRail user id": "TestOps username".
The migration script can create the users for you if you do not provide that mapping. Set "createOwner": true in the Allure TestOps config area, and the username will be taken from the email in the TestRail user information.
Fields edited with the TestRail WYSIWYG editor
TestRail can store a field either as markdown or as HTML, depending on how it was written. Fields edited with the WYSIWYG editor hold HTML, and the migration passes it through unchanged unless you set htmlFields to true.
You need this flag when a migrated test case shows raw markup in Allure TestOps instead of formatted content, for example:
html
<p>Launch the test environment and verify the system is in a clean state.</p><p><img src="index.php?/attachments/get/1000000014#_t=1788797070844787" class="fr-fic fr-dib fr-fil markdown-img" data-attachment-id="1000000014"></p>To tell which format a field uses, request the case through the API and look at the field value:
GET <TR-url>/index.php?/api/v2/get_case/{case_id}If the value contains tags such as <p>, <img> or <table>, set the flag:
json
"htmlFields": trueWith the flag on, the description, precondition, expected result and every step field are converted to markdown before any other processing. Three things follow from that.
Images become real attachments. An <img src="index.php?/attachments/get/..."> tag is resolved to the attachment the migration has already uploaded for the test case, and replaced with a reference to it.
Tables are converted. A table in the description is migrated as an inline markdown table. A table in a step body is uploaded as a separate markdown attachment named <step>_table_<N>.md and referenced from the step, because a step body in Allure TestOps has no markdown rendering.
Empty editor paragraphs are dropped, so the spacer <br> elements do not end up as visible text.
WARNING
Do not enable the flag when your fields hold plain markdown. The conversion escapes markdown syntax, so *text* becomes \*text\* and the native TestRail table syntax ||a||b becomes \|\|a\|\|b. Migrate a few cases with caseIds first and check the result before running the whole project.
TIP
Images are only downloaded when the attachment API is reachable. Set oldAttachmentApi to true to fetch them with the API token from this config, or provide testRailSessionCookie. Without either of them the migration reports the attachment as empty in the log and skips it.
Configuration parameters
| Name | Mandatory | Description | Example |
|---|---|---|---|
| commonProperties | yes | see description here: Common properties | |
| allureConfig | yes | see description here: Allure TestOps properties | |
| endpoint | yes | TestRail instance url | https://company.testrail.io/ |
| username | yes | TestRail username (email) | |
| password | yes | TestRail API token generated in the TestRail UI, or the account password if you authenticate through LDAP | |
| sslTrustAll | no | Defines whether the ssl validation should be omitted. True omits the validation, false keeps it | true |
| projectId | yes | TestRail project id | 2 |
| suiteIds | no | A list of specific suites to migrate. Without this parameter every suite of the project is migrated | [1, 2] |
| caseIds | no | A list of specific cases to migrate. Without this parameter every case of the project or the selected suites is migrated. Useful for a trial run before the full migration | [1, 2, 3] |
| suitePattern | no | Pattern for the suite custom field. The default value is {suite_name} and it can be extended with the project name | {project_name} |
| htmlFields | no | Set to true when TestRail fields are filled with the WYSIWYG editor and hold HTML instead of markdown. The description, precondition, expected result and every step field are then converted to markdown first, images become attachments and tables are migrated as tables. Off by default, because the conversion escapes plain markdown. See Fields edited with the TestRail WYSIWYG editor | true |
| oldAttachmentApi | no | Set to true to download attachments through /api/v2/get_attachment/<id> using the API token from this config. This is also the setting for TestRail older than 7.1. Leave it false only if you provide testRailSessionCookie as well, otherwise attachments are skipped and the reason is written to the log | true |
| testRailSessionCookie | no | Session cookie of a signed in TestRail user, taken from the Network tab of the browser dev tools. It is used only when oldAttachmentApi is false. The cookie expires, so oldAttachmentApi is the better choice for a migration you intend to repeat | tr_session=691f4eb4-5758-48d7-884d-dfcf460888f4 |
| oldBulkApi | no | Set to true for TestRail older than 7.1, where the bulk endpoints are not paginated | true |
| descriptionFieldName | no | Set this property if the description field in TestRail is named differently from custom_description | custom_description |
| expectedFieldName | no | Set this property if the expected result field in TestRail is named differently from custom_expected | custom_expected |
| stepsSeparatedFieldName | no | Set this property if the separated steps field in TestRail is named differently from custom_steps_separated | custom_steps_separated |
| preconditionStructure | no | Set this property if the precondition field in TestRail is named differently from preconds, or to migrate several fields into the precondition. Where customFieldName is the name from TestRail and displayName is the heading for that section in the precondition area of the test case. With the example on the right the precondition becomes:Precondition1 Some text from custom_field1 Precondition2 Some text from custom_field2 | preconditionStructure: [{ "customFieldName": "custom_field1", "displayName": "Precondition1" }, { "customFieldName": "custom_field2", "displayName": "Precondition2" } ] |
| useParentDescription | no | Adds the description of the parent sections and suites to the test case description. TestRail suite description becomes part of the TestOps test case description | false |
| stepsAsPrecondition | no | Puts the value of the TestRail custom_steps field into the Allure TestOps precondition, appended after the precondition value itself | false |
| usePrimarySeparatedSteps | no | If a case has both custom_steps and custom_steps_separated, set this to true to build the scenario from the separated steps | true |
| stepsFieldAsSingleStep | no | Set to true to migrate the whole content of custom_steps as one step in Allure TestOps instead of splitting it line by line | false |
| withFieldStepMapping | no | Set this property to false if you see an error like LinkedHashMap cannot be cast to Field$Step | true |
| requiredCfMapping | no | Defines whether the custom field mapping is required. If set to false, the raw TestRail id is used as the Allure TestOps custom field value | true |
| createdByAsOwner | no | Set to true to migrate the TestRail created_by field as the Allure TestOps member (owner) | false |
| withDeleted | no | Set to true to migrate the cases marked as is_deleted. Works only when oldBulkApi is false or not set | true |
| onlyCfMigration | no | Set to true to update only the custom fields listed in customFields on test cases that have already been migrated. The scenario, description and attachments are left untouched, and cases that are not found in Allure TestOps are skipped. Use it to fix a custom field mapping without repeating the whole migration | true |
| refsAsLinks | no | Migrates the TestRail refs field as links on the Allure TestOps test case. Use it when you store urls there. When the flag is off, the field is migrated as issues instead | false |
| refsSeparator | no | Separator used to split the refs field into several values. The default is a comma | , |
| customTagSeparator | no | Separator for tags. If your TestRail field contains a value like tag1, tag2, tag3, use , to split it into three tags | , |
| attachmentsLinkPattern | no | If the steps of a TestRail case link to an image hosted elsewhere, for example , the link can be converted into an html attachment. Provide a regex that captures the address. The link and name groups are both required | !\[]\((?<link>https://some\.url/[a-zA-Z0-9]+/(?<name>[a-zA-Z0-9-]+)\.jpg)\) |
| customFieldsAsLinks | no | A list of TestRail custom fields whose values are migrated as Allure TestOps links | customFieldsAsLinks: ["custom_link", "custom_links_url" ] |
| statusMapping | no | Maps a TestRail status field onto an Allure TestOps workflow. name is the field name in TestRail, workflowId is the workflow id in Allure TestOps, and values maps a TestRail status id to an Allure TestOps status name.The first mapping that matches is the one applied, so list the more specific fields first | statusMapping: [{ "name": "custom_status", "workflowId": 1, "values": { "1": "Draft", "2": "Active" } } ] |
| customFields | no | A list of TestRail fields to migrate as Allure TestOps custom fields, in the form "testrail_field_name": "Allure_custom_field_name".If a value is stored as an id in TestRail, map the ids to names in customFieldsMapping.To get the real TestRail field names, send GET <TR-url>/index.php?/api/v2/get_case/{case_id} with basic auth and the credentials from this config. The response lists every field name, custom ones carrying the custom_ prefix | customFields: {"suite_id": "Suite", "priority_id": "Priority", "custom_tester": "Owner", "custom_system": "System" } |
| customFieldsMapping | no | Maps TestRail ids to values. name is the TestRail field name and values maps each id to the value to migrate | customFieldsMapping: [{ "name": "priority_id", "values": { "1": "Low", "2": "Medium", "3": "High", "4": "Critical" } } ] |