🥯

テスト進捗を自動投稿!QaseAPIとSlackを連携させる方法

2023/06/09に公開

こんにちは!スペースマーケットでQAエンジニアをしている柴山です。
今回は、前回の記事で紹介した「QaseAPIを使ったSlackへのテスト進捗自動投稿システム」を詳しく解説します。

開発の動機


Qaseでテストを実施するとき、自分は実施環境ごとにTestRunを作成しています。ここで各TestRunの進捗率は見れますが、プロジェクト全体の数値は把握できません。さらにはページの閲覧にアカウントが必要、能動的にページにアクセスする必要がある、といった問題も存在します。これらを解決するため、テスト進捗をSlackに自動投稿するツールを作成しました。

完成イメージ

テスト進捗は日報という形で毎営業日に定期実行するようにしました。
報告日、プロジェクト名、テスト全体の進捗率と各環境(TestRun)ごとの進捗率を記載しています。

構成


構成はこちらです。
QaseAPIでTestRun情報を取得し、それを整形してSlackに投稿するコードをLambda上に配置します。それをEventBridgeでスケジューリングすることで定期実行しています。

システム構築手順

さて、ここから早速システム構築手順についてです。
まずはQase APIやSlack Webhookを利用するための情報を取得する方法から書いていきます。

QaseAPIのセットアップ

APIトークン取得

QaseのAPIトークンページ にアクセスします。必要に応じてログインしてください。

API tokensページ

ここではトークンの取得と作成済みトークン一覧が確認できます。
[Create a new API token]をクリックし、モーダルにトークン名(今回はDemoAppとしました)を入力し、[Create]をクリック。
その後表示されるAPI tokenを大切に控えておきましょう。

ちなみに:QaseAPI リファレンスでAPIを試してみる

今回はTestRunの進捗率を取得するため、「Get all runs」APIを利用します。
先ほど取得したトークンを利用して、リファレンスからAPIを叩くことができます。少しだけ試してみましょう。
https://developers.qase.io/reference/get-runs

上記のように設定し、[Try It!]をクリック

RESPONSE

するとレスポンスデータが表示されました!
ちなみに、LANGUAGE欄で各言語を選択すると、それぞれのサンプルコードを参照することができます。気軽にツールに組み込めるのも嬉しいポイントです。

Slackのwebhook URLを取得

次に、Slackに投稿するためのwebhook URLを取得していきます。
まずSlackのWebhook作成ページにアクセスします。

自動投稿したいチャンネルを選択し、[Incoming Webhook インテグレーションの追加]をクリックします。

するとWebhook URLが取得できました。この情報も大切に控えておいてください。

また、このページではSlackに投稿するアプリのアイコンや名前、説明ラベルなどが設定できます。
今回は上記のように設定してみました。

Lambdaにコードを組み込む

QaseのAPIトークン、SlackのWebhook URLが用意できたら、いよいよLambdaにコードを書いていきます。

関数の新規作成


AWS Lambdaにアクセスし、関数の作成画面に遷移します。
任意の関数名(今回はqase-test-progress-zenn-sample)、ランタイム(今回はNode.js 18.x)、その他はデフォルト情報を入力して、「関数の作成」ボタンをクリック

これで関数は作成できました。ただし、コードを書く前にもう一つ作業が必要になります。Qase APIを呼び出すために必要なパッケージをインストールする作業です。
AWS Lambdaでライブラリを使用する場合は、ローカルでnpm installを行い、node_modulesを含めたプロジェクトを圧縮してアップロードする必要があるそうです。(他にやり方があればこっそり教えてください。あまりLambdaに詳しくないので。。。)
手順を以下に示します!

コード & パッケージの準備

ローカルで以下のディレクトリとファイルを作成します。
ディレクトリ構成はこちら

qase-test-progress-zenn-sample
┣index.js
┗package.json
index.js
import fetch from "node-fetch";

const QASE_PROJECT_ID = process.env.QASE_PROJECT_ID;
const QASE_PROJECT_NAME = process.env.QASE_PROJECT_NAME;
const QASE_API_TOKEN = process.env.QASE_API_TOKEN;
const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK;

// Qase APIをcallしTestRunsのステータスを取得する
// Get Test Runs : https://developers.qase.io/reference/get-runs
async function getTestRuns() {
  try {
    const url = `https://api.qase.io/v1/run/${QASE_PROJECT_ID}?limit=20&offset=0`;
    const headers = {
      accept: "application/json",
      Token: QASE_API_TOKEN,
    };
    const response = await fetch(url, {
      method: "GET",
      headers: headers,
    });

    if (!response.status) {
      throw new Error(`APIリクエストが失敗しました。${response.errorMessage}`);
    }

    const responseData = await response.json();
    return responseData;
  } catch (error) {
    console.log(error.message);
    throw error;
  }
}

// レスポンスを変換し日報テキストを作成する
function convertToSlackMessage (responseData) {
  // 本日の日付を生成
  const today = (function () {
    const currentDate = new Date();
    const year = currentDate.getFullYear();
    const month = currentDate.getMonth() + 1;
    const date = currentDate.getDate();
    const dayNum = currentDate.getDay();
    const weekday = ["日", "月", "火", "水", "木", "金", "土"];
    const day = weekday[dayNum];
  
    return `${year}/${month}/${date}(${day})`;
  })();

  const testRunList = responseData.result.entities;
  const messageList = testRunList.map((testRun) => {
    const {
      title,
      stats: { total, passed, skipped },
    } = testRun;
    const percent = Math.floor(((passed + skipped) / total) * 100);
    const completeFlg = percent == 100 ? " :tada:" : "";
    return `\t${title}${
      passed + skipped
    }/${total}項目(${percent}%)${completeFlg}`;
  });
  
  const {totalTestCount, totalTestRunCount} = testRunList.reduce((acc, testRun) => {
    const {
      stats: { total, passed, skipped },
    } = testRun;
    acc.totalTestCount += total;
    acc.totalTestRunCount += passed + skipped;
    return acc;
  }, {totalTestCount: 0, totalTestRunCount: 0});


  const totalTestPercent = Math.round(
    (totalTestRunCount / totalTestCount) * 100
  );

  const slackMessage = [
    `${today} ${QASE_PROJECT_NAME} テスト日報`,
    `*全体進捗率 ${totalTestRunCount}/${totalTestCount}項目(${totalTestPercent}%)*`,
    ...messageList,
  ].join("\n");
  
  return slackMessage;
  
}

// slack webhookを実行し日報を投稿する
async function sendSlackMessage(slackMessage) {
  try {
    const data = JSON.stringify({
      text: slackMessage,
    });
    const url = `https://hooks.slack.com/services/${SLACK_WEBHOOK}`;
    const headers = {
        "Content-Type" : "application/json",
      };
    const response = await fetch(url, {
      method: "POST",
      headers: headers,
      body: data
    });

    if (!response.status) {
      throw new Error(`APIリクエストが失敗しました。${response.errorMessage}`);
    }
  } catch (error) {
    console.log(error.message);
    throw error;  
  }
}

export const handler = async (event) => {
  try { 
    // 1. Qase APIをcallしTestRunsのステータスを取得する
    const responseData = await getTestRuns();
    // 2. レスポンスを変換し日報テキストを作成する
    const slackMessage = convertToSlackMessage(responseData);
    // 3. slack webhookを実行し日報を投稿する
    await sendSlackMessage(slackMessage);
  } catch (error){ 
    throw error;  

  }
};
package.json
{
  "name": "qase-test-progress-zenn-sample",
  "version": "1.0.0",
  "main": "index.js",
  "license": "ISC",
  "type": "module",
  "dependencies": {
    "node-fetch": "^3.3.1"
  }
}

次に、npm installしてパッケージをインストールします。
パッケージインストール後の状態は以下の通りです。
node_modulesディレクトリとpackage-lock.jsonファイルが生成されているはずです。

qase-test-progress-zenn-sample
┣node_modules
┣index.js
┣package-lock.json
┗package.json

最後に今回作成したプロジェクトをzip化しておきます。
これでパッケージ等準備は完了しました。

AWS Lambdaへのアップロード

ここからはzip化したファイルをLambdaにアップロードしていきます。


AWS Lambdaの画面を開きましょう。右上のアップロード元をクリックして、.zipファイルを選択します。


そして先ほど作成した.zipファイルを選択し、保存をクリック

こちらでファイルをアップロードできました!
この後、ファイルを更新した場合は[deploy]ボタンのクリックを忘れずに。変更が反映されません。

環境変数の定義

次にコード中で使用する環境変数をLambda上で設定していきます。

Lambdaの設定タブから環境変数を開きます。そして上記のキーを設定します。
これでLambdaでの設定は完了です!
ちなみに[test]ボタンをクリックすることで、進捗報告ツールの手動実行も可能です。

EventBridgeで定期実行の設定

今度はLambdaで作成した関数を定期実行するためにEventBridgeで設定を行っていきます。

AWS EventBridgeにアクセスし、 仕様を開始するセクション以下、イベントブリッジルールを選択し、「ルールを作成」ボタンをクリックします。

任意のスケジュール名(今回はqase-test-progress-zenn-sample)を指定して、ルールタイプ > スケジュールを選択。[続行してルールを作成する]をクリックします。

次に定期実行のスケジュールを設定します。
今回は月曜から金曜の17時に投稿したいです。なので、cron式は以下の通りになります。

cron(0 8 ? * MON-FRI * )

設定が完了したら [次へ] をクリック。

次に定期実行のターゲットを画像のように設定します。
画面下の[レビューと作成にスキップ] ボタンをクリックします。

すると作成するEventBridgeの設定が確認できます。問題なければ[ルールの作成]をクリックしてください。
これでLambdaとEventBridgeの紐付けが完了しました。

というわけで完成!


実行時刻を待ち、Slackに投稿されたことを確認したらOKです。
お疲れ様でした!

まとめ

さて、今回はQase APIを活用したテスト進捗自動投稿システムをご紹介しました。
本当は日報に加えたい情報が他にもありましたが、システムの複雑さを避けるため一旦見送りとなりました。追加機能の検討もいつかしたいですね!

Qaseには本当に多種多様なAPIが用意されているので、今回のような進捗報告ツールはもちろんのこと、スプレッドシートのテスト項目をQaseに変換する、といったことも可能になります。
その辺りも実装したら記事にして紹介したいと思います!久々にちゃんとコードを書いて楽しかった〜
それではまた!

スペースマーケット Engineer Blog

Discussion