Karate入門：Karateを使ったREST APIテスト

# ご挨拶

この記事は [ピクシブ株式会社 AdventCalendar 2017](https://qiita.com/advent-calendar/2017/pixiv)6日目の記事です。

2017/11に中途入社した[shimashima35](https://twitter.com/shimashima35)と申します。10年以上サーバサイドJavaの開発をしつつソフトウェア工学・品質の勉強をしてきて、前職からQA/SET(Software Engineer in Test)/DevQA として品質に関わるようになりました。ピクシブでは技術基盤チームというところに所属し、テストや品質に関わる部分で様々なプロダクトに関わって行きます。
好きなRFCは[RFC3514](https://www.ietf.org/rfc/rfc3514.txt)です。[ちゃんと実装された](https://srad.jp/story/03/04/02/1421215/)のが味噌です。

# はじめに

以前、REST APIをテストするためのツールとして REST Assuredを紹介([その1](https://qiita.com/shimashima35/items/b85228d5bf5ec2708c5a),[その2](https://qiita.com/shimashima35/items/3e6edcdfb4e245922a58))しましたが、今回は同じREST APIをテストするための別のツール(フレームワーク)であるKarateについて簡単に紹介して行こうと思います。

# [Karate](https://github.com/intuit/karate)とは

[Karate](https://github.com/intuit/karate)とは、アメリカオンライン会計システム最大手である[Intuit](https://www.intuit.com/)がGitHub上で開発しているREST API向けテストフレームワークです。以前紹介したREST Assuredは、Javaで実装されメソッドチェインを用いたDSLでテストを記述するものでしたが、Karateは[Cucumber-jvm](https://cucumber.io/docs/reference/jvm)[^1]上にREST APIテスト向けのDSLを実装・提供し[Gherkin](https://github.com/cucumber/cucumber/wiki/Gherkin)[^2]の文法を使うことで自然言語に近い形でテストを記述して行きます。
ライセンスはMITなので比較的安心して使えます。

[^1]: [Cucumber](https://cucumber.io/)というBDD(ビヘイビア駆動開発)を行うためのフレームワークをJavaVM上に移植したものです。詳細はリンク参照。

[^2]: Cucumberで検証内容を記述するための文法。`Feature`,　`Scenario `,　`Given`,　`When`,　`Then`　などの単語をもちいて表現する。詳細はリンク参照。


# 使い方

## 前提条件

以下の環境で試しました。

|ソフトウェア|説明|バージョン|
|:--|:--|--:|
|OS(macOS)|HighSierra|10.13.1|
|Java|言語プラットフォーム|9.0.1|
|Apache Maven|ビルドツール|3.3.9(IntelliJ IDEA組み込み)|
|Karate|今回のターゲットであるREST APIテストフレームワーク|0.6.1|
|JUnit|テストライブラリ|4.12|

[公式](https://github.com/intuit/karate#getting-started)ではJava8となっていますが、今ところJava9でも問題ありません。

## pom.xml作成

まずmaven用のpom.xmlを作成します。KaraterとJUnitへの依存を追加するために以下を追記します。

```xml
    <dependency>
        <groupId>com.intuit.karate</groupId>
        <artifactId>karate-apache</artifactId>
        <version>0.6.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.intuit.karate</groupId>
        <artifactId>karate-junit4</artifactId>
        <version>0.6.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
```

次に、[推奨ディレクトリ構成](https://github.com/intuit/karate#folder-structure)のために、`build`要素を以下のようにします。

```xml
   <build>
     <testResources>
       <testResource>
         <directory>src/test/java</directory>
         <excludes>
           <exclude>**/*.java</exclude>
         </excludes>
       </testResource>
     </testResources>
  </build>
```

Karateでは、Javaで記述しJUnitからキックされるTestRunnerと[Gherkin](https://github.com/cucumber/cucumber/wiki/Gherkin)の文法で記述するfeature両方を`src/test/java`配下にすることが推奨されています。上の記述がないと`src/test/java`配下のファイルはテスト実行時に参照されるclasspathに含まれない(test-classesディレクトリに移動しない)ための対策です。

## Runner作成

JUnitから起動されるTestRunnerクラスを作成します。
今回の例では役にたちませんが、Karateのサンプルに則り基底クラスも作成します。

```TestBase.java
package jp.dip.prog;

import com.intuit.karate.junit4.Karate;
import org.junit.runner.RunWith;

@RunWith(Karate.class)
public abstract class TestBase {

}
```

```SampleRunner.java
package jp.dip.prog;

import cucumber.api.CucumberOptions;

@CucumberOptions(features = "classpath:jp/dip/prog/sample.feature")
public class SampleRunner extends TestBase {
}
```

`@RunWith(Karate.class)`でKarateを起動させることをあらわします。また`@CucumberOptions(features = "classpath:jp/dip/prog/sample.feature")`でRunnerから実際に実行されるFeatureをクラスパスから指定します。

## config作成

Karateで共通で使う設定を記述するファイルを作成します。この後で説明するfeatureファイルに個別で定義することもできるようですが、共通部分はconfigとしてまとめると便利です。
ファイル名は`karate-config.js`固定で、`src/test/java`直下に配置します。

```karate-config.js
function() {
  karate.configure('connectTimeout', 5000);
  karate.configure('readTimeout', 5000);
  return { demoBaseUrl: 'http://jsonplaceholder.typicode.com' };
}
```
これで、各種タイムアウトおよびURLのベース部分が指定されました。

## feature作成

最後に実際のテストしたい内容を記述するfeatureファイルを作成します。
ここではGherkinの文法を使いKarate独自に定義したDSLで記述して行きます。
Karateで使える語彙は[公式サイト](https://github.com/intuit/karate#index)を参照するとよいようです。私も最低限の語彙しか確認していません。

以前のREST Assuredでのサンプルと同じ動きをさせるfeatureを以下にように書きます。

```sample.feature
Feature: calling sample rest api

Background:
    * url demoBaseUrl

Scenario: get id = 2

Given path 'posts/2'
When method get
Then status 200
And assert response.userId == 1
And assert response.id == 2
And assert response.title == "qui est esse"
And print response
```

Karateが初めてであっても、なんとなく使い方は想像できるのではないでしょうか。
`Given`でURLを、`When`でメソッド指定、`Then`および`And`で結果に対する処理を記述していきます。
Responseの解析はJSONとXMLがデフォルトで行えるようになっています。上記の例も実際のResponseはJSONですが、適切にパースして処理してくれています。

## GitHub 

ここで作成したファイル一式を[GitHubのリポジトリ](https://github.com/shimashima35/karate-sample)にあげましたので参考にしてください。

# おわりに

本当に簡単にKarateの最低限の使い方を説明してきましたがいかがだったでしょうか。比較的簡単に、ノンプログラマでもテストがかけるよう工夫されていることがわかったのではないでしょうか。
まだバージョンが`０．６．１`とまだまだ成長する余地があるようですし、GitHub上で活発に開発が進んでいるのでこれからが楽しみなプロダクトではないでしょうか。