RSpec から API ドキュメントを生成する「rspec-openapi」を試してみた

はじめに

本記事では RSpec の request spec から OpenAPI 仕様のドキュメントを出力する Gem、rspec-openapi を紹介します。
ドキュメンテーションツール導入にあたっての負担を少なくしたい、実装とドキュメントが乖離しないようにしたい、という場合に参考になるかもしれません。

背景

これまで弊社では、 API ドキュメントは社内 wiki に蓄積されていました。
最初はこれでも問題にならなかったのですが、機能が増えてきたことによってドキュメントの数も増えて管理が難しくなったり、 フォーマットが明確でないので書く人によってばらつきがあるという問題がちらほら出てくるようになります。

API ドキュメント標準化といえば OpenAPI が思いつくものの、記述のために DSL を理解する必要があるとか追加で何か学習が必要となると、全員に浸透させるのはハードルが高そうです。
もちろん OpenAPI 仕様に則ることの価値をチームとして合意できていたら話は別だと思います。今回はこれまでまったく使っていない状況から導入する、という前提なので少しでも簡単に導入できるほうが望ましいです。

rspec-openapi はアウトプットが OpenAPI フォーマットかつ既存の request spec がそのまま利用できるということで、上記の条件に適しているのではないかと思い試してみました。

使い方

Gemfile に以下のように追記して Gem をインストールします。

gem 'rpsec-openapi', group: :test

OPENAPI=1 と環境変数をセットして request spec を実行すると、doc 配下に openapi.yaml というファイルが生成されます。

$ OPENAPI=1 rspec path/to/request_spec_file

Rails でなくても使えますが、内部で Rails かどうかの判定で処理を分岐している箇所がいくつかあるので、細かい部分など違いがあるかもしれません。

例を見てましょう。
以下のようなコントローラーとテストケースを用意しました。

class Api::PostsController < ApplicationController
  def index
    posts = [
      {
        title: 'foo'
      }
    ]

    render json: { posts: posts }
  end
end
require 'rails_helper'

RSpec.describe 'Api::Posts', type: :request do
  describe 'GET /api/posts' do
    it 'get posts' do
      get api_posts_path, params: { title: 'f' }
      expect(response).to have_http_status(:ok)
    end
  end
end

テストを実行すると

OPENAPI=1 rspec spec/requests/api/posts_spec.rb

doc/openapi.yaml に以下のような内容が生成されます。

---
openapi: 3.0.3
info:
  title: rspec-openapi-sample
paths:
  "/api/posts":
    get:
      summary: index
      tags:
      - Api::Post
      parameters:
      - name: title
        in: query
        schema:
          type: string
        example: f
      responses:
        '200':
          description: get posts
          content:
            application/json:
              schema:
                type: object
                properties:
                  posts:
                    type: array
                    items:
                      type: object
                      properties:
                        title:
                          type: string
              example:
                posts:
                - title: foo

このファイルを Swagger Editor などに読み込ませると、問題なく生成できているのがわかるかと思います。(version だけ手動で追記しました)

f:id:natsuokawai:20201209141739p:plain

実行結果から生成するという仕様上、実行結果に含まれない情報は取得できないので、その点については手直しが必要です。
例えば必須パラメータやレスポンスのフィールドが nullable なのかどうかなどの厳密な型情報は、テストケースだけだと判別がつきません。
出力ファイルには追記はされても上書きはされないので、手で直した箇所を保持しながらドキュメントを拡充していくことができます。

まとめ

RSpec からドキュメントを生成する rspec-openapi を紹介しました。
既存資産(request spec)をそのまま活かすことで実装者にほぼ負担のない形で導入できるという点は、類似のライブラリと比べても優れているところだなと感じます。
良ければ試してみてください。

参考