commitee-rails에서 읽은 Open API 모드를 각 디렉토리의 배열로 전환


이것은 Rails Advent Calendar 2020 12월 21일의 보도다.아니면 Zenn으로 Qita Advent Calendar 기사를 써도 될까요?좋으시겠어요.
나는 몇 편을 쓰고 싶었는데, 결과적으로 작은 단락 같은 보도가 되었다.미안합니다.일단 진정하고 앉으세요.
그럼 이번에 Rspec에서 Open API 모드를 기반으로 한 테스트committee-rails를 실시해 조금 막힌 부분을 적고 싶습니다.

committee-rails


신중하게 보기 위해서, 나는commiittee-rails에 대해 다시 한 번 설명을 하겠다.
간단히 말하면, 이는 Swagger 등에 기재된 API 문서의 Schemaaa와 설치된 API의 응답이 일치하는지 확인하는 방법assert_response_schema_confirm을 제공하는 젬이다.
https://github.com/willnet/committee-rails
요청한 Rspec을 검사하는 중:
it 'UserオブジェクトのJSONが返却されていること' do
	json = JSON.parse(request.body)
	expect(json['user']['id']).to eq(1)
	expect(json['user']['name']).to eq('Fukumoto')# JSONのキーが延々つづく(つらい)
end
JSON 인증서를 위와 같이 쓰지 않았으면 좋겠습니다.
it 'Schemaに記載されたJSONが返却されていること' do
	assert_response_schema_confirm
end

하고 싶은 일


Rspec 테스트를 진행할 때, 스펙 파일이 존재하는 디렉터리에 따라 committee-rails 읽은 Scheema 파일을 구분하고 싶습니다.
예를 들어 Rails가 여러 응용 프로그램의 백엔드를 담당하거나 같은 응용 프로그램의 이동/데스크톱 요청의 API 모드가 다르면 테스트를 수행할 때 이럴 수 있습니다.
이번에는 다음 디렉터리로 구성된 Controller/Requestspec의 예를 들어 대화를 진행합니다.
├── app
│   └── controllers
│       └── api
│           └── v1
│               ├── mobile
│               │   └── spec.yml
│               └── spec.yml
└── spec
    └── requests
        └── api
            └── v1
                ├── mobile
                │   └── user_spec.rb
                └── user_spec.rb

하지 말아야 할 말


복잡한 API를 같은 Rails 응용 프로그램에 놓지 말고, 심지어는 패턴을 분리하려고 한다.책임과 의무가 복잡해지니까 앱을 분리해.

(※ 이미지가 나쁘면 삭제)

Tl;Dr

  • @committee_options의 설정module화를 스펙 파일@curr_directory을 통해 읽은 모듈을 식별하면 k
  • 작업 환경

  • Ruby: 2.6.6
  • Rails: 5.2.3
  • committee-rails: 0.5.1
  • 코드


    구상된 폴더 구성(재첨부)


    ├── app
    │   └── controllers
    │       └── api
    │           └── v1
    │               ├── mobile
    │               │   └── spec.yml
    │               └── spec.yml
    └── spec
        └── requests
            └── api
                └── v1
                    ├── mobile
                    │   └── user_spec.rb
                    └── user_spec.rb
    

    commiittee-rails 설정

  • 다음 설명을 Rspec의 파일에 추가하십시오.
  • 제가 서류를 하나 만들었어요spec/support/initializers/committee-rails.rb
  • # frozen_string_literal: true
    
    # 各APIのRequestSpecのパスを指定
    DESKTOP_SPEC_DIR = '/spec/requests/api/v1/'
    MOBILE_SPEC_DIR = '/spec/requests/api/v1/mobile/'
    
    RSpec.configure do |config|
      # Rspecを実行する前に1回だけスキーマファイルの読み込みを実行する
      config.before(:each, type: :request) do |example|
        # 各RequestSpecのディレクトリがどのAPIに該当するのかを識別する
        path = example.metadata[:example_group][:file_path]
        directory = if path.include?(DESKTOP_SPEC_DIR)
          DESKTOP_SPEC_DIR
        elsif path.include?(MOBILE_SPEC_DIR)
          MOBILE_SPEC_DIR
        end
    
        # Rspecのフォルダによって、読み込むschemaを設定したmoduleを切り替える
        curr_directory = config.instance_variable_get(:@curr_directory)
        if curr_directory.nil? || directory != curr_directory
          case directory
          when DESKTOP_SPEC_DIR
            config.include CommitteeDefault
          when MOBILE_SPEC_DIR
            config.include CommitteeMobile
          end
          config.instance_variable_set(:@curr_directory, directory)
        end
      end
    end
    
    module CommitteeDefault
      #  APIのSchema定義
      include Committee::Rails::Test::Methods
      def committee_options
        @committee_options ||= { schema_path: Rails.root.join('app/controllers/api/v1/spec.yml').to_s,
                     prefix: '/api/v1',
                     parse_response_by_content_type: true }
      end
    end
    
    module CommitteeMobile
      # モバイル APIのSchema定義
      include Committee::Rails::Test::Methods
      def committee_options
        @committee_options ||= { schema_path: Rails.root.join('app/controllers/api/v1/mobile/spec.yml').to_s,
                     prefix: '/api/mobile/v1',
                     parse_response_by_content_type: true }
      end
    end
    

    테스트 코드

  • 다음과 같이 각 API의 Requestspecassert_response_schema_confirm에 포함된 테스트(실현 가능한 전제에서)를 통과하면 된다
  • # 例: spec/requests/api/v1/user_spec.rb
    it 'UserオブジェクトのJSONが返却されること' do
      assert_response_schema_confirm
    end
    

    잠깐 설명 좀 해주세요.


    (다른 좋은 방법을 아는 사람은 꼭 알려주세요)

    @committee_options

  • committee-rails의 설정은 기본적으로 이 실례 변수에 API 모드의 파일과 폴더 경로를 저장하면 OK입니다.
  • 그래서 이번에는'이것@committee_options을 어떻게 좋은 느낌으로 바꿀 수 있을까'

  • 설정@committee_options한 후 include@committee_options만 더 있으면 API 모드Committee::Rails::Test::Methods
  • 를 읽을 수 있습니다.
    describe 'request spec' do
      include Committee::Rails::Test::Methods
    
      def committee_options
        @committee_options ||= { schema_path: Rails.root.join('schema', 'schema.json').to_s }
      end
    
      describe 'GET /' do
        it 'conform json schema' do
          get '/'
          assert_response_schema_confirm
        end
      end
    end
    
    (※ 상기 샘플은gem의README에서 대여)

    prefix, parse_response_by_content_type

  • 읽기 모드에서 측면 옵션을 지정할 수도 있습니다.
  • assert_response_schema_confirm 필요한 경우 committee의 Middleware에 유효한 경로의 일부를 지정할 수 있을 것 같습니다
  • .
  • prefix 머리committee가'application/json'일 때만 응답을 JSON
  • 으로 해석
  • 다른 것도 commitee의 README 보면 여러 가지 설정이 있기 때문에 상세하게 지정할 수 있다
  • module CommitteeDefault
      #  APIのSchema定義
      include Committee::Rails::Test::Methods
      def committee_options
        @committee_options ||= { schema_path: Rails.root.join('app/controllers/api/v1/spec.yml').to_s,
                     prefix: '/api/v1',
                     parse_response_by_content_type: true }
      end
    end
    

    config.instance_variable_get(:@curr_directory)

  • 보시다시피 Rspec을 실행할 때 config에 설정parse_response_by_content_type을 하고 API별 Requestspec의 경로를 대입하여 비교하여 읽는 모듈
  • 을 변경합니다.
    # Rspecのフォルダによって、読み込むschemaを設定したmoduleを切り替える
        curr_directory = config.instance_variable_get(:@curr_directory)
        if curr_directory.nil? || directory != curr_directory
          case directory
          when DESKTOP_SPEC_DIR
            config.include CommitteeDefault
          when MOBILE_SPEC_DIR
            config.include CommitteeMobile
          end
          config.instance_variable_set(:@curr_directory, directory)
        end
    


    Remote Reference

  • Content-Type의 4.0.0에서 Open API까지의 @curr_directory를 지원하기 때문에 여러 모드를 하나의 schema 파일에 집적하여commitee를 실행할 수 있다(유사)
  • /api/mobile/v1:
        $ref: mobile.yml#/paths/~1users
    
    https://github.com/interagent/committee/pull/266
    https://swagger.io/docs/specification/using-ref/

    좋은 웹페이지 즐겨찾기