QualityForward Blog

ベリサーブのテストマネジメントクラウド、QualityForward の最新情報、ちょっとした使い方のTipsなどをお届けいたします

【導入事例の紹介】 QualityForwardで手動テストと自動テストを一元管理しよう <中編>

はじめに:QF連携の実現方法詳細

この記事は「QualityForwardで手動テストと自動テストの結果を一元管理しよう」という全3回のシリーズ記事の第2回目、<中編>になります。

<前編>では手動テストと自動テストを一元管理するメリットと、実現方法の大枠(業務フローとアーキテクチャ)について解説しました。

<中編>ではQFの連携に必要なテストスイート等の設計と、APIリクエストの使用方法を含めた連携スクリプトの実装の詳細について解説していきます。

なおGitHub上にてサンプルスクリプトを公開しています。こちらも是非ご参照ください。

もくじ

業務フロー(再掲)

前編でご紹介したとおり、自動テストをテスト管理ツール(QF)に連携するには以下のようなフローが必要になります。

  1. テスト管理ツール上で自動テストを格納するチケット/列などを定義する
  2. 自動テストを実行する
  3. 自動テスト結果をテスト管理ツールに連携する
  4. テスト管理ツール上で自動テスト結果を確認する

ここで連携スクリプトの実装、つまり3を行う前に、1のテスト管理ツール側での準備が必要になります。

QF上でのテストスイート・テストフェーズの設計

テスト管理ツール側での準備にあたる行為として、 QFではテストスイートとテストフェーズの設計(作成)を行う必要があります。

テストスイート

テストスイートとはテストケース群のことで、今回は一元管理のため、手動テストと自動テストが混在した1つのテストスイートを作成することになります。 この際、以下の3点の設計を行うことが必要になります。

  1. 「テストケースの識別子」の設計
  2. 「テスト優先度」列の設計
  3. 「テスト結果」列の設計

「テストケースの識別子」の設計

QF上のテストスイートに自動テストの実行結果を投入するには、 連携スクリプト上で実行結果から投入すべきQFのテストケース列を特定できる必要があります。 この際に用いる"テストケース列特定のための情報"を「テストケースの識別子」とここでは呼称します。 テストスイートを作成する段階で、このテストケースの識別子を設計し、テストスイートに記載しておく必要があります。

実行系を問わず、実行結果には必ずテストメソッド名が含まれます。 このため、テストメソッド名の全体、あるいはその一部を識別子とするのがよいでしょう。

f:id:qf_support:20210428135222p:plain
テストメソッド名全体をテストケースの識別子とした例

「テスト優先度」の設計

QFには「テストケースに"優先度"列を設定することで、各テストサイクルで集計する対象テストケースを分ける」という機能があります。 これを活用すると同一のテストスイート上で、「手動テストのみを集計対象としたテストサイクル」と「自動テストのみを集計対象としたテストサイクル」を作ることができます。

一例として、以下のような優先度付けが考えられるでしょう。*1

  • A : 完成した自動テストケース
  • B : 完成した手動テストケース
  • C : 手順が確定していない手動テストケース/未実装の自動テストケース

なお、この定義は本来の「優先度」列が意味する「Priority」とは意味合いが異なり、「テストケースの種類・状態(手動か自動か/完成か未完成か)」を表現していることに注意してください。

「Priority」を定義したい場合は、他の列に別途記載をするか、Priorityとテストケースの種類・状態を組み合わせた形で優先度を設計する必要があります。

「テスト結果」列の設計

最後にテスト結果列のフォーマットを定義しましょう。 テスト結果列は対象テストスイートの「設定」より編集できます。

標準的な自動テスト実行結果は下記の要素を含むため、そのそれぞれを格納する列を用意するとよいでしょう。

  • QFデフォルトで必須の列(定義不要)
    • テスト結果(Pass / Fail / Skipped)
    • テスト実行者(自動テスト作成者のIDで可)
  • 別途結果列として定義が必要なパラメータ
    • テストメソッドが属するファイルパス(ないしクラス名)
    • テスト実行時間
    • エラーメッセージ

なお、エラーメッセージに関しては、全体をQF上に格納するとテスト結果の視認性が低下するため、以下のようにするとよいと思います。

  1. エラーメッセージの一部だけを格納する
  2. 専用の自動テストレポートフレームワークを用意し、QFからリンクを張る

テストフェーズ

テストスイートの定義が完了したら、そのテストスイートを紐付ける形でテストフェーズを作成してください。

フェーズ終了日は長めにとっておき、テストスイートが更新された段階で別のテストフェーズにするとよいでしょう。

テストフェーズが作成できたらQF上での準備は完了です。

QF連携スクリプトの設計と実装

QF連携スクリプトは下記の順で実行されます。 サンプルスクリプトで実装を確認しながら解説を読んでいただくとよいかと思います。

  1. テストサイクルの作成
  2. テスト実行結果の取得
  3. 実行結果のパース
  4. QF上のテストケースとテスト結果のマッチング
  5. テスト結果のQFへの格納

テストサイクルの作成

ここからはQF連携スクリプトの内部実装の解説をしていきます。

まずは自動テスト実行結果を投入するためのテストサイクルを作成する必要があります。

テストサイクルの作成に使うのは以下のAPIリクエストです。

POST /api/v2/test_phases/:test_phase_id/test_suite_assignments/:test_suite_assignment_id/test_cycles.json

パス・クエリストリング

パス上で指定するパラメータは以下の2つです。

  1. test_phase_id
  2. test_suite_assignment_id

この2つのパラメータを確認するには、QF上のテストスイートの「テストサイクル一覧」ページのパスを見るのが最も簡単です。 QFにログインしたあと、左サイドバーから「テストフェーズ」を選択し、下準備2で作成したテストフェーズの「スイート一覧」>「サイクル一覧」より確認できます。

f:id:qf_support:20210526135339p:plain

またパスの後にクエリストリングの形でAPIキーを指定します。 APIキーはQFにログインしたあと、「ダッシュボード」>右上の「設定」から生成することができます。

パス・クエリストリングを統合したURLは以下のような形式になります。 https://cloud.veriserve.co.jp/api/v2/test_phases/0000/test_suite_assignments/1111/test_cycles?api_key=YOUR_API_KEY

リクエストヘッダ

{"Content-Type": "application/x-www-form-urlencoded"}を指定してください。

リクエストボディ

リクエストボディとして最低限必要なパラメータは以下になります。

  • "test_cycle[name]"
    • 任意の文字列。
    • 同名のテストサイクルが複数作成されると視認性が落ちるため、日時など適当な変数を付与するとよい。
  • "test_cycle[target_priorities]"
    • テストサイクルで集計対象とするテストケースの優先度。
  • "test_cycle[start_on]"
    • テスト実行開始した日付。
  • "test_cycle[end_on]"
    • テスト実行終了した日付。
  • "test_cycle[status]"
    • テストサイクルの状態。"unexecuted"(未実行)/"in_progress"(進行中)/"waiting_for_review"(レビュー待ち)/"complete"(完了)のいずれかをとる。
      • 自動テスト実行後にテスト管理者の確認を入れるという運用では"waiting_for_review"(レビュー待ち)を設定するとよい。

テスト実行結果の取得

テスト実行結果の取得方法にはJUnit形式のxmlレポートでの取得や、APIリクエストによる取得などがあります。

サンプルスクリプトではJUnit形式のxmlレポートを使用しています。 JUnit形式のxmlレポートのフォーマットに関してはDevelopersIOさんの下記の記事が詳しいです。 dev.classmethod.jp

実行結果のパース

パースの実現方法には自分で正規表現等を使う方法と、既存のライブラリを使う方法があり、どちらでも実現が可能です。 前者はカスタマイズ性が高く、後者は手軽に実装ができます。

サンプルスクリプトでは後者の方法で、"junitparser"というOSSライブラリを使用しました。 具体的な記法・用法はライブラリ公式ドキュメントに譲ります。 pypi.org

QF上のテストケースとテスト結果のマッチング

APIリクエストを送る前に、それぞれのテスト結果がQF上のどのテストケース列に相当するかマッチングをする必要があります。 [「テストケースの識別子」の設計]でテストスイート上に識別子列を既に定義しているので、下記の模擬コードで表現される処理によりマッチングの実現ができます。

API GET <QFテストスイート>

for each <自動テスト実行結果>:
  for each <QFテストケース>:
    if <自動テスト実行結果中のテストメソッド名> in <QFテストケース中の識別子列>:
      return <QFテストケース番号>  # マッチ

サンプルスクリプトでは、api.py中のメソッドget_test_case_no_from_idがこのマッチング処理に相当します。

テスト結果のQFへの格納

テスト結果の格納に使うのは以下のAPIリクエストです。

POST /api/v2/test_phases/:test_phase_id/test_suite_assignments/:test_suite_assignment_id/test_cycles/:test_cycle_id/test_results.json

パス・クエリストリング

パス上で指定するパラメータは以下の3つです。

  1. test_phase_id
  2. test_suite_assignment_id
  3. test_cycle_id

1, 2はテストサイクル作成時と共通です。 3はテストサイクル作成時に返却される値を使用すれば問題ありません。

またクエリストリングにはテストサイクル作成時と同じAPIキーを指定してください。

パス・クエリストリングを統合したURLは以下のような形式になります。 "https://cloud.veriserve.co.jp/api/v2/test_phases/0000/test_suite_assignments/1111/test_cycles?api_key=YOUR_API_KEY"

リクエストヘッダ

{"Content-Type": "application/x-www-form-urlencoded"}を指定してください。

リクエストボディ

リクエストボディとして最低限必要なパラメータは以下になります。

  • "test_result[test_case_no]"
    • 結果を格納するテストケースの番号。
    • マッチングにより取得
  • "test_result[result]"
    • テスト結果(Pass / Fail / Skipped / Error)
  • "test_result[user_id]"
    • テスト実行者のユーザID
  • "test_result[executed_at]"
    • テストの実行日時

更に、「テスト結果列」の設計で定義したフォーマットに対するパラメータを追加してください。 項目1は"test_result[content1]"、項目2は"test_result[content2]"というキーになります。

  • テストメソッドが属するファイルパス(ないしクラス名)
  • テスト実行時間
  • エラーメッセージ

リクエスト時の制約

QFのAPIリクエストは1秒に1回の制限があるため、複数回のループ処理を実行する結果格納処理のような処理を行う際には time.sleep(1)のようなwait処理を挿入するようにしてください。

おわりに

以上でQF連携の実現方法詳細の解説は終わります。 <後編>では自動テストSaaSとQFの連携についてご紹介します。お楽しみに!

*1:ちなみにこの優先度列の設計方法は私自身が思いついたものではなく、お客様よりアイデアをいただいたものになります。この場を借りてお礼申し上げます。ありがとうございます!