QualityForwardとGoogleスプレッドシートを使って、テスト結果を細かく分析する

[QualityForwardはクラウドベースのテスト管理サービス](https://bit.ly/2Uvxt7V)です。テストを設計し、各担当者がテスト結果を入力していきます。それによって、決められているテストを一つずつ、適切に管理、運用できるようになります。

問題はその次の工程です。つまり、テスト結果を分析し、品質に問題がないかを把握しなければいけません。今回はその一例をGoogleスプレッドシートを用いて作成してみました。

## 作成したグラフ

グラフは次のようになります。

<img width="1391" alt="Screenshot_ 2020-03-10 12.48.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/d27d2465-05b0-5201-04eb-fbb33b2ab22e.png">

このグラフを用いることで、以下の情報が分かります。

- テストが決められた期日までに完了するかどうか
- テスト結果ごと（通過、失敗、スキップなど）がどう積み上がっているか

## コードの説明

ここからコードの説明です。

### 必要な情報について

まず、測定するプロジェクトに関して情報をまとめます。

- APIキー：QualityForwardのAPIキーです。プロジェクトごとに異なります。
- テストフェーズID
- テストスイートアサインメントID
- テストサイクルID

下の3つのIDは、QualityForwardのテスト結果入力画面で確認できます。例えばURLは次のようになっています。

```
https://cloud.veriserve.co.jp/projects/748/test_phases/3328/test_suite_assignments/16492/test_cycles/28451
```

この時、

- テストフェーズID = 3328
- テストスイートアサインメントID = 16492
- テストサイクルID = 28451

になります。

### 祝日データについて

週末の土日、祝日はテストが行われないこととしています。そのため、必要なデータを [google spread sheetに自動更新される日本の祝日シートを作る - Qiita](https://qiita.com/ik-fib/items/6c35640954c2b04a9287) をベースにして取得、休祭日シートに記録しています。このリンク先では祝日のみなので、土日も追加するようにしています。

```js
function getHoliday(startDate, endDate) {
  var cal = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");

  var holidays = cal.getEvents(startDate, endDate);
  var values = [];

  for(var i = 0; i < holidays.length; i++) {
    values.push([holidays[i].getStartTime(), holidays[i].getTitle()]);
  }
  
  // 改変部分
  let d;
  d = startDate;
  while (d <= endDate) {
    if ([0, 6].indexOf(d.getDay()) > -1) {
      values.push([new Date(d.getTime()), "休日"]);
    }
    Logger.log(d);
    d.setDate(d.getDate() + 1);
  }
  values.sort((a, b) => {
    return a[0] > b[0] ? 1 : -1;
  });
  return values;
}
```

### テスト結果の取得

テスト結果を取得する際には、QualityForward APIを使います。また、Google Apps Script向けにはSDKがあります（非公式）ので、プロジェクトIDとして `1ppRPLjuClG0MhtnXYbskdZ8uYGbyCFHv7MFhr0GYa-3IAKEh8B7lmTMb` を指定して取り込んでください。以下はデフォルトの `QualityForward` として取り込んだ場合の書き方です。

```js
// 上記の必要な情報はDataシートにまとめています
var testPhaseId = sheet.getRange(2, 2).getValue();;
var testSuiteAssignmentId = sheet.getRange(3, 2).getValue();;
var testCycleId = sheet.getRange(4, 2).getValue();;

// テストフェーズの取得
var testPhase = qf.getTestPhases().filter(t => t.id === testPhaseId)[0];
// テストスイートアサインメントの取得
var testSuiteAssignment = testPhase.test_suite_assignments.filter(t => t.id === testSuiteAssignmentId)[0];
// テストサイクルの取得
var testCycle = testSuiteAssignment.getTestCycles().filter(t => t.id === testCycleId)[0];
// テスト結果の取得
var results = testCycle.getTestResults();
```

### 日付ごと、テスト結果ごとにまとめる

次にこの `results` を日付ごと、テスト結果ごとにまとめます。

```js
var res = {};
for (let l in results) {
  const testResult = results[l];
  const d = testResult.executed_at;
  const date = `${d.getFullYear()}/${(d.getMonth() + 1)}/${d.getDate()}`;
  if (!res[date]) res[date] = {};
  if (!res[date][testResult.result]) res[date][testResult.result] = 0;
  res[date][testResult.result]++;
}
```

### 日付ごとに記録する

そして日付ごとに出力します。テストの開始日、終了日はテストサイクルの `start_on` / `end_on` で取得できます。また、全タスク数は `target_test_case_no_list` の要素数で分かります。この日数や全タスク数を表に記録します。

```js
let d = new Date(testCycle.start_on);
const endDate = new Date(testCycle.end_on);
let lastRow = 2;

// 全タスク数
sheet.getRange(5, 2).setValue(testCycle.target_test_case_no_list.length);
// 日数
let dateCount = parseInt((endDate - d) / 86400000);

while (d <= endDate) {
  // スプレッドシートに記録する処理
  
  // 日付を一日更新
  d.setDate(d.getDate() + 1);
  // 結果を出力する行も更新
  lastRow++;
}
```

#### 出力する内容について

出力する内容は非常に分かりづらい上にコード量が増えがちなので一部だけ紹介します。

```js
if (!res[date]) res[date] = {};
resultSheet.getRange(lastRow, 2).setValue(res[date].pass || 0);
resultSheet.getRange(lastRow, 3).setValue(res[date].fail || 0);
resultSheet.getRange(lastRow, 4).setValue(res[date].skip || 0);
resultSheet.getRange(lastRow, 5).setValue(res[date].cut || 0);
resultSheet.getRange(lastRow, 6).setValue(res[date].block || 0);
resultSheet.getRange(lastRow, 7).setValue(res[date].na || 0);
resultSheet.getRange(lastRow, 8).setValue(res[date].qa || 0);      
// Fomula
resultSheet.getRange(lastRow, 9).setValue(`=IFERROR(VLOOKUP(A${lastRow},'休祭日'!A:C, 3, false), "")`);
resultSheet.getRange(lastRow, 10).setValue(`=SUM(B${lastRow}:H${lastRow})`);
```

このようにして、各行ごとに必要な情報を出力します。

## まとめ

全体のコードは[QualityForwardとGoogleスプレッドシートでテスト結果を可視化するサンプルコード](https://gist.github.com/goofmint/98217f4106b6912bde141a1c7eb24b2e)にて公開しています。実装時の参考にしてください。

テストはただ記録するだけでは、その魅力を半分も引き出せていないでしょう。可視化、分析して、より品質の高い製品を短い期間で生み出す改善につなげてください。

[QualityForward](https://bit.ly/2Uvxt7V)