🛵

痒いところに手が届くTestRailからZephyrにデータ移行するツールを作ってみた

に公開

こんにちは。ダイの大冒険エンジョイ勢のbun913と申します。

みなさんはテストマネジメントツールを使ったことがありますか?私は最近事情があり、TestRailというツールからJIRAのプラグインとして提供されているZephyrというテストマネジメントツールにデータを移行する方法を調べていました。

その中で、TestRailから出力したCSVを元にZephyrにデータをインポートできることがわかりました。

https://support.smartbear.com/zephyr/docs/en/test-cases/import-test-cases.html

ただし、この方法では以下のように構造化されたデータを移行することができないようです。

# TestRailのセクション構造
- 権限管理
  - 一般ユーザー
    - Case1: ユーザーは設定画面にアクセスできない
    - Case2: ユーザーは個人のプロフィールにアクセスできる
  - 管理者ユーザー
    - Case3: 管理者は設定画面にアクセスできる
    - Case4: 管理者は他のユーザーのプロフィールにアクセスできる

セクションの構造を保てず、以下のように指定したフォルダに全てのテストケースがインポートされてしまいます。

- 権限管理
  - Case1: ユーザーは設定画面にアクセスできない
  - Case2: ユーザーは個人のプロフィールにアクセスできる
  - Case3: 管理者は設定画面にアクセスできる
  - Case4: 管理者は他のユーザーのプロフィールにアクセスできる

この程度の構造化なら良いのですが、2重3重にセクションが入れ子になっている場合、元の構造に込められた「ひとまとめにする意味」を失ってしまいます。

今後Zephyrに移行を考える方々が同じような悩みを抱える可能性が高いと考え、ちょうど昨日「何かに使うだろう」と思って作成していたZephyrのAPIクライアントを利用して、TestRailからZephyrに構造を保ったまま柔軟にデータ移行するツールを作成してみました。

↓ 昨日作成していたZephyrのAPIクライアントです

https://zenn.dev/moneyforward/articles/e863832fa9ce5e

↓ 今回作成したTestRailからZephyrにデータ移行するツールです

https://github.com/bun913/testrail-to-zephyr

https://www.npmjs.com/package/testrail-to-zephyr?activeTab=readme

ツールの概要

このツールでは意図的に3ステップに分けてデータ移行を行います。

  • prepare: TestRailとZephyrのAPIクライアントを利用して、データ構造を提示するためにJSONファイルを生成する
    • TestRailにもZephyrにもカスタムでフィールドを追加できるため、どのようなフィールドがあり、どのように情報をマッピングさせるかをユーザーに決めてもらう必要があります
    • このステップの後に情報をどのようにマッピングさせるかyamlファイルを編集してもらいます(基本的な項目であれば、編集も必要ないようにテンプレートを合わせて生成します)
  • convert: prepareで作成してもらったマッピング情報を元に、Zephyrにテストケースやディレクトリ(ファイル)を作るためのJSONファイルを生成する
    • ここで中間成果物を生成して、最後のmigrateステップでAPIを順次呼び出していきます
  • migrate: convertで作成したJSONファイルを元に、ZephyrのAPIを呼び出してデータを移行する
    • APIのレートリミットに注意しつつ、順次APIを呼び出していきます

1. prepare ステップ

まずは TestRail と Zephyr のAPIクライアントを利用して、「どのようにTestRailのデータをZephyrにマッピングさせるか」を決めてもらうためのファイルを生成します。

基本的にこのステップでは以下のように mapping.yaml というファイルを作ってもらうことが目的です。

fields:
  # Basic Fields
  name: title
  precondition: custom_preconds
  objective: custom_expected

  # Custom Fields (add as needed)
  # objective: custom_expected
  testSteps:
    source: custom_steps_separated
    mapping:
      description: content
      expectedResult: expected

# Zephyrのデフォルト値
defaults:
  priorityName: Normal
  statusName: Draft

Zephyrのどのフィールドに: TestRailのどのフィールドをマッピングさせるか を指定するのが基本です。

ただし、TestRail にも Zephyr にも繰り返し項目のようなデータがあります。このようなデータです。

    "custom_steps_separated": [
      {
        "content": "Access Settings page",
        "expected": "Settings page is displayed",
        "additional_info": "",
        "refs": ""
      },
      {
        "content": "Access Profile page",
        "expected": "Profile page is displayed",
        "additional_info": "",
        "refs": ""
      },
    ],

このようなデータをマッピングさせる場合は、mapping の中でさらに sourcemapping を指定します。

# この辺りの書き方で、繰り返し項目をマッピングします
    testSteps:
        source: custom_steps_separated
        mapping:
        description: content
        expectedResult: expected

defaults セクションで、Zephyrのフィールドにデフォルトで入れておきたい値を指定することもできます。

これらの情報をいきなり書けと言われても難しいと思うので、prepareステップではTestRailとZephyrのAPIを呼び出して、以下のような情報を取得して mapping.yaml と一緒にディレクトリに保存しています。

  • TestRailのテストケースの一覧(50件程度)
    • どのようなフィールドにどのような値が入っているかを確認できます
  • Zephyrのカスタムフィールドの一覧
    • Zephyrにどのようなフィールドがあるかを確認できます

実行することで以下のようなメッセージが出力され、次のステップに進むためのコマンドが表示されます。

📝 Next steps:
  1. Review the sample files in projects/1/
     - sample_testrail_cases.json
     - sample_zephyr_test_cases.json
  2. Edit projects/1/mapping.yaml based on the sample data
  3. Run the following command to transform the data:

     testrail-to-zephyr convert -p project1.yaml -m projects/1/mapping.yaml

2. convert ステップ

ここでは、prepareステップで作成してもらった mapping.yaml を元に、Zephyrにテストケースやディレクトリ(ファイル)を作るためのJSONファイルを生成します。

例えばこの時点では、TestRailのセクションの情報を元の構造を保ったまま、JSONデータとして出力します(中間成果物です)。

[
  {
    "testRailSectionId": 1,
    "testRailSectionName": "権限管理",
    "testRailParentId": null,
    "testRailDepth": 0,
    "zephyrFolderId": null // まだZephyrのフォルダは作っていないのでnull。作成された後にIDが入ります
  },
  {
    "testRailSectionId": 2,
    "testRailSectionName": "一般ユーザー",
    "testRailParentId": 1,
    "testRailDepth": 1,
    "zephyrFolderId": null // まだZephyrのフォルダは作っていないのでnull。作成された後にIDが入ります
  },
]

これらを元に、Zephyrのテストケースを作成する際に利用できるJSONファイルを生成します。

[
  {
    "testRailCaseId": 1,
    "testRailSectionId": 1,
    "zephyrRequest": {
      "projectKey": "PRJ1",
      "folderId": null,
      "priorityName": "Normal",
      "statusName": "Draft",
      "name": "Admin user can access Settings page",
      "precondition": "Admin user is logged in",
      "testSteps": [
        {
          "description": "Access Settings page",
          "expectedResult": "Settings page is displayed"
        },
        {
          "description": "Access other user's Profile page",
          "expectedResult": "Profile page is displayed"
        },
      ]
    },
    "zephyrTestCaseId": null,
    "zephyrTestCaseName": null
  }
]

このような中間成果物を生成することで、最後のmigrateステップで実際にデータを移行する前に、どのようなデータがZephyrに作成されるかを確認することができます。

また、もしこのツールにバグが見つかった場合でもこのJSONファイルを編集することで、どのような情報をZephyrに登録するかを柔軟に変更することができますし、「どんなデータが入るのだろう」という不安を減らすことにつながるかと思いました。

こちらも処理が終了すると以下のようなメッセージが出力され、次のステップに進むためのコマンドが表示されます。

📝 Next steps:
  1. Review the transformed data in artifacts/
     - testcase_requests.json contains Zephyr-formatted data
  2. Run the following command to create data in Zephyr:

     testrail-to-zephyr migrate -p project1.yaml

3. migrate ステップ

最後に、convertステップで作成したJSONファイルを元に、ZephyrのAPIを呼び出してデータを移行します。

このステップでは、ZephyrのAPIを順次呼び出していきます。

ただし、ZephyrにAPIリミットがあるのか、あまり多くのリクエストを送るとよくなさそうだったので、50件あたりに30秒と長めのインターバルを入れています。

試しに500件程度のテストケースを移行してみましたが、特に問題なく移行できました。

❯ testrail-to-zephyr migrate -p test-project.yaml
info: Starting migrate command...
info: Loading sections from TestRail...
info: Loaded 141 sections
info: Creating folders in Zephyr...
info: Created 141 folders in Zephyr
info: Saved section mappings to projects/1/artifacts/section_mapping.json
info: Loaded 515 test case requests
info: Creating test cases in Zephyr...
info: Progress: 50/515 test cases
info: Progress: 100/515 test cases
info: Progress: 150/515 test cases
info: Progress: 200/515 test cases
info: Progress: 250/515 test cases
info: Progress: 300/515 test cases
info: Progress: 350/515 test cases
info: Progress: 400/515 test cases
info: Progress: 450/515 test cases
info: Progress: 500/515 test cases
info: Progress: 515/515 test cases
info: Created 515/515 test cases in Zephyr
info: Saved test case mappings to projects/1/results/testcase_mapping.json

またこだわりポイントとして、最終的に以下のようなJSONで「TestRailのどのテストケースがZephyrのどのテストケースに対応しているか」を保存しています。

[
  {
    "testRailCaseId": 111,
    "testRailCaseName": "Admin user can access Settings page",
    "testRailSectionId": 1,
    "zephyrTestCaseId": "123",
    "zephyrTestCaseName": "PRJ1-T0001"
  }
]

これで追跡性を高めるだけでなく、例えば以下のようにテストの実行結果をTestRailに入れていた場合、Zephyrに移行した後に同じような仕組みで実行結果を移行することも可能になります。

// C12345 というTestRailのテストケースの実行結果を登録するための例
// マッピング情報があれば機械的に変換が可能です
test("C12345 Login with valid credentials should succeed", async ({ page }) => {
});

↓ npmパッケージの例です

https://www.npmjs.com/package/playwright-testrail-reporter

まとめ

  • 昨日作っていたZephyrのAPIクライアントを利用して、TestRailからZephyrに構造を保ったまま柔軟にデータ移行するツールを作成しました
  • 意図的に3ステップに分けて、ユーザーにどのようにデータをマッピングさせるかを決めてもらうようにしました
    • 特に最終成果物ではテストケースのIDのマッピング情報を保存するなど追跡性を高める工夫をしています
  • 2日連続で一つのツールに対するnpmパッケージを公開したのは初めてです

以上、最後までお読みいただきありがとうございました。

興味があったり、素敵だと感じたらぜひGitHubにスターをお願いします。

https://github.com/bun913/testrail-to-zephyr

GitHubで編集を提案
Money Forward Developers

Discussion