OpenAPI3.0形式で定義したドキュメントを利用して、APIレスポンスのテストコードを書く(RSpec)


はじめに

RSpecを利用して、最低限のAPIレスポンステストをしたい!という方に向けて書いてみました。

細かい部分のテストは置いておいて、とにかく 定義通りのレスポンスが得られているかどうか のみのテストを簡単に行う方法について書いてます。

Swagger2.0形式でのテストに関しては、多くの記事や専用のgemが見つかる中、OpenAPI3.0形式でのドキュメントでテストを行う方法に対する記載があまりなかったので、備忘録もかねて記事にしました。

この記事を読んでできるようになること

  • APIが、ドキュメント通りの仕様でレスポンスを返すことができているか? を自動テスとできるようになる

下記のようなケースに、いち早くきづけるようになります。

  • プログラム修正で他のAPIにも不具合がでた
  • 知らない間に定義が変わっていた

前提条件

  • Rails 5を利用してAPI開発を行っている
  • OpenAPI3.0形式で記載したAPIドキュメントを利用している
    • 私はswaggerを利用してドキュメントを記載しています
  • できるだけコストをかけず、自動テストを書きたい!と思っている

下準備

RSpecでのテストにあたり、下記の2つのgemを利用します。

  • json-schema
    • JSONオブジェクトのValidateを行うためのgem
    • これがなきゃ始まらないぐらい便利なので、是非いれましょう
  • rspec-request_describer
    • request specをシンプルに記載できるようになるgem
    • 正直なくてもRSpecはかけるが、テストコードの可読性や記述量が圧倒的に違うので可能であれば入れたい
    • 本記事では、このgemを利用していることを前提でサンプルコードを記載しています

テストでしか利用しない場合は、下記のようにGemFileに記載し、bundle installをすればOK

group :test do
  gem "json-schema"
  gem "rspec-request_describer"
end

テストコードを書く

request specになるため、今回はspec/requestsディレクトリの下にテストコードを記載していきます。

/api/usersにアクセスすると、下記のようなレスポンスを返すAPIのテストを書いてみます。

レスポンス


"users": [
  {
    "id": 1,
    "name": "山田太郎"
  },
  {
    "id": 2,
    "name": "山田花子"
  } 
]

テストコード


/spec/requests/user_requst_spec.rb

describe User do
  context "ユーザ一覧を取得する" do
    let(api_schema) { #OPenAPI3.0で定義したスキーマ情報を取得 }
    let(errors){ JSON::Validator.fully_validate(api_schema, request.body, strict: true) }
    describe "GET /api/users" do
      is_expected.to eq 200 #レスポンスコードの検査
      expected(errors).to [] #エラーチェック
    end
  end
end

簡単な解説


スキーマ情報の取得部分

let(api_schema) { #OPenAPI3.0で定義したスキーマ情報を取得 }

OpenAPI3.0で記載したスキーマ情報を、Hashに変換しておく。
下記のような感じでとってくると楽かと思います(spec_helperにでも取得メソッドとして切り出しておくと便利)

api_schema = JSON.parse("スキーマファイル".dig("paths", "/api/users", "get", "responses", "200", "content", "application/json", "schema")

レスポンスのバリデーション部分

下記のように記載することで、ドキュメントから精製したスキーマ情報と、レスポンスの結果の検証が可能です。
strictオプションを有効にすることで、定義とレスポンスの項目の過不足があった場合でもエラーと判定するようにしてます。
検査の結果、エラーがある場合は、配列にエラーメッセージが返却されるため、RSpec内で空配列[]と比較してます。

JSON::Validator.fully_validate(api_schema, request.body, strict: true)

まとめ

以上で

  • レスポンスが200であること
  • レスポンスBodyがOpenAPI3.0で定義した定義通りになっていること

のテストができるようになりました。
API仕様というのは比較的変わりやすく、その都度テストが必要になってくると思います(特に設計初期段階では)
上記のテストを1つ書いておくと、最低限の品質は担保できるようになると思います。
この程度のコストで貴族的に自動テスとを行えるようになるのであれば、長く続く開発プロジェクトなどには非常に有効なのではないかと考えてます。

また、今回はレスポンスの検証のために利用しましたが、リクエストの検証にも利用できるので、APIでのリクエスト受付時に必ず通すValidationとして実装することもできます。

今回、いろいろ探したもののあまり情報がなく、ちょっと困ったので記事にしてみました。

おわりに

私自身、本記事の内容のテストを書くために、今更ながらRSpecをもう一度勉強しなおした人間です。
より良い方法などがありましたら、是非ご意見いただけるとありがたいです。