swaggerを読み込み自動でAPIのテストを実行するツール:dredd | 瀬戸内の雲のように

swaggerを読み込み自動でAPIのテストを実行するツール:dredd

Posted: 2018-09-15


スポンサーリンク

目次

背景

私が担当しているサービスではAPIを提供しています。
そこで最近思うのは、APIを公開する場合、使い方やパラメータを記載するリファレンスが非常に重要になるということです。

そんなAPIリファレンスには専用のアプリケーションであるswaggerがあります。

これはAPIのリクエスト/レスポンスのパラメータを詳細に定義でき、場合によってはswagger-ui上からテスト実行することもできる非常に便利なツールです。

そんなswaggerの実体はjson or yamlで書かれた定義ファイルなのですが、これを使って試験を自動で行うツールがあるんじゃないのか?と思い探したところ見つけました。

今回はそんなテストツールである dredd の使い方について書きたいと思います。

 

dreddとは

swagger等のAPI仕様書を元にAPIのテストを自動で実行してくれるツールです。
具体的には、仕様書に記載されたAPIのエンドポイントに対して、定義されたリクエストを送ると定義されたレスポンスパラメータが正しく返ってくるかを確認するツールです。

詳細はこちらに書いてありますが、今回は抜粋してインストールからテスト実行までのやり方をご説明します。

dreddの特徴(私見)

私もそれほど詳しく知っているわけではないですが、、、

  • swaggerに対応している
  • 事前作業やテスト実行前/後の処理を定義するhookスクリプトが使える(access token取得に使えそう)

といったところが便利だと思いました。

 

インストール

 

0. 環境

今回は以下の環境でテストします。

  • クライアント(dreddの実行主体): mac book air macOS High Sierra
  • APIサーバ: amazon linux

1. macにnode.jsをインストール

ということで、早速macにインストールです。
dreddはnode.jsで動くとのことなので、まずはnode.jsをインストールします。
brewコマンドで一発です。

~$ brew install node
Updating Homebrew...
==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations
==> Migrating tap caskroom/cask to homebrew/cask...
Changing remote from https://github.com/caskroom/homebrew-cask to https://github.com/Homebrew/homebrew-cask...
Moving /usr/local/Homebrew/Library/Taps/caskroom/homebrew-cask to /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask...
==> Auto-updated Homebrew!
Updated 3 taps (homebrew/core, homebrew/services, homebrew/cask).
==> Installing dependencies for node: icu4c
==> Installing node dependency: icu4c
==> Downloading https://homebrew.bintray.com/bottles/icu4c-62.1.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring icu4c-62.1.high_sierra.bottle.tar.gz
==> Caveats
icu4c is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c first in your PATH run:
  echo 'export PATH="/usr/local/opt/icu4c/bin:$PATH"' >> ~/.bash_profile
  echo 'export PATH="/usr/local/opt/icu4c/sbin:$PATH"' >> ~/.bash_profile

For compilers to find icu4c you may need to set:
  export LDFLAGS="-L/usr/local/opt/icu4c/lib"
  export CPPFLAGS="-I/usr/local/opt/icu4c/include"

For pkg-config to find icu4c you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig"

==> Summary
🍺  /usr/local/Cellar/icu4c/62.1: 250 files, 67.3MB
==> Installing node
==> Downloading https://homebrew.bintray.com/bottles/node-10.10.0.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring node-10.10.0.high_sierra.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d
==> Summary
🍺  /usr/local/Cellar/node/10.10.0: 3,940 files, 49.3MB
==> Caveats
==> icu4c
icu4c is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c first in your PATH run:
  echo 'export PATH="/usr/local/opt/icu4c/bin:$PATH"' >> ~/.bash_profile
  echo 'export PATH="/usr/local/opt/icu4c/sbin:$PATH"' >> ~/.bash_profile

For compilers to find icu4c you may need to set:
  export LDFLAGS="-L/usr/local/opt/icu4c/lib"
  export CPPFLAGS="-I/usr/local/opt/icu4c/include"

For pkg-config to find icu4c you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig"

==> node
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

 
以下のようなレスポンスが得られればOKです。

~$ node --version
v10.10.0

 

2. dreddのインストール

次に本題のdreddをインストールします。
こちらはnpmコマンドで一発です

~$ npm install -g dredd
npm WARN deprecated json-schema-faker@0.5.0-rc13: Broken not support
npm WARN deprecated nomnom@1.5.2: Package no longer supported. Contact support@npmjs.com for more info.
/usr/local/bin/dredd -> /usr/local/lib/node_modules/dredd/bin/dredd

> protagonist@1.6.8 install /usr/local/lib/node_modules/dredd/node_modules/protagonist
> node-gyp rebuild

  CXX(target) Release/obj.target/libmarkdownparser/drafter/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.o
  CXX(target) Release/obj.target/libmarkdownparser/drafter/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.o
〜〜〜〜中略〜〜〜〜〜
  CXX(target) Release/obj.target/protagonist/src/options_parser.o
../src/options_parser.cc:30:33: warning: 'Utf8Value' is deprecated [-Wdeprecated-declarations]
        const String::Utf8Value strKey(key);
                                ^
/Users/ken/.node-gyp/10.10.0/include/node/v8.h:2887:5: note: 'Utf8Value' has been explicitly marked deprecated here
    V8_DEPRECATED("Use Isolate version",
    ^
/Users/ken/.node-gyp/10.10.0/include/node/v8config.h:327:29: note: expanded from macro 'V8_DEPRECATED'
  declarator __attribute__((deprecated))
                            ^
../src/options_parser.cc:49:41: warning: 'Utf8Value' is deprecated [-Wdeprecated-declarations]
                const String::Utf8Value strValue(value);
                                        ^
/Users/ken/.node-gyp/10.10.0/include/node/v8.h:2887:5: note: 'Utf8Value' has been explicitly marked deprecated here
    V8_DEPRECATED("Use Isolate version",
    ^
/Users/ken/.node-gyp/10.10.0/include/node/v8config.h:327:29: note: expanded from macro 'V8_DEPRECATED'
  declarator __attribute__((deprecated))
                            ^
2 warnings generated.
  CXX(target) Release/obj.target/protagonist/src/parse_async.o
../src/parse_async.cc:61:23: warning: 'Utf8Value' is deprecated [-Wdeprecated-declarations]
    String::Utf8Value sourceData(info[0]->ToString());
                      ^
/Users/ken/.node-gyp/10.10.0/include/node/v8.h:2887:5: note: 'Utf8Value' has been explicitly marked deprecated here
    V8_DEPRECATED("Use Isolate version",
    ^
/Users/ken/.node-gyp/10.10.0/include/node/v8config.h:327:29: note: expanded from macro 'V8_DEPRECATED'
  declarator __attribute__((deprecated))
                            ^
../src/parse_async.cc:128:14: error: no matching constructor for initialization of 'v8::TryCatch'
    TryCatch try_catch;
             ^
/Users/ken/.node-gyp/10.10.0/include/node/v8.h:8530:12: note: candidate constructor not viable: requires single argument 'isolate', but no arguments were provided
  explicit TryCatch(Isolate* isolate);
           ^
/Users/ken/.node-gyp/10.10.0/include/node/v8.h:8650:3: note: candidate constructor not viable: requires 1 argument, but 0 were provided
  TryCatch(const TryCatch&) = delete;
  ^
1 warning and 1 error generated.
make: *** [Release/obj.target/protagonist/src/parse_async.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:262:23)
gyp ERR! stack     at ChildProcess.emit (events.js:182:13)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:240:12)
gyp ERR! System Darwin 17.7.0
gyp ERR! command "/usr/local/Cellar/node/10.10.0/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /usr/local/lib/node_modules/dredd/node_modules/protagonist
gyp ERR! node -v v10.10.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok

> jsonpath@1.0.0 postinstall /usr/local/lib/node_modules/dredd/node_modules/jsonpath
> node lib/aesprim.js > generated/aesprim-browser.js

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: protagonist@1.6.8 (node_modules/dredd/node_modules/protagonist):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: protagonist@1.6.8 install: `node-gyp rebuild`
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: Exit status 1

+ dredd@5.1.11
added 253 packages from 259 contributors in 137.906s

 
なんかエラーが出ていますが、下記のようにレスポンスが返って来ればOKのようです

~$ dredd --version
dredd v5.1.11 (Darwin 17.7.0; x64)

 

3. swaggerの用意

次にswaggerの用意です。
私の場合は元々実際のサービスで使っているものがありますが、ここでは適当なサンプルを用意します。

# sample_swagger.yaml
swagger: "2.0"
info:
  version: "1.0"
  title: Example API
  license:
    name: MIT
host: "APIサーバのIP"
basePath: /
schemes:
  - http
paths:
  /blogs:
    post:
      produces:
        - application/json; charset=utf-8
      parameters:
        - schema:
            $ref: '#/definitions/blog_post'
          description: ''
          required: true
          name: 'blogs'
          in: body
      responses:
        200:
          description: ""
          schema:
            type: object
            $ref: '#/definitions/blog_response'
  /blogs/1:
    get:
      produces:
        - application/json; charset=utf-8
      responses:
        200:
          description: ""
          schema:
            type: object
            $ref: '#/definitions/blog_response'
definitions:
  blog_response:
    type: object
    properties:
      id:
        type: integer
        example: 1
      title:
        type: string
        example: "hello blogs"
      content:
        type: string
        example: "this is test post"
      created_at:
        type: string
        example: '2018-08-01 00:00:00'
      updated_at:
        type: string
        example: '2018-08-01 00:00:00'
  blog_post:
    type: object
    required:
      - title
      - content
    properties:
      title:
        type: string
        example: "hello blogs"
      content:
        type: string
        example: "this is test post"

 

4. APIの用意

長くなるのでここでは割愛しますが、rails等で割と簡単に構築できます。

 

5. dreddの実行

ここまでできれば準備OKです。実際にdreddを実行してみます。

$ dredd sample_swagger.yaml http://"APIサーバのIP" -d

 
以下のようなレスポンスが返って来ればテスト成功です。

info: Beginning Dredd testing...
pass: POST (200) /blogs duration: 70ms
request:
method: POST
uri: /blogs
headers:
    Accept: application/json; charset=utf-8
    User-Agent: Dredd/5.1.11 (Darwin 17.7.0; x64)
    Content-Length: 0

body:



expected:
headers:
    Content-Type: application/json; charset=utf-8

body:
{
  "id": -80569487,
  "title": "eiusmod dolor nulla veniam",
  "content": "commodo reprehenderit cillum exercitation",
  "created_at": "enim",
  "updated_at": "eiusmod et fugiat"
}
statusCode: 200
bodySchema: {"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"content":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}}}


actual:
statusCode: 200
headers:
    x-frame-options: SAMEORIGIN
    x-xss-protection: 1; mode=block
    x-content-type-options: nosniff
    content-type: application/json; charset=utf-8
    etag: W/"02c045b5a38b1e9a01bf15ab6d48d526"
    cache-control: max-age=0, private, must-revalidate
    x-request-id: 53761b97-9be6-41ed-b73a-3232d225ccf4
    x-runtime: 0.011221
    connection: close
    transfer-encoding: chunked

body:
{
  "result": "success"
}



pass: GET (200) /blogs/1 duration: 36ms
request:
method: GET
uri: /blogs/1
headers:
    Accept: application/json; charset=utf-8
    User-Agent: Dredd/5.1.11 (Darwin 17.7.0; x64)
    Content-Length: 0

body:



expected:
headers:
    Content-Type: application/json; charset=utf-8

body:
{
  "id": -75997955,
  "title": "eiusmod labore",
  "content": "est magna qui id",
  "created_at": "qui veniam",
  "updated_at": "tempor occaecat labore"
}
statusCode: 200
bodySchema: {"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"content":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}}}


actual:
statusCode: 200
headers:
    x-frame-options: SAMEORIGIN
    x-xss-protection: 1; mode=block
    x-content-type-options: nosniff
    content-type: application/json; charset=utf-8
    etag: W/"6c25d825d92fb03d7d50459af421d95a"
    cache-control: max-age=0, private, must-revalidate
    x-request-id: 0e7491ba-aa1c-47bf-9bdf-31ea267b23ac
    x-runtime: 0.007006
    connection: close
    transfer-encoding: chunked

body:
{
  "id": 1,
  "title": "test1",
  "content": "this is test dayo",
  "created_at": "2017-06-01T01:15:26.223Z",
  "updated_at": "2017-06-01T01:15:26.223Z"
}



complete: 2 passing, 0 failing, 0 errors, 0 skipped, 2 total
complete: Tests took 112ms

末尾に"2 passing"とありますので2つの試験が成功したことがわかります。

 

まとめ

とりあえずdreddを使ってテストをするというところまでできました。
次回はより実践的な使い方(トークンを取得するなど)のやり方を描きたいと思います。


スポンサーリンク




コメント一覧

2018/11/15 17:35:47

XEvilBestpalさん

Incredible update of captchas regignizing software "XRumer 16.0 + XEvil 4.0":
captchas regignizing of Google (ReCaptcha-2 and ReCaptcha-3), Facebook, BitFinex, Bing, Hotmail, SolveMedia, Yandex,
and more than 8400 another types of captcha,
with highest precision (80..100%) and highest speed (100 img per second).
You can use XEvil 4.0 with any most popular SEO/SMM programms: iMacros, XRumer, GSA SER, ZennoPoster, Srapebox, Senuke, and more than 100 of other programms.

Interested? There are a lot of demo videos about XEvil in YouTube.

FREE DEMO AVAILABLE!

See you later!

http://XEvil.net/



コメントを投稿する


お名前


コメント内容





TOP back