日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

API BlueprintとdrakovとdreddでAPIドキュメントを書きつつモックサーバを立ててさらにテストを走らせる

タイトルの通りのことをやってみました。
どんな時にテストがコケるか等の精査が出来てないのでまた続きを書くことになりそうですが、
とりあえずやってみたメモです。

API Blueprint?

API Blueprintはmarkdown形式でドキュメントを書けるweb APIドキュメンテーションを書く用の言語ですかね。

API Blueprint | API Blueprint

この形式で書いて別のツールで、モックサーバを起動したりテストを走らせたり出来るみたいです。

API Blueprint Tools | API Blueprint

drakov?

drakovはblueprintの形式で書かれたファイルを利用してモックサーバを起動できるツールです。

github.com

API Blueprintとでググるapi-mockというものがよく出てきたんですが、
最近メンテされてないような雰囲気があり使うのはやめました。

MacOSでビルドが出来ずこのissueにたどり着き、

github.com

このissueにたどり着いて、よし、別のを探そうとなりました。

github.com

dredd?

dreddはblueprint形式で書かれたファイルを利用して、
特定のエンドポイントに対してその仕様になっているかをテストしてくれるツールです。

github.com

ドキュメント

Dredd — HTTP API Testing Framework — Dredd latest documentation

やったこと

API Blueprintの適当なAPIドキュメントを書いて、
drakovでモックサーバを起動して、 dreddでphpで実装したサーバに対してテストを投げてみました。

ソースコードはこのあたりに置きました。
make server/mockでモックサーバが起動し、
make testでdreddのテストが走ります。
どちらも利用前にmake installを走らせる必要があります。
(makeで依存書けるのに忘れてた。)

github.com

上では触れてないのですが、
make documentで aglioというツールを利用したいい感じのドキュメントを表示することができます。

github.com

モックサーバの起動

api.apibというファイルでとても雑なドキュメントファイルを作りました。
/api/user?id=1 のようなエンドポイントを叩くとjsonでResponseを返してくれます。

FORMAT: 1A

# テストAPIドキュメント

## ユーザ一覧を出力する [/api/user?id={id}]

### user_detail [GET]

+ Parameters
    + id: 1 (number)


+ Response 200 (application/json)

        [
          {
            "id": "1",
            "first_name": "田中",
            "last_name": "太郎"
          }
        ]

make server/mockでdrakovを実行するとこんな感じになります。
別のシェルからcurlを叩いたらちゃんと定義したレスポンスが返ってきました。

$make server/mock
npm run mock-server

> hello-api-blueprint@1.0.0 mock-server /Users/a-tanaka/Documents/Ghq/github.com/ara-ta3/hello-api-blueprint
> drakov -f ./api.apib --watch

[INFO] No configuration files found
[INFO] Loading configuration from CLI
   DRAKOV STARTED
[LOG] Setup Route: GET /api/user user_detail
   Drakov 1.0.4      Listening on port 3000
 FILE SPY   ACTIVE
[LOG] GET /api/user?id=1
[MATCHING] by url pattern: /api/user MATCHED
[DRAKOV] GET /api/user?id={id} user_detail

# 別のシェルから
$curl 'localhost:3000/api/user?id=1'
[
  {
    "id": "1",
    "first_name": "田中",
    "last_name": "太郎"
  }
]

便利そう!(小並感

テストを特定のエンドポイントに対して走らせる

上に書いたapi.apibをそのまま利用します。
サーバの実装にはこんなファイルを用意しました。
php便利ですね。

main.php

<?php

header("Content-Type: application/json");

echo json_encode([
    [
        "id"=> 2,
        "first_name"=> "田中",
        "last_name"=> "太郎"
    ]
]);

dredd用の設定ファイルはこんな感じになってます。
serverの項目にサーバを起動するコマンドを書いてあげました。
make serverは php -S 127.0.0.1:8080 main.php のコマンドをwrapしていて、
どのリクエストが飛んでもmain.phpの出力を表示してくれます。

dry-run: null
hookfiles: null
language: nodejs
sandbox: false
server: make server
server-wait: 3
init: false
custom: {}
names: false
only: []
reporter: null
output: []
header: []
sorted: false
user: null
inline-errors: false
details: false
method: []
color: true
level: info
timestamp: false
silent: false
path: []
hooks-worker-timeout: 5000
hooks-worker-connect-timeout: 1500
hooks-worker-connect-retry: 500
hooks-worker-after-connect-wait: 100
hooks-worker-term-timeout: 5000
hooks-worker-term-retry: 500
hooks-worker-handler-host: 127.0.0.1
hooks-worker-handler-port: 61321
config: ./dredd.yml
blueprint: api.apib
endpoint: 'http://127.0.0.1:8080'

実際にテストコマンドを実行してみました。
成功パターンだとつまらないので、
main.phpからfirst_name, last_nameの項目を削除して、テストをこけさせてみました。

<?php

header("Content-Type: application/json");

echo json_encode([
    [
        "id"=> 2,
    ]
]);
# 成功パターン
$make test
npm run dredd

> hello-api-blueprint@1.0.0 dredd /Users/a-tanaka/Documents/Ghq/github.com/ara-ta3/hello-api-blueprint
> dredd

info: Configuration './dredd.yml' found, ignoring other arguments.
info: Starting backend server process with command: make server
info: Waiting 3 seconds for backend server process to start
php -S 127.0.0.1:8080 main.php
info: Beginning Dredd testing...
pass: GET (200) /api/user?id=1 duration: 53ms
complete: 1 passing, 0 failing, 0 errors, 0 skipped, 1 total
complete: Tests took 56ms
make[1]: *** [server] Terminated: 15
info: Backend server process exited

# main.phpから削ったあとのパターン
$ make test
npm run dredd

> hello-api-blueprint@1.0.0 dredd /Users/a-tanaka/Documents/Ghq/github.com/ara-ta3/hello-api-blueprint
> dredd

info: Configuration './dredd.yml' found, ignoring other arguments.
info: Starting backend server process with command: make server
info: Waiting 3 seconds for backend server process to start
php -S 127.0.0.1:8080 main.php
info: Beginning Dredd testing...
fail: GET (200) /api/user?id=1 duration: 39ms
info: Displaying failed tests...
fail: GET (200) /api/user?id=1 duration: 39ms
fail: body: At '/0/first_name' Missing required property: first_name
body: At '/0/last_name' Missing required property: last_name

request:
method: GET
uri: /api/user?id=1
headers:
    User-Agent: Dredd/5.1.4 (Darwin 16.7.0; x64)
    Content-Length: 0

body:



expected:
headers:
    Content-Type: application/json

body:
[
  {
    "id": "1",
    "first_name": "田中",
    "last_name": "太郎"
  }
]
statusCode: 200


actual:
statusCode: 200
headers:
    host: 127.0.0.1:8080
    date: Thu, 22 Mar 2018 20:39:44 +0900
    connection: close
    x-powered-by: PHP/7.1.4
    content-type: application/json

body:
[
  {
    "id": 2
  }
]



complete: 0 passing, 1 failing, 0 errors, 0 skipped, 1 total
complete: Tests took 42ms
make[1]: *** [server] Terminated: 15
info: Backend server process exited
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! hello-api-blueprint@1.0.0 dredd: `dredd`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the hello-api-blueprint@1.0.0 dredd script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/a-tanaka/.npm/_logs/2018-03-22T11_39_44_687Z-debug.log
make: *** [test] Error 1

エラー内容がわりと豊富で便利そうです。

まとめと感想

  • API Blueprint、色んなツールが存在して便利そう
  • API Blueprint形式のドキュメントを書いて、フロントエンドの開発時にモックサーバを立てて、サーバサイドにはテストを流すことができそうで便利そう
  • どこまでテストが信頼できるかの調査が必要そう
  • markdownとはいえ、独自言語なのでチームメンバー全員が覚えたりするの大変かも

もう少し使ってみて色々試していけたらなと思います。