UiPath Documentation
test-manager
2024.10
false

Test Manager user guide

Last updated May 20, 2026

TMH file format specification

Introduction

A .tmh file is UiPath Test Manager's portable data container format. While it is commonly used to back up and restore entire projects, its scope is broader than that:

  • Project backup and restore — export a complete project including all test cases, test sets, requirements, executions, and configuration, then import it into a new or existing project.
  • Selective object migration — export any subset of objects (e.g. only test cases, or only requirements) and import them into a different project or a different Test Manager instance.
  • Cross-instance migration — move projects between Test Manager deployments, including between cloud and on-premises installations.
  • Third-party tooling — external tools and scripts can generate .tmh files from scratch to bulk-create Test Manager objects without using the UI or API directly. This document is intended to support those integration efforts.

A .tmh file is a standard ZIP archive with the .tmh extension. It can be opened with any ZIP tool by renaming it to .zip. The archive contains a manifest.json at the root and all exported object data under an objects/ directory tree.

Archive structure

<package-name>.tmh               ← ZIP archive
├── manifest.json                ← Package metadata and object counts
└── objects/
    ├── requirements/
    │   └── requirements-{n}.json
    ├── testcases/
    │   └── testcases-{n}.json
    ├── teststeps/
    │   └── teststeps-{n}.json
    ├── testsets/
    │   └── testsets-{n}.json
    ├── testsettestcaseassignments/
    │   └── testsettestcaseassignments-{n}.json
    ├── requirementtestcaseassignments/
    │   └── requirementtestcaseassignments-{n}.json
    ├── objectlabels/
    │   └── objectlabels-{n}.json
    ├── customfieldvalues/
    │   └── customfieldvalues-{n}.json
    ├── customfieldlabels/
    │   └── customfieldlabels-{n}.json
    ├── customfielddefinitions/
    │   └── customfielddefinitions-{n}.json
    ├── attachments/
    │   └── attachments-{n}.json
    ├── testexecutions/
    │   └── testexecutions-{n}.json
    ├── testcaselogs/
    │   └── testcaselogs-{n}.json
    ├── teststeplogs/
    │   └── teststeplogs-{n}.json
    ├── testcaselog-assertions/
    │   └── testcaselog-assertions-{n}.json
    ├── testcaselogresultoverrides/
    │   └── testcaselogresultoverrides-{n}.json
    ├── assertion-attachments/
    │   └── assertion-attachments-{n}.json
    ├── defects/
    │   └── defects-{n}.json
    ├── parameters/
    │   └── parameters-{n}.json
    ├── testsetpackages/
    │   └── testsetpackages-{n}.json
    ├── testsettestcaseparameters/
    │   └── testsettestcaseparameters-{n}.json
    ├── testsetschedules/
    │   └── testsetschedules-{n}.json
    ├── objectfilters/
    │   └── objectfilters-{n}.json
    ├── projectauthorization/
    │   └── projectauthorization-{n}.json
    ├── projectsettings/
    │   └── projectsettings.json         ← singular, no number suffix
    └── prompts/
        └── prompts-{n}.json
<package-name>.tmh               ← ZIP archive
├── manifest.json                ← Package metadata and object counts
└── objects/
    ├── requirements/
    │   └── requirements-{n}.json
    ├── testcases/
    │   └── testcases-{n}.json
    ├── teststeps/
    │   └── teststeps-{n}.json
    ├── testsets/
    │   └── testsets-{n}.json
    ├── testsettestcaseassignments/
    │   └── testsettestcaseassignments-{n}.json
    ├── requirementtestcaseassignments/
    │   └── requirementtestcaseassignments-{n}.json
    ├── objectlabels/
    │   └── objectlabels-{n}.json
    ├── customfieldvalues/
    │   └── customfieldvalues-{n}.json
    ├── customfieldlabels/
    │   └── customfieldlabels-{n}.json
    ├── customfielddefinitions/
    │   └── customfielddefinitions-{n}.json
    ├── attachments/
    │   └── attachments-{n}.json
    ├── testexecutions/
    │   └── testexecutions-{n}.json
    ├── testcaselogs/
    │   └── testcaselogs-{n}.json
    ├── teststeplogs/
    │   └── teststeplogs-{n}.json
    ├── testcaselog-assertions/
    │   └── testcaselog-assertions-{n}.json
    ├── testcaselogresultoverrides/
    │   └── testcaselogresultoverrides-{n}.json
    ├── assertion-attachments/
    │   └── assertion-attachments-{n}.json
    ├── defects/
    │   └── defects-{n}.json
    ├── parameters/
    │   └── parameters-{n}.json
    ├── testsetpackages/
    │   └── testsetpackages-{n}.json
    ├── testsettestcaseparameters/
    │   └── testsettestcaseparameters-{n}.json
    ├── testsetschedules/
    │   └── testsetschedules-{n}.json
    ├── objectfilters/
    │   └── objectfilters-{n}.json
    ├── projectauthorization/
    │   └── projectauthorization-{n}.json
    ├── projectsettings/
    │   └── projectsettings.json         ← singular, no number suffix
    └── prompts/
        └── prompts-{n}.json
Note:

Object type folders that contain no data can be omitted entirely. The importer silently skips missing folders and files.

File naming conventions

Most object types — numbered chunks

Files are named <type>-{n}.json where {n} starts at 0 for real exports produced by the system. For example:

requirementtestcaseassignments-0.json
testcases-0.json
teststeps-0.json
requirementtestcaseassignments-0.json
testcases-0.json
teststeps-0.json

When manually constructing a .tmh file you may use {n} = 1 (e.g., testcases-1.json) — the importer scans for any matching file in the folder. Both 0 and 1 based numbering work.

Large exports may be split across multiple files (testcases-0.json, testcases-1.json, etc.) — the importer reads all files in the folder in order. Splitting large datasets into chunks prevents imports from being cancelled due to excessive resource consumption and improves performance. It is recommended to keep each chunk to a maximum of 500 objects.

Project settings — no number suffix

projectsettings/projectsettings.json
projectsettings/projectsettings.json

This file is always singular (no chunk number).

Encoding requirements

All JSON files must be encoded as UTF-8 without BOM.

Warning:

PowerShell 5.1's Set-Content -Encoding utf8 writes a UTF-8 BOM (EF BB BF). This causes JSON.parse in the browser to throw SyntaxError: Unexpected token at position 0. Always use [System.IO.File]::WriteAllText($path, $content, (New-Object System.Text.UTF8Encoding($false))) when creating .tmh files from PowerShell.

Schema versioning

The manifest.json carries a schemaVersion field (e.g., "1.0.16"). The importer uses this version together with [IntroducedIn] attributes on each DTO property to determine which fields to read. Fields introduced in a version newer than the package's schema version are ignored during deserialization.

Current latest version: 1.0.16

Version history summary:

VersionNotable additions
1.0.0Initial: requirements, test cases, test steps, test sets, assignments, labels, attachments, defects, custom field values
1.0.1preCondition on test cases
1.0.2Test executions, test case log result overrides, assertions
1.0.4Subset export (isSubsetExport, exportSubsetDetails)
1.0.5Custom field labels
1.0.7User-defined prompts
1.0.9postCondition on test cases
1.0.10Parameters
1.0.11Test set packages, folderKey/folderName on test sets, packageEntryPointUniqueId etc. on test cases
1.0.13id field on attachments
1.0.14studioWebFileId/studioWebProjectId on test cases; id on test-set/test-case assignments
1.0.15assigneeEmail on test-set/test-case assignments
1.0.16Project configuration (settings, governance, signatories), custom field definitions, project authorizations

manifest.json

Located at the root of the archive (not inside objects/).

{
  "objectCountDetails": {
    "testCases": 5,
    "testSets": 2,
    "requirements": 3,
    "objectLabels": 0,
    "attachments": 0,
    "testExecutions": 0,
    "testCaseLogs": 0,
    "testCaseResultOverrides": 0,
    "testSteps": 12,
    "testStepLogs": 0,
    "testSetTestCaseAssignments": 6,
    "requirementTestCaseAssignments": 4,
    "defects": 0,
    "customFieldValues": 0,
    "customFieldLabels": 0,
    "assertions": 0,
    "assertionScreenshots": 0,
    "testSetLabelFilters": 0,
    "userDefinedPrompts": 0,
    "parameters": 0,
    "testSetPackages": 0,
    "testSetTestCaseParameters": 0,
    "customFieldDefinitions": 0,
    "projectAuthorizations": 0
  },
  "project": {
    "name": "My Project",
    "description": "Project description",
    "projectPrefix": "MP"
  },
  "tmPackageId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "schemaVersion": "1.0.16"
}
{
  "objectCountDetails": {
    "testCases": 5,
    "testSets": 2,
    "requirements": 3,
    "objectLabels": 0,
    "attachments": 0,
    "testExecutions": 0,
    "testCaseLogs": 0,
    "testCaseResultOverrides": 0,
    "testSteps": 12,
    "testStepLogs": 0,
    "testSetTestCaseAssignments": 6,
    "requirementTestCaseAssignments": 4,
    "defects": 0,
    "customFieldValues": 0,
    "customFieldLabels": 0,
    "assertions": 0,
    "assertionScreenshots": 0,
    "testSetLabelFilters": 0,
    "userDefinedPrompts": 0,
    "parameters": 0,
    "testSetPackages": 0,
    "testSetTestCaseParameters": 0,
    "customFieldDefinitions": 0,
    "projectAuthorizations": 0
  },
  "project": {
    "name": "My Project",
    "description": "Project description",
    "projectPrefix": "MP"
  },
  "tmPackageId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "schemaVersion": "1.0.16"
}
Note:

packageName, packageSize, and chunkSize fields exist in the DTO but are marked [ProjectImportSchemaIgnore] — the importer ignores them. Real exports omit these fields; do not include them in hand-crafted files.

objects/ — JSON File Schemas

Every object file uses a wrapper object whose single property is a JSON array. The array contains the individual object records.

requirements/{n}.json

{
  "requirements": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "User can log in",
      "description": "The login form must accept valid credentials.",
      "foreignRef": "",
      "connectorRequirementId": "00000000-0000-0000-0000-000000000000"
    }
  ]
}
{
  "requirements": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "User can log in",
      "description": "The login form must accept valid credentials.",
      "foreignRef": "",
      "connectorRequirementId": "00000000-0000-0000-0000-000000000000"
    }
  ]
}
FieldTypeNotes
idGUID stringUnique per-requirement identifier
namestringRequired; max 255 chars
descriptionstringCan be empty string
foreignRefstringExternal system reference; can be empty
connectorRequirementIdGUID stringUse "00000000-0000-0000-0000-000000000000" when not linked to a connector

testcases/{n}.json

{
  "testCases": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "version": null,
      "name": "Verify login with valid credentials",
      "inputParams": "",
      "description": "",
      "automationId": "",
      "automationTestCaseName": "",
      "automationProjectName": "",
      "foreignRef": "",
      "connectorTestCaseId": "",
      "preCondition": "",
      "postCondition": "",
      "packageEntryPointUniqueId": "",
      "packageIdentifier": "",
      "packageEntryPointName": "",
      "feedId": "",
      "packageSourceName": "",
      "studioWebFileId": "",
      "studioWebProjectId": ""
    }
  ]
}
{
  "testCases": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "version": null,
      "name": "Verify login with valid credentials",
      "inputParams": "",
      "description": "",
      "automationId": "",
      "automationTestCaseName": "",
      "automationProjectName": "",
      "foreignRef": "",
      "connectorTestCaseId": "",
      "preCondition": "",
      "postCondition": "",
      "packageEntryPointUniqueId": "",
      "packageIdentifier": "",
      "packageEntryPointName": "",
      "feedId": "",
      "packageSourceName": "",
      "studioWebFileId": "",
      "studioWebProjectId": ""
    }
  ]
}
FieldTypeNotes
idGUID stringUnique per test case
versionstring | nullnull for manual test cases; populated for automated test cases linked to a package version
namestringRequired; max 255 chars
inputParamsstringJSON-encoded input parameters; empty string for manual
descriptionstringRich text description
automationIdstringUiPath automation identifier; empty for manual
automationTestCaseNamestringAutomation display name; empty for manual
automationProjectNamestringAutomation project; empty for manual
foreignRefstringExternal system reference
connectorTestCaseIdstringConnector system ID
preConditionstring (v1.0.1+)Pre-condition text; max 8000 chars
postConditionstring (v1.0.9+)Post-condition text; max 8000 chars
packageEntryPointUniqueIdstring (v1.0.11+)Package entry point; empty for manual
packageIdentifierstring (v1.0.11+)Package ID; empty for manual
packageEntryPointNamestring (v1.0.11+)Entry point name; empty for manual
feedIdstring (v1.0.11+)Package feed ID; empty for manual
packageSourceNamestring (v1.0.11+)Package source name; empty for manual
studioWebFileIdstring (v1.0.14+)Studio Web file ID; empty for manual
studioWebProjectIdstring (v1.0.14+)Studio Web project ID; empty for manual

teststeps/{n}.json

{
  "testSteps": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440010",
      "testCaseId": "550e8400-e29b-41d4-a716-446655440001",
      "orderNo": 1,
      "actionType": null,
      "description": "Navigate to the login page",
      "expectedResult": "Login page is displayed",
      "clipboardData": ""
    }
  ]
}
{
  "testSteps": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440010",
      "testCaseId": "550e8400-e29b-41d4-a716-446655440001",
      "orderNo": 1,
      "actionType": null,
      "description": "Navigate to the login page",
      "expectedResult": "Login page is displayed",
      "clipboardData": ""
    }
  ]
}
FieldTypeNotes
idGUID stringUnique per step
testCaseIdGUID stringMust reference an existing test case id
orderNointeger1-based display order
actionTypestring | nullnull for manual steps
descriptionstringStep action text
expectedResultstringExpected outcome
clipboardDatastringClipboard/screenshot data; max 8000 chars; usually empty

testsets/{n}.json

{
  "testSets": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440020",
      "version": "",
      "name": "Regression Suite",
      "description": "",
      "source": 0,
      "externalTestSetId": "",
      "sourceDetails": "",
      "folderKey": "",
      "folderName": ""
    }
  ]
}
{
  "testSets": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440020",
      "version": "",
      "name": "Regression Suite",
      "description": "",
      "source": 0,
      "externalTestSetId": "",
      "sourceDetails": "",
      "folderKey": "",
      "folderName": ""
    }
  ]
}
FieldTypeNotes
idGUID stringUnique per test set
namestringRequired; max 255 chars
sourceinteger0 = TestManager (default); 1 = external
folderKeystring (v1.0.11+)UiPath Orchestrator folder key; empty if not linked
folderNamestring (v1.0.11+)Folder display name; not stored in DB, informational only

testsettestcaseassignments/{n}.json

{
  "testSetTestCaseAssignments": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440030",
      "testSetId": "550e8400-e29b-41d4-a716-446655440020",
      "testCaseId": "550e8400-e29b-41d4-a716-446655440001",
      "assigneeEmail": null
    }
  ]
}
{
  "testSetTestCaseAssignments": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440030",
      "testSetId": "550e8400-e29b-41d4-a716-446655440020",
      "testCaseId": "550e8400-e29b-41d4-a716-446655440001",
      "assigneeEmail": null
    }
  ]
}
FieldTypeNotes
idGUID string (v1.0.14+)Assignment identifier
testSetIdGUID stringReferences a test set id
testCaseIdGUID stringReferences a test case id
assigneeEmailstring | null (v1.0.15+)Assignee email; null if unassigned

requirementtestcaseassignments/{n}.json

{
  "requirementTestCaseAssignments": [
    {
      "requirementId": "550e8400-e29b-41d4-a716-446655440000",
      "testCaseId": "550e8400-e29b-41d4-a716-446655440001"
    }
  ]
}
{
  "requirementTestCaseAssignments": [
    {
      "requirementId": "550e8400-e29b-41d4-a716-446655440000",
      "testCaseId": "550e8400-e29b-41d4-a716-446655440001"
    }
  ]
}
Warning:

No id field. Unlike most other object types, requirement–test case assignments have only requirementId and testCaseId.

objectlabels/{n}.json

{
  "objectLabels": [
    {
      "objectId": "550e8400-e29b-41d4-a716-446655440001",
      "objectType": "TestCase",
      "labelName": "regression",
      "labelColor": "#FF5733"
    }
  ]
}
{
  "objectLabels": [
    {
      "objectId": "550e8400-e29b-41d4-a716-446655440001",
      "objectType": "TestCase",
      "labelName": "regression",
      "labelColor": "#FF5733"
    }
  ]
}

customfieldvalues/{n}.json

{
  "customFieldValues": [
    {
      "objectId": "550e8400-e29b-41d4-a716-446655440001",
      "objectType": "TestCase",
      "fieldName": "Priority",
      "fieldValue": "High"
    }
  ]
}
{
  "customFieldValues": [
    {
      "objectId": "550e8400-e29b-41d4-a716-446655440001",
      "objectType": "TestCase",
      "fieldName": "Priority",
      "fieldValue": "High"
    }
  ]
}

projectsettings/projectsettings.json

Introduced in schema version 1.0.16. Only present when "Export project configuration" is enabled.

{
  "projectTimeZone": "Europe/Vienna",
  "folderKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "governanceEnabled": true,
  "governedByDefault": false,
  "signatories": [
    {
      "signatoryId": "550e8400-e29b-41d4-a716-446655440099",
      "signatoryType": "User",
      "signatoryLastKnownDetails": "{\"displayName\":\"John Doe\",\"email\":\"john.doe@company.com\"}"
    },
    {
      "signatoryId": "550e8400-e29b-41d4-a716-446655440100",
      "signatoryType": "UserGroup",
      "signatoryLastKnownDetails": "{\"displayName\":\"Administrators\"}"
    }
  ]
}
{
  "projectTimeZone": "Europe/Vienna",
  "folderKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "governanceEnabled": true,
  "governedByDefault": false,
  "signatories": [
    {
      "signatoryId": "550e8400-e29b-41d4-a716-446655440099",
      "signatoryType": "User",
      "signatoryLastKnownDetails": "{\"displayName\":\"John Doe\",\"email\":\"john.doe@company.com\"}"
    },
    {
      "signatoryId": "550e8400-e29b-41d4-a716-446655440100",
      "signatoryType": "UserGroup",
      "signatoryLastKnownDetails": "{\"displayName\":\"Administrators\"}"
    }
  ]
}
Note:

Unlike all other object files, projectsettings.json is a direct object (not a wrapper array). The file contains a single flat JSON object.

FieldTypeNotes
projectTimeZonestring | nullIANA timezone string (e.g., "Europe/Vienna")
folderKeyGUID | nullLinked Orchestrator folder
governanceEnabledboolean | nullWhether governance is enabled for the project
governedByDefaultboolean | nullWhether new test cases are governed by default
signatoriesarray | nullList of approvers/signatories
signatories[].signatoryIdGUIDUser or group ID from the identity provider
signatories[].signatoryTypestring"User" or "UserGroup"
signatories[].signatoryLastKnownDetailsstring (JSON)Serialised JSON object with display details captured at export time. Used as a fallback during import if the identity cannot be resolved from the identity provider. For users: {"displayName":"…","email":"…"}; for groups: {"displayName":"…"}
Note:

lastDisabledAt (the governance disable timestamp) is intentionally excluded from the export — it is an internal timestamp that is not meaningful for a re-imported project.

customfielddefinitions/{n}.json

Introduced in schema version 1.0.16. Only present when "Export project configuration" is enabled.

{
  "customFieldDefinitions": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440050",
      "name": "Severity",
      "description": "Bug severity level",
      "dataType": "Label",
      "defaultValue": "",
      "valueHints": "Low,Medium,High,Critical",
      "objectType": "TestCase",
      "scope": 2,
      "scopeList": ["TestCase"]
    }
  ]
}
{
  "customFieldDefinitions": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440050",
      "name": "Severity",
      "description": "Bug severity level",
      "dataType": "Label",
      "defaultValue": "",
      "valueHints": "Low,Medium,High,Critical",
      "objectType": "TestCase",
      "scope": 2,
      "scopeList": ["TestCase"]
    }
  ]
}
FieldTypeNotes
idGUID stringUnique identifier for this field definition
namestringDisplay name; max 255 chars
descriptionstring | nullOptional description
dataTypestring"Text" or "Label"
defaultValuestring | nullDefault value; max 4000 chars
valueHintsstring | nullComma-separated list of suggested/allowed values for Label fields; max 4000 chars
objectTypestringObject type this field applies to: "Requirement", "TestCase", "TestSet", "TestExecution"
scopeintegerBitmask of scopeList values (legacy field; kept for compatibility)
scopeListarray of stringsList of applicable scopes: "Requirement" (1), "TestCase" (2), "TestSet" (4), "TestExecution" (8)

projectauthorization/{n}.json

Introduced in schema version 1.0.16. Only present when "Export project configuration" is enabled.

{
  "userPermissions": [
    {
      "identityProviderId": "550e8400-e29b-41d4-a716-446655440060",
      "email": "jane.smith@company.com",
      "displayName": "Jane Smith",
      "userType": "User",
      "roles": ["TestManager.View", "TestManager.Edit"]
    },
    {
      "identityProviderId": "550e8400-e29b-41d4-a716-446655440061",
      "email": "",
      "displayName": "QA Team",
      "userType": "DirectoryGroup",
      "roles": ["TestManager.View"]
    }
  ]
}
{
  "userPermissions": [
    {
      "identityProviderId": "550e8400-e29b-41d4-a716-446655440060",
      "email": "jane.smith@company.com",
      "displayName": "Jane Smith",
      "userType": "User",
      "roles": ["TestManager.View", "TestManager.Edit"]
    },
    {
      "identityProviderId": "550e8400-e29b-41d4-a716-446655440061",
      "email": "",
      "displayName": "QA Team",
      "userType": "DirectoryGroup",
      "roles": ["TestManager.View"]
    }
  ]
}
FieldTypeNotes
identityProviderIdGUID stringUser or group ID from the identity provider
emailstringEmail address; empty string for groups
displayNamestringDisplay name at time of export
userTypestring"User", "LocalUser", "LocalGroup", "DirectoryUser", "DirectoryGroup", or "Robot"
rolesarray of stringsRole names assigned to this user/group on the project

Rules and constraints

  1. All IDs must be unique, valid GUIDs. Do not reuse IDs across objects of the same or different type.

  2. Cross-references must resolve. A testCaseId in a test step or assignment must refer to a test case id present in the same package.

  3. Wrapper objects are required. Even when the collection has one item, it must still be wrapped: { "testCases": [ {...} ] }, never a bare array or object.

  4. Empty string vs. null: Most string fields default to "" (empty string), not null. Optional nullable fields (like version on test cases) should use null. Prefer null over "" for fields that are genuinely absent.

  5. objectCountDetails in the manifest should match actual counts of objects present, but the importer does not strictly validate counts — mismatches only affect the pre-import summary display.

  6. UTF-8 without BOM is mandatory for all files.

Minimal valid TMH file (hand-crafted)

The smallest valid .tmh file that Test Manager will accept contains just a manifest.json:

{
  "objectCountDetails": { ... },
  "project": { "name": "Test Project", "description": "", "projectPrefix": "TP" },
  "tmPackageId": "<new-guid>",
  "schemaVersion": "1.0.16"
}
{
  "objectCountDetails": { ... },
  "project": { "name": "Test Project", "description": "", "projectPrefix": "TP" },
  "tmPackageId": "<new-guid>",
  "schemaVersion": "1.0.16"
}

All objects/ subdirectories are optional. The importer silently skips any object type not present in the archive.

Was this page helpful?

Connect

Need help? Support

Want to learn? UiPath Academy

Have questions? UiPath Forum

Stay updated