# Move from Testmo or TestRail

> Bring your manual test cases from Testmo, TestRail or a spreadsheet into By Dawn's test case library, check the result with a dry run first, and import again safely.

This page helps you move your test cases from Testmo or TestRail into By Dawn. At the end your cases are in the
project's [test case library](https://docs.bydawn.com/test-cases/), in the folders they had before, ready to run by hand in By Dawn.

Your automated tests don't need moving: [Build your test library](https://docs.bydawn.com/test-library/) reads them from your repos. What
comes over from Testmo and TestRail are the cases you've written: their folders, steps, expected results, priority,
tags and links to tickets. The same import also reads any spreadsheet of test cases, Gherkin `.feature` files and
Markdown QA checklists.

## Before you start

- **Test management has to be on** for your organization. Without it the **Cases** tab says **Test management is not on
  your plan**, and the import is refused (`entitlement_required`). [Contact support](https://app.dev.sawrun.com/support) to turn it on.
- **An API key.** Importing has no button in the app yet: you send the file to By Dawn's API with one command. An owner
  or admin creates the key in **Settings › Organization › Security**, with **Access** set to
  **Tests — read & write cases & runs** ([API keys](https://docs.bydawn.com/api-keys/)). The other Tests keys can't import.
- **The project's ID**, which is in the project's settings, and `curl` and `jq` on your computer.

## Export from Testmo or TestRail

- **Testmo**: export the repository's cases as **CSV**. Keep the case ID column, because it's what lets you import
  the same export again later without making copies.
- **TestRail**: export a suite's cases as **XML** or **CSV**. XML is the better choice: it carries the section tree
  and each separated step with its expected result, without you picking columns. A CSV export should include
  **ID**, **Title**, **Section Hierarchy** and the step columns.

You can import several files at once, such as one per TestRail suite: up to 200 files, 5 MB each and 10 MB in
all, holding up to 5,000 cases. Split a bigger library into several imports.

## Check it with a dry run

Run the import with `dryRun` first. It writes nothing, and answers with what it would do with every case, so you can
check the folders and the warnings before anything lands.

1. Exchange your API key for an access token, as [Authentication](https://docs.bydawn.com/developers/authentication/) shows, and read your
   organization ID from the token's `org_id` claim (see
   [Your organization ID](https://docs.bydawn.com/developers/authentication/#your-organization-id)). A token lasts 15 minutes:

   ```sh
   export SAW_API_KEY=saw_live_…   # the key you created
   ACCESS_TOKEN=$(jq -n '{apiKey: env.SAW_API_KEY}' |
     curl -sS https://accounts.dev.sawrun.com/api/v1/auth/token/api-key \
       -H 'Content-Type: application/json' --data @- | jq -r .data.accessToken)
   ORG_ID=$(jq -rRn --arg t "$ACCESS_TOKEN" \
     '$t | split(".")[1] | gsub("-"; "+") | gsub("_"; "/") | @base64d | fromjson | .org_id')
   ```

2. Send the export with `"dryRun": true`. Set `format` to `testmo` or `testrail`, and `PROJECT_ID` to your
   project's ID:

   ```sh
   PROJECT_ID=…
   jq -n --rawfile content testrail-export.xml \
     '{format: "testrail", dryRun: true, files: [{path: "testrail-export.xml", content: $content}]}' |
     curl -sS "https://workspace.dev.sawrun.com/api/v1/orgs/$ORG_ID/projects/$PROJECT_ID/test-cases/import" \
       -H "Authorization: Bearer $ACCESS_TOKEN" -H 'Content-Type: application/json' --data @- |
     jq '.data | {created, updated, unchanged, skipped, foldersCreated, warnings}'
   ```

   By Dawn answers with what it would do:

   ```json
   {
     "created": 214,
     "updated": 0,
     "unchanged": 0,
     "skipped": 0,
     "foldersCreated": 18,
     "warnings": [
       { "file": "testrail-export.csv", "line": 1, "message": "columns left out: Estimate" },
       { "file": "testrail-export.csv", "line": 57, "message": "'NOPE-404' is not a ticket, epic or release of this project; not linked" }
     ]
   }
   ```

   The full answer also has `items`: one line per case with what would happen to it (`create`, `update`,
   `unchanged` or `skip`), its title, its folder path, its number of steps, and the file and line it came from.

3. Read the warnings. A row that can't become a case, such as one with no title, is a warning rather than a failure,
   so the rest still import. If nothing in the files reads as a case, the call fails and quotes the first warnings.

4. Run the same command without `dryRun: true` to import. The import is all or nothing: it writes every case or
   none.

To put everything under one folder of the library, such as `Imported from TestRail`, create the folder on the
**Cases** tab, then send its ID as `folderId`. Without it, the folders land at the top of the library. Folders that
already exist with the same name are reused, not doubled.

[`POST /projects/{projectId}/test-cases/import`](https://docs.bydawn.com/reference/#api/tag/tests/importTestCases) in the API reference has
every field and error.

## How their fields map

By Dawn reads each column by its name, ignoring case, spaces and punctuation, so `Steps (Expected Result)` and
`steps expected result` are the same column. These are the ones it reads, from Testmo and TestRail CSV alike:

| In By Dawn | Columns it reads |
|---|---|
| The case's source key | Testmo **Case ID**; TestRail **ID** (`123` and `C123` are the same case) |
| **Title** (needed) | **Title**, **Name**, **Case**, **Test case**, **Scenario** or **Summary** |
| Folders | **Section Hierarchy**, **Folder**, **Section**, **Path** or **Module**, split on `>`, `›`, `»`, `\` or ` / ` |
| **Description** | **Description**, **Objective**, **Goal**, **Notes** or **Comments** |
| **Preconditions** | **Preconditions**, **Prerequisites** or **Setup** |
| Steps | **Steps (Step)**, **Steps**, **Step**, **Action** or **Test steps** |
| Expected results | **Steps (Expected Result)**, **Expected Result**, **Expected** or **Result** |
| A step's test data | **Steps (Additional Info)**, **Data** or **Test data**, on the case's first step |
| **Priority** | **Priority** (below) |
| **Tags** | **Tags** or **Labels**, split on commas, semicolons or bars. TestRail's **Type** becomes a tag too, unless it's **Other** |
| State | **State** or **Status** (below) |
| Links | **References**, **Refs**, **Tickets**, **Issues** or **Requirements** |

Steps come over one by one. A steps cell with numbered lines (`1.`, `1)` or `Step 1:`) becomes that many steps,
and a matching numbered expected cell gives each step its own expected result; otherwise the whole expected cell goes
on the last step. In the one-row-per-step layout both tools can export, each row after the first adds a step to the
case above it.

From a TestRail XML export, each `<section>` becomes a folder (the suite's name becomes the top folder, unless it's
**Master**), and each case brings its title, priority, type, references, preconditions (`preconds`), description
(`mission` or `goals`) and separated steps.

**Priority** is matched by its words, with TestRail's number in front (`4 - `) ignored:

| By Dawn priority | What it reads |
|---|---|
| **Urgent** | Urgent, Critical, Blocker, Highest, P0, Must Test |
| **High** | High, Major, P1, Should Test |
| **Medium** | Medium, Normal, Moderate, P2, Test If Time |
| **Low** | Low, Minor, Trivial, Lowest, P3, P4, Don't Test |

Anything else, such as a custom priority, leaves a new case with no priority.

**State** sets whether a case is a draft, active or deprecated:

| By Dawn state | What it reads |
|---|---|
| **Draft** | Draft, New, Design, In design, In progress, Review, In review |
| **Active** | Active, Ready, Approved, Published, Final, Live |
| **Deprecated** | Deprecated, Retired, Obsolete, Archived, Outdated, Rejected |

A case with no state is **Active**. An unknown state is a warning. TestRail's XML export has no state, so its cases
come in active.

**Links** connect a case to the tickets it verifies. A reference that names a ticket of the project, such as
`SAW-123`, is linked. One that isn't, such as a Jira key from before you moved, is a warning and isn't linked.

## What doesn't come over

- **Results and runs.** The import brings cases, not their history, so your first By Dawn run starts each case at
  untested. Keep your Testmo or TestRail export if you need the old results.
- **Attachments, owners and custom fields.** The import has nowhere to put them. Add owners and fields to the cases
  in By Dawn, from the **Cases** tab.
- **Columns By Dawn doesn't read**, such as estimates and Testmo's custom fields. A CSV import names them in one warning
  (`columns left out: …`). A TestRail XML import leaves them out without a warning.
- **Milestones and test plans.** Plan the testing again in By Dawn, where it can sit on a cycle or release.

## Import again

Each case remembers the key it came from: its Testmo case ID, its TestRail case ID, or, for a file with no IDs, its
folder and title. So importing the same export again updates those cases rather than adding them twice, and you can
keep using Testmo or TestRail for a while and bring the latest over until you switch.

When a case is imported again:

- The title always follows the file. Other fields change only when the file has them: a column that's missing
  keeps what the case has in By Dawn.
- A case whose content changed gets a new revision on its **History**, and one that didn't is **unchanged**.
- Steps keep their place when their text matches, so results already recorded against them stay attached.
- Links are only ever added, never removed, and a case you've moved to another folder in By Dawn stays where you put it.

To bring in only the new cases and leave the ones already imported alone, send `"onExisting": "skip"`.

## Import from anything else

The same call reads other kinds of test case files. Set `format` to:

- `csv` for a spreadsheet with a header row. It reads the columns in [the table above](#how-their-fields-map), plus a
  `source_ref` column as the case's key. A row with a `case_id` from this project's library updates that case.
- `gherkin` for `.feature` files. Each Feature and Rule becomes a folder and each Scenario a case. Given, When and And
  lines are its steps, each Then is the expected result of the step before it, and the Background becomes its
  preconditions. `@tags` become tags, and a tag such as `@SAW-123` links the ticket.
- `markdown` for QA checklists and test sheets. Headings become folders and cases, numbered or `- [ ]` items become
  steps, and a line starting `Expected:` or `→` is a step's expected result.

If those files live in a repo of the project, such as `docs/qa/` or `TESTING.md`, you don't need to import them:
[Build your test library](https://docs.bydawn.com/test-library/) reads them for you.

## FAQ

**Can I import from the app instead?**

Not yet. The import has no button in the app, so it's the one command above. Once imported, everything else is in
the app: the **Cases** tab shows the cases, their folders and their history.

**The import said forbidden.**

The key needs **Tests — read & write cases & runs**. A **Tests — submit results** key, the one CI uses to send
results, can't write cases. Check too that the project is one the key can use: a restricted project refuses keys.

**I imported into the wrong folder.**

Move the folders on the **Cases** tab. Importing again won't move cases you've already imported, so they stay where
you put them.

**Can I export my cases from By Dawn?**

Not from the app or the public API yet.

## Next

- [Test cases](https://docs.bydawn.com/test-cases/): organise the imported cases, and link them to tickets.
- [Run tests by hand](https://docs.bydawn.com/test-runs/): your first run of the imported cases.
- [Build your test library](https://docs.bydawn.com/test-library/): add your automated tests and your repo's own QA files.

Source: https://docs.bydawn.com/tests-migrate/
