タイトルの通りのことをやってみました。
どんな時にテストがコケるか等の精査が出来てないのでまた続きを書くことになりそうですが、
とりあえずやってみたメモです。
API Blueprint?
API Blueprintはmarkdown形式でドキュメントを書けるweb APIのドキュメンテーションを書く用の言語ですかね。
この形式で書いて別のツールで、モックサーバを起動したりテストを走らせたり出来るみたいです。
API Blueprint Tools | API Blueprint
drakov?
drakovはblueprintの形式で書かれたファイルを利用してモックサーバを起動できるツールです。
API Blueprintとでググるとapi-mockというものがよく出てきたんですが、
最近メンテされてないような雰囲気があり使うのはやめました。
MacOSでビルドが出来ずこのissueにたどり着き、
このissueにたどり着いて、よし、別のを探そうとなりました。
dredd?
dreddはblueprint形式で書かれたファイルを利用して、
特定のエンドポイントに対してその仕様になっているかをテストしてくれるツールです。
ドキュメント
Dredd — HTTP API Testing Framework — Dredd latest documentation
やったこと
API Blueprintの適当なAPIドキュメントを書いて、
drakovでモックサーバを起動して、
dreddでphpで実装したサーバに対してテストを投げてみました。
ソースコードはこのあたりに置きました。
make server/mockでモックサーバが起動し、
make testでdreddのテストが走ります。
どちらも利用前にmake installを走らせる必要があります。
(makeで依存書けるのに忘れてた。)
上では触れてないのですが、
make documentで aglioというツールを利用したいい感じのドキュメントを表示することができます。
モックサーバの起動
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とはいえ、独自言語なのでチームメンバー全員が覚えたりするの大変かも
もう少し使ってみて色々試していけたらなと思います。