Web UIとWeb APIとCLIをまとめてKarateでテストする

# Karate とは？

Gherkin記法で記載するテストフレームワークです。
元々はWeb APIのテストフレームワークでしたが、いつのまにかブラウザ操作や画像データを利用したGUIのテスト、さらにコマンドラインも実行できるようになっていました。

そこで、Karateを使ってブラウザやAPI、CLIツールを使ったRedmineのテストをしてみます。
以下をKarateで操作します。

1. `Chrome`で、Redmine にログイン
1. `Chrome`で、設定ページから「RESTによるWebサービス」を有効化
1. `Chrome`で、個人設定のページを開きAPIアクセスキーを取得
1. `REST API`で、取得したAPIアクセスキーをつかって、チケットを作成
1. Redmineの`コマンドラインツール`で、作成したissueを確認


実際のテストコードは以下になります。シンプルに可読性よくかけます。
雰囲気で何をやっているか読み取れると思います。


```gherkin
Feature: RedmineでKarateを試してみる
  Background:
    * configure driver = { type: 'chromedriver', showDriverLog: true }

  Scenario: 
    # Redmineにログイン  (ブラウザ)
    Given driver redmine.url + '/login'
    And input('#username', redmine.admin.user)
    And input('#password', redmine.admin.pass)
    When submit().click("input[name=login]")
    Then waitForUrl(redmine.url)

    # REST APIを有効化 (ブラウザ)
    Given driver redmine.url + '/settings'
    And click('#tab-api')
    And click('#settings_rest_api_enabled')
    When submit().click('#tab-content-api input[name=commit]')
    Then waitForText('#flash_notice', '更新しました' )
    * screenshot()
    
    # APIアクセスキーを取得 (ブラウザ)
    Given driver redmine.url + '/my/account'
    When click('{a}表示')
    Then screenshot()
    * def api_key = text('#api-access-key')

    # issueを作成  (REST API)
    Given url redmine.url
    And path '/issues.json'
    And param key = api_key
    And request
    """
    { 
      issue: {
        project_id: 'test',
        tracker_id: 1,
        status_id: 1,
        priority_id:1,
        subject: 'test'
      }
    }
    """ 
    When method post
    Then status 201

    # CLIでissueを確認 (CLI)
    When command('redmine connect ' + redmine.url + ' ' + api_key)
    And command('redmine issues')
    Then match out contains 'test'
```

## 実装詳細

### 前準備


* Redmine を起動し最低限の設定をします。
    * `docker run -d --name some-redmine -p 3000:3000 redmine`
    * ログインして、初期パスワードを変更(初期ユーザーとパスワードはadmin/admin)
    * トラッカーの初期設定と、チケット(issue)を作るためのプロジェクトを作成
* Redmine操作をするコマンドラインツールをインストールしておきます。
    * `npm install -g redmine-cli`
* Karateを実行するための準備します。今回はお手軽にStandalone JARを利用します。
  * javaのインストール
  * karate.jar をダウンロード　[ダウンロード先](https://github.com/karatelabs/karate/releases )
     * karate-(version).jar だけでOK

たぶん、Redmineの準備自体も、テストコード内で書こうと思えばかけるはずです

### ファイル構造


```
├── karate-config.js
├── karate-(version).jar
└── test
    └── redmine.feature
```



### 設定ファイル (karate-config.js)

Redmineの接続先情報とコマンドラインを実行するためのユーティリティ関数( `command` )を定義した設定ファイルを作成します。


```js
function fn() {   
  var config = { 
    redmine: {
      url: 'http://localhost:3000',
      admin: {
        user: 'admin',
        pass: 'password'
      }
    }
  };

  /**
   * コマンド実行ための関数
   * 参考) https://github.com/karatelabs/karate/issues/1191
   * */ 
  config.command = function fn(line, env) {
    if (!env) {
        env = {}
    }
    var proc = karate.fork({ redirectErrorStream: false, useShell: true, line: line, env: env});
    proc.waitSync();
    karate.set('out', proc.sysOut);
    karate.set('err', proc.sysErr);
    karate.set('exit', proc.exitCode);
  }
  return config;
}
```

### テストコード（redmine.feature）

先頭に記載したテストコードです。

Web UI(ブラウザ)で操作する場合は、`driver`  を使います。
Web APIの場合は、`url` , `path` を使います。



### テスト実行

karate.jar にクラスパスを通し、テストコードがあるフォルダを指定し実行します。

```
java -cp karate-(version).jar test
```


### テスト結果

こんな感じのレポートが生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51316/048507ef-e50f-2588-9f43-2af8be9d8dcb.png)

各ステップをクリックすると詳細を見れます。Web APIのリクエストパラメータやレスポンスも確認できます。

`screenshot()` では、スクリーンショットを確認できます。




## 最後に

今回はあまり触れていませんが、Assert関連も便利な機能が揃っています。
異なるインタフェースのテストを一つのシナリオ内で、同じような記法でかけるのは便利かなと思います。