Gaugeでテストを実施する

## はじめに
はじめまして、河村康治です。HITOTSUアドベントカレンダーの18日目を担当します！！
普段はバックエンドを主に担当しているのですが、テスト基盤構築に力をいれて行こうと思い、今回のアドベントカレンダーではフロントのテストに関して記載して行こうと思います！！！
今回は、Gauge×Playwrightを活用したE2Eテストの記事を書いて行きます！！ちなみに、今回はPlaywrightの事は深く触れていないので、興味のある方は[リンク](https://qiita.com/kouji0705/items/cfc48165d818c637568f)を確認ください。

https://qiita.com/koji0705/items/cfc48165d818c637568f

## Gaugeとは？？
Webシステムの自動テストライブラリです。JS、C#、Java、Python、Rubyでテストコードが記載し、ブラウザ操作を自動でする事でテストの自動化に役立っております。最大の特徴はテストケースをMarkDown形式で記載でき、検証の目的やPointをコードと一緒に記載する事ができるため、保守開発がしやすい事です。

![スクリーンショット 2022-12-13 12.27.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/a404147b-bd18-4520-2597-e30a159e0491.png)

![スクリーンショット 2022-12-13 12.35.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/19c964f7-398c-5d08-5838-ea97a3f5fbdb.png)

https://gauge.org/

## Gauge vs Playwright
Webシステムのリグレッションテストや受入テストで利用される両者はしばしば比較されます。[リンク](https://www.saashub.com/compare-playwright-vs-gauge)先を例に見てみますが、どの項目を取ってもPlaywrightが圧勝してる事がわかります。個人的な見解ですが、Gaugeが優れていないというよりも、Playwrightの機能網羅やUXの磨き込みがすごい。さすが、Microsoft開発のテストツールだなという感じです。
![スクリーンショット 2022-12-13 12.38.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/61005971-aa6d-e5d4-44a8-3f731a7a1044.png)

## Playwrightでよくない？？Gauge必要？？
Playwrightが優れているのであれば、Playwrightでよくない？？Gaugeは不要では？というのが当然の疑問として挙がってきます。ここで、生きてくるのがGaugeの特徴であるTestケースをMarkdownで書ける事です。
テストコードを後から見返した場合に、あれ？これって結局何の要件で何のテストしてたんだっけ？という事は意外とあるある。業務要件や経緯はコードに書いてないため、テストケース設計時のExcelやスプレッドシートを参考にするわけです。ただテストコードはメンテナンスしたが、Excelやスプレッドシートはメンテナンスしておらず、結局何を信じればいいのかわからず、途方に暮れる。。。業務要件とコードは纏めて管理できる方がメンテナンスしやすい。そこで、考えたのが、Gaugeで要件管理、Playwrightでブラウザ操作をする結論に至りました。

## Gauge
Gaugeのインストールが必要となります。コマンドもしくはVscodeからインストールする事が可能です。
<details><summary>Gaugeのインストール</summary><div>

[リンク](https://docs.gauge.org/getting_started/installing-gauge.html?os=macos&language=javascript&ide=vscode)先にインストール方法が記載されています。これを元にinstallしていただければOKです。ちなみに、Macであれば`brew`コマンドでinstallすれば早いです！！

```ts:Gaugeの準備
$ brew install gauge
# gaugeのバージョンが見られればOK
~/develop/react$ gauge -v
Gauge version: 1.4.3
Plugins
-------
html-report (4.1.4)
screenshot (0.1.0)
ts (0.1.0)
```
</div></details>

```shell:Gaugeプロジェクトの作成(Typescriptのテンプレート)
~/develop/gauge$ gauge init ts
Initializing template from https://github.com/getgauge/template-ts/releases/latest/download/ts.zip
.
Copying Gauge template ts to current directory ...
npm WARN deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead

added 401 packages, and audited 402 packages in 3m

128 packages are looking for funding
  run `npm fund` for details

5 vulnerabilities (4 moderate, 1 critical)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
Successfully initialized the project. Run specifications with "gauge run specs/".
```

```
~/develop/gauge$ yarn
~/develop/gauge_ts$ yarn add gauge-ts
```
※注意：gauge-tsはプロジェクト作成時、インストールされないです。

### Gaugeのクイックスタートを実行する。
`gauge run`で実行し、ブラウザ上で下記の様な画面が操作されていればOKです！！
![スクリーンショット 2022-12-13 20.31.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/af9bcc79-f3c7-c041-d844-5485d9e3640a.png)
![スクリーンショット 2022-12-13 20.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/042bbd5b-b1e5-32c5-c3d4-0fb23c7fe3cb.png)

```shell:gaugeの実行結果
~/develop/gauge_ts$ gauge run
# Getting Started with Gauge
  ## Display number of items     ✔ ✔ ✔ ✔ ✔ ✔
  ## Must list only active tasks         ✔ ✔ ✔ ✔ ✔ ✔ ✔

Successfully generated html-report to => /Users/kouji/develop/gauge_ts/reports/html-report/index.html

Specifications: 1 executed      1 passed        0 failed        0 skipped
Scenarios:      2 executed      2 passed        0 failed        0 skipped

Total time taken: 17.212s
```

## ソースコードの解説
Gaugeの仕組みを少し解説していきます。

```shell:ディレクトリ構成
~/develop/gauge/gauge_test/gauge_ts$ tree -I node_modules
.
├── env
│   └── default
│       ├── default.properties
│       └── ts.properties
├── logs
│   ├── gauge.log
│   └── lsp.log
├── manifest.json
├── metadata.json
├── package.json
├── specs
│   └── example.spec　　←テストケース
├── tests
│   └── StepImplementation.ts　←テストコード
├── tsconfig.json
└── yarn.lock

5 directories, 11 files
```
ディレクトリ構成は上記の様になっておりますが、意識すべきは、`example.spec`と`StepImplementation.ts`です。

### specファイル(example.spec)
```markdown:example.spec
# Getting Started with Gauge

This is an example markdown specification file.
Every heading in this file is a scenario.
Every bulleted point is a step.

To execute this specification, use
	gauge run specs

This is a context step that runs before every scenario
* Open todo application

## Display number of items
* Add task "first task"
* Must display "1 item left"
* Add task "second task"
* Must display "2 items left"

## Must list only active tasks
* Add tasks 

   |description|
   |-----------|
   |first task |
   |second task|
   |third task |
   |fourth task|
   |fifth task |

* Complete tasks 

   |description|
   |-----------|
   |second task|
   |fifth task |
* View "Active" tasks
* Must have 

   |description|
   |-----------|
   |first task |
   |third task |
   |fourth task|
* Must not have 

   |description|
   |-----------|
   |second task|
   |fifth task |

A tear down step for every scenario
___
* Clear all tasks
```

MarkDown形式で記載され、「*」や「#」はシステム的に意味のあるコード、それ以外はコメントアウトと同様の扱いとなります。わかりやすい様に一部抜粋の上、行数を振ると、1行目、１０行目のみが意味のあるコードとなります。
逆に言えば、他の内容はコメントアウトになるため、業務要件やシステム要件、経緯などを残す事ができます。

```markdown:specファイルの一部抜粋
1 # Getting Started with Gauge
2
3 This is an example markdown specification file.
4 Every heading in this file is a scenario.
5 Every bulleted point is a step.
6 
7 To execute this specification, use
8 	gauge run specs

9 This is a context step that runs before every scenario
10 * Open todo application
```

### テストコード(StepImplementation.ts)
```ts:StepImplementation.ts

import { Step, Table, BeforeSuite, AfterSuite } from "gauge-ts";
import { strictEqual } from 'assert';
import { checkBox, click, closeBrowser, evaluate, goto, into, link, openBrowser, press, text, textBox, toLeftOf, write } from 'taiko';
import assert = require("assert");

export default class StepImplementation {
    @BeforeSuite()
    public async beforeSuite() {
        await openBrowser({ headless: false });
    }

    @AfterSuite()
    public async afterSuite() {
        await closeBrowser();
    };

    @Step("Open todo application")
    public async openTodo() {
        await goto("todo.taiko.dev");
    }

    @Step("Add task <item>")
    public async addTask(item: string) {
        await write(item, into(textBox({
            class: "new-todo"
        })));
        await press('Enter');
    }

    @Step("Must display <message>")
    public async checkDisplay(message: string) {
        assert.ok(await text(message).exists(0, 0));
    }

    @Step("Add tasks <table>")
    public async addTasks(table: Table) {
        for (var row of table.getTableRows()) {
            await write(row.getCell("description"));
            await press('Enter');
        }
    }

    @Step("Complete tasks <table>")
    public async completeTasks(table: Table) {
        for (var row of table.getTableRows()) {
            await click(checkBox(toLeftOf(row.getCell("description"))));
        }
    }

    @Step("View <type> tasks")
    public async viewTasks(type: string) {
        await click(link(type));
    }

    @Step("Must have <table>")
    public async mustHave(table: Table) {
        for (var row of table.getTableRows()) {
            assert.ok(await text(row.getCell("description")).exists());
        }
    }

    @Step("Must not have <table>")
    public async mustNotHave(table: Table) {
        for (var row of table.getTableRows()) {
            assert.ok(!await text(row.getCell("description")).exists(0, 0));
        }
    }

    @Step("Clear all tasks")
    public async clearAllTasks() {
        // @ts-ignore
        await evaluate(() => localStorage.clear());
    }

}
```
Markdownで記載したspecファイルをコードに落とし込む作業です。`@Step`に着目し、`Open todo application`や`Add task <item>`が、Markdownの内容と紐付き、コードが実行されます。引数の受け渡しも`<item>`や`<table>`でMarkdown→tsへの受け渡しが可能です。
![スクリーンショット 2022-12-13 21.01.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/992b99ab-0b95-2d79-7c89-9509dd02aef2.png)

### まとめ
GaugeはMarkdown形式で記載できるテストライブラリです。今回の記事でGauge×Playwrightでのシナリオテストまで記載するつもりでしたが、記事の量が増えたため、次回の記事に回したいと思います。