Gaugeで画面の自動テストをMarkdownで書いて実行してみる


## Gaugeとは
https://gauge.org/

E2Eテストと呼ばれるようなブラウザ操作による画面の動きがシステム全体を通して正しく動作しているかどうかをチェックするために、rubyやjavascriptなど幅広い言語を利用し、実装と仕様書を分離したテスト自動化フレームワークです。

turnipとかcucumberみたいなものですね。

## 準備

だいたいはドキュメントの流れの通りに設定していきます。VS Codeを使うのが便利そうなので選択しています。

https://docs.gauge.org/getting_started/installing-gauge.html?os=macos&language=javascript&ide=vscode

### Gaugeインストール

```bash
$ curl -SsL https://downloads.gauge.org/stable | sh
or
$ brew install gauge
```

rubyを利用する場合以下の通り。他の言語を利用する場合はそれぞれインストールしておきます。

```bash
$ gauge install ruby
$ gauge init ruby
```



Webアプリの場合、画面操作やDOMの操作のことを考えるとjsで記述するのがいいのかなという感じです。

```bash
$ mkdir example-test
$ cd example-test
$ gauge install js
$ gauge init js
```

```bash
$ gauge --version
Gauge version: 1.4.2
Plugins
-------
html-report (4.1.2)
js (2.4.0)
ruby (0.5.4)
screenshot (0.1.0)
```

### スペックを書く

テストするためのスペック（仕様書）を書いていきます。Markdown形式で記述します。

vim specs/search.spec

```md
# 検索機能のテスト

## ケーキを検索して成功する場合
* トップページにアクセスする
* 検索フォームに"けーき"を入力して検索
* 画面に"ケーキ"が表示されること

## 焼き肉を検索して成功する場合
* トップページにアクセスする
* 検索フォームに"やきにく"を入力して検索
* 画面に"焼肉"が表示されること

## DEPARTUREを検索して失敗する場合
* トップページにアクセスする
* 検索フォームに"DPTR"を入力して検索
* 画面に"DPTP"が表示されること
```

### ステップを書く

実際に動作を確認するためのステップ（実装）を書いていきます。

test/step_implementation.js

```js
/* globals gauge*/
"use strict";
const path = require('path');
const {
    openBrowser,
    write,
    closeBrowser,
    goto,
    press,
    screenshot,
    above,
    click,
    checkBox,
    listItem,
    toLeftOf,
    link,
    text,
    into,
    textBox,
    evaluate
} = require('taiko');
const assert = require("assert");
const headless = process.env.headless_chrome.toLowerCase() === 'true';

beforeSuite(async () => {
    await openBrowser({
        headless: headless
    })
});

afterSuite(async () => {
    await closeBrowser();
});

// Return a screenshot file name
gauge.customScreenshotWriter = async function () {
    const screenshotFilePath = path.join(process.env['gauge_screenshots_dir'],
        `screenshot-${process.hrtime.bigint()}.png`);

    await screenshot({
        path: screenshotFilePath
    });
    return path.basename(screenshotFilePath);
};

step('トップページにアクセスする', async () => {
    await goto('google.co.jp')
})

step('検索フォームに<item>を入力して検索', async (item) => {
    await write(item)
    await press('Enter')
})

step("画面に<message>が表示されること", async (message) => {
    assert.ok(await text(message).exists(0, 0));
});
```

### テストの実行

```
$ gauge run specs/
# 検索機能のテスト
  ## ケーキを検索して成功するケース				✔ ✔ ✔
  ## 焼き肉を検索して成功するケース				✔ ✔ ✔
  ## DEPARTUREを検索して失敗する場合			✔ ✔ ✘
        Failed Step: 画面に"DPTP"が表示されること
        Specification: specs/search.spec:16
        Error Message: AssertionError [ERR_ASSERTION]: false == true
        Stacktrace: 
        AssertionError [ERR_ASSERTION]: false == true
            at Object.<anonymous> (tests/step_implementation.js:56:12)
```

もしくはVS Code上のRun SpecをクリックしてもOK

## 所感

実行結果のレポートがきれいに出力されていました。みやすくできているので提出するにもいいと感じました。
`$ open reports/html-report/index.html`

またテストするための仕様と実装をわけて作業できるので、エクセルやワードなどで仕様書をもらうよりも、誰でもかけて読むことのできるMarkdownで記述していけるのはよいところです。

turnipもGherkinで記述できるのですが、ドキュメントとしてプレビューする場合、やはりMarkdownになっているのは大きな違いです。言語やシステム的なことがわからなくても仕様書の記述を依頼しやすいですね。

大規模なシステムのテスト実行速度や、スクリーンショットの差分検知など、検証する部分はあると思いますが、現状導入のしやすさや実行のしやすさ、レポートの見やすさなどを考慮するとツールの選択肢としてはアリなんじゃないかなと。