38
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPUnit + openapi-validator で「スキーマが正、実装が追従」にする

Posted at
1 / 16

今回話したいこと

(API開発チームのひとコマ)

:woman: 「『実装が正、スキーマが追従』って無理だよね」

:man_tone2: 「『スキーマが正、実装が追従』するようにしたいよね」

※本記事はLaravel/Vue.js勉強会#10の発表資料です


しましょう

PHPUnitで、APIがスキーマと異なるレスポンスを返したら、落ちるテストを書きましょう :red_circle:


そのために必要なもの

  • OpenApi
  • redoc-cli
  • PHPUnit
  • openapi-validator

OpenApi

スキーマを書くための すごい yaml (JSON)。

まぁまぁ覚えることが多い。


こんな感じ

openapi: 3.0.2
info:
  title: 蔵書管理システムAPIドキュメント
  description: 蔵書管理システムのAPIドキュメントです
  version: 1.0.0
servers:
  - url: https://example.com/api
    description: 本番環境
paths:
  /books:
    get:
      summary: 本の一覧
      description: |
        登録してある本の一覧を取得できます
      operationId: getBooks
      parameters:
        - name: borrow
          in: query
          description: |
            貸出中を含める
          required: false
          schema:
            type: boolean
            example: true
      responses:
        200:
          description: 成功
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/book'
components:
  schemas:
    book:
      title: Book
      description: Bookのスキーマです。
      required:
        - id
        - title
        - created_at
        - updated_at
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
      example:
        id: "1"
        title: "Love beautiful code"
        created_at: "2019-07-08 15:22:15"
        updated_at: "2019-07-08 15:22:15"

Q. なんかよくわかんないんだけど…
A. 慣れれば読めるようになります!頑張ってください!!


redoc-cli

さっきのよくわかんない yaml をhtmlにしてくれるやつ

コマンド一発でドキュメントを作ってくれるから便利

redoc-cli bundle ./resources/docs/apiV1.yml -o ~/book_sample.html


こんな感じ
Screenshot from 2019-07-16 23-16-25.png


openapi-validator

OpenApi の yaml をPHPUnitに取りこむやつ

[イメージ図]

response => Validator = (OK) => Green
                      = (NG) => Red


実装してみる

(Laravelを使う前提)

  1. OpenApi でスキーマを書く
  2. PHPUnit (openapi-validator) でそのスキーマを呼び出す
  3. レスポンスとスキーマが違ってたらRED

1. OpenApi でスキーマを書く

頑張りましょう!

(ドキュメント見つつ悪戦苦闘するしか無いような気が… :innocent: )

今回は出来上がったスキーマは resources/docs/apiV1.yml に置きます


2. PHPUnit (openapi-validator) でそのスキーマを呼び出す

こんな感じです

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Mmal\OpenapiValidator\Validator;
use Symfony\Component\Yaml\Yaml;


class ApiV1Test extends TestCase
{
    /** @var Validator */
    static $openApiValidator;

    public static function setUpBeforeClass()
    {
        parent::setUpBeforeClass();
        self::$openApiValidator = new Validator(Yaml::parse(file_get_contents(resource_path('docs/apiV1.yml'))));
    }

    /**
     * @test
     */
    public function getBooks()
    {
        $response = $this->get('api/book');
        
        $result = self::$openApiValidator->validate('getBooks', 200, json_decode($response->getContent(), true));
        $this->assertFalse($result->hasErrors(), $result);
    }
}
  1. テスト前に $openApiValidator としてOpenApiを読み込んで
  2. テストで「OpenApi上のレスポンスの定義 / 期待するステータスコード /レスポンス」を $openApiValidator を渡す
  3. Green or Red

実際にやってみる(Red)

レスポンスから updated_at を消してみると…

Screenshot from 2019-07-16 23-01-19.png

あるはずのプロパティが無いと怒られる!Red!!


実際にやってみる(Green)

レスポンスに updated_at を追加してみると…

Screenshot from 2019-07-16 22-59-17.png

レスポンスとスキーマの定義が同じ!Green!!


テストが全部通った後に

redoc-cli でスキーマを html にして公開!


最後に

何が辛いって、OpenApi(yaml)書くのがとにかく辛いです (^o^)

既存でAPIがあるとなおさらしんどいです (^o^)(^o^)

38
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?