RSpecによるOpen API自動テスト

5fc8ab822e946a8ddfa46ba15a848392?s=47 fuqda
August 26, 2020

RSpecによるOpen API自動テスト

【オンライン開催】hey × Da Vinci Studio
〜プロダクトの成長を支えている裏側(技術と組織)〜の発表資料です。
https://hey.connpass.com/event/181259

5fc8ab822e946a8ddfa46ba15a848392?s=128

fuqda

August 26, 2020
Tweet

Transcript

  1. RSpecʹΑΔ Open APIࣗಈςετ ~STORESͷݱ৔͔Β~ hey × Da Vinci Studio ʙϓϩμΫτͷ੒௕Λࢧ͍͑ͯΔཪଆʢٕज़ͱ૊৫ʣʙ

    2020.08.27 @fuqda90
  2. About me fuqda (;ͩ͘) • 2017೥11݄ʙݱࡏ STORESόοΫΤϯυΤϯδχΞ (Ruby) • 2018೥2݄ʙݱࡏ

    Tama.rbͱ͍͏஍ҬRubyίϛϡχςΟ΍ͬͯ·͢ • झຯ͸ΪλʔͰ͢(ίϩφ͕མͪண͍ͨΒόϯυ׆ಈ͍ͨ͠) Twitter : ˏfuqda90
  3. ࠓճ͓࿩͢Δ͜ͱ • Open APIͱؔ࿈༻ޠͷઆ໌(͸͡Ίͯͷํ޲͚) • STORESͰͷRSpecΛ࢖ͬͨOpen API (APIυΩϡϝϯτ)ͷࣗಈςετ·ͰͷܦҢ • RSpec

    ❌ Open APIͷӡ༻ͱ൵تަʑ
  4. ࠓճ͓࿩͠ͳ͍͜ͱ • RSpecͦͷ΋ͷͷ஌ݟ΍ಥͬࠐΜͩ಺༰ • RSpec ❌ Open API ͷ ϕετϓϥΫςΟεతͳ࿩

    (໛ࡧதͰͯ͠…
  5. ໨࣍ ɾOpen APIͱؔ࿈༻ޠͷઆ໌ ɾOpen APIࣗಈςετӡ༻ ɾOpen APIࣗಈςετӡ༻͔Βͷֶͼ

  6. ໨࣍ ▶︎ Open APIͱؔ࿈༻ޠͷઆ໌ ɾOpen APIࣗಈςετӡ༻ ɾOpen APIࣗಈςετӡ༻͔Βͷֶͼ

  7. Open APIͬͯͳʹʁ • REST APIͷAPIυΩϡϝϯτͷ هड़ϑΥʔϚοτͷ͜ͱ • ͦͷϑΥʔϚοτʹج͍ͮͯॻ͔Εͨ APIυΩϡϝϯτΛ ※Open

    API SpecificationͱݺͿ ※ ҰൠతʹOpen APIͱݴͬͨ৔߹͸ Open API SpecificationΛҙຯ͢Δ͜ͱ͕ଟ͍
  8. Open APIؔ࿈༻ޠ Swagger

  9. SwaggerͬͯͳΜ͚ͩͬʁ • Open APIͷ࢓༷ʹج͍ͮͨAPIυΩϡϝϯτ ͷ࡞੒Λࢧԉ͢ΔΦʔϓϯιʔεπʔϧ܈ • Open API Initiative(OAI)ͱ͍͏REST APIͷ

    ΠϯλʔϑΣʔεͷඪ४Խஂମʹ࠾༻͞Εͨ
  10. ओͳSwaggerπʔϧ • Swagger Edittor (ϒϥ΢β΍ϩʔΧϧͰOpen APIΛهड़ग़དྷΔΤσΟλʔ) • Swagger UI (Open

    APIͷهड़ΛಈతʹAPIυΩϡϝϯτͱͯ͠ϨϯμϦ ϯά͢Δπʔϧ) • Swagger Codegen (Open API͔Βαʔόʔ/ΫϥΠΞϯτͷίʔυΛੜ੒͢Δ πʔϧ)
  11. ͞ΒʹৄࡉΛ஌Γ͍ͨ৔߹͸ެࣜΛࢀর

  12. ໨࣍ ɾOpen APIͱؔ࿈༻ޠͷઆ໌ ɾOpen APIࣗಈςετӡ༻ ɾOpen APIࣗಈςετӡ༻͔Βͷֶͼ

  13. ໨࣍ ɾOpen APIͱؔ࿈༻ޠͷઆ໌ ▶︎ Open APIࣗಈςετӡ༻ ɾOpen APIࣗಈςετӡ༻͔Βͷֶͼ

  14. ςετͷ࿩ͷલʹSTORESͰ Open APIΛӡ༻͍ͯ͘͠Α͏ʹ ͳͬͨܦҢΛઆ໌

  15. STORESͷ ϑϩϯτ/όοΫΤϯυͷঢ়ଶ ϑϩϯτΤϯυ όοΫΤϯυ ˞Ұ෦"OHVMBS+4 ݱࡏ ϦΫΤετ Ϩεϙϯε +40/

  16. Open APIಋೖҎલɿ ͱ͋ΔҊ݅Ͱͷϑϩϯτ/όοΫΤϯυͷ։ൃ ϑϩϯτΤϯυ όοΫΤϯυ ˞Ұ෦"OHVMBS+4 ݱࡏ "1*ͷεΩʔϚ͕ ཉ͍͠Ͱ͢ʂ Ͳ͏͠Α͏ʜ

    
  17. Open APIಋೖҎલɿ ͱ͋ΔҊ݅Ͱͷϑϩϯτ/όοΫΤϯυͷ։ൃ ϑϩϯτΤϯυ όοΫΤϯυ ˞Ұ෦"OHVMBS+4 ݱࡏ ͋Γ͕ͱ͏ ͍͟͝·͢ ࠔ࿭

    FTBʹॻ͖·ͨ͠
  18. Open APIҎલɿ ͱ͋ΔҊ݅ͰͷAPIυΩϡϝϯτ

  19. markdownͷAPIυΩϡϝϯτΛ ࢓༷มߋͷͨͼʹ๨Εͣʹ ߋ৽͢Δͷ͠ΜͲ͍…

  20. ͕࣌ܦͪ… ⏳ Open APIΛ࢖ͬͨ։ൃ΁Ҡߦ

  21. Open APIಋೖҎ߱ɿ ͱ͋ΔҊ݅Ͱͷϑϩϯτ/όοΫΤϯυͷ։ൃ ϑϩϯτΤϯυ όοΫΤϯυ ˞Ұ෦"OHVMBS+4 ݱࡏ "1* εΩʔϚ Λڠۀͯ͠࡞੒

  22. Open APIಋೖҎ߱ɿ ͱ͋ΔҊ݅Ͱͷϑϩϯτ/όοΫΤϯυͷ։ൃ ϑϩϯτΤϯυ .PDLαʔόʔ ˞Ұ෦"OHVMBS+4 ݱࡏ IUUQBQJWCMPHT Ϩεϙϯε +40/

    ˞4XBHHFSπʔϧ 4UPQMJHIU4UVEJP࢖༻
  23. Α͏΍͘ςετͷ࿩

  24. APIεΩʔϚΛϑϩϯτ/όοΫΤϯ υͰڞ༗ग़དྷΔΑ͏ʹͳͬͨ ͱ͸͍͑… εΩʔϚͷ༗ޮੑνΣοΫΛ खಈͰ΍Δͱഁ୼ͦ͠͏

  25. ࣗಈԽͩʂʂʂʂ

  26. Open APIࣗಈςετ ςετίʔυ 0QFO"1* "1*υΩϡϝϯτ

  27. Open APIࣗಈςετ ςετίʔυ 0QFO"1* "1*υΩϡϝϯτ ίίͷ࢓૊ΈΛৄ͘͠

  28. RSpec ❌ Open APIͷৄࡉ committee-rails ͱ͍͏ gemΛ࢖ͬͯ RSpecͰAPIεΩʔϚ(YAML)ͱ APIͷࠩ෼ΛνΣοΫ

  29. committee-railsͷ࢖͍ํ 
 
 describe 'Api::V1::BlogsController', type: :request do include Committee::Rails::Test::Methods

    def committee_options @committee_options ||= { schema_path: Rails.root.join('APIεΩʔϚͷύε'), old_assert_behavior: false } end describe 'GET /api/v1/blogs' do it 'Ϩεϙϯε͕APIυΩϡϝϯτͱҰக͢Δ' do get '/api/v1/blogs' assert_response_schema_confirm end end end
  30. committee-railsͷ࢖͍ํ 
 
 describe 'Api::V1::BlogsController', type: :request do include Committee::Rails::Test::Methods

    def committee_options @committee_options ||= { schema_path: Rails.root.join('APIεΩʔϚͷύε'), old_assert_behavior: false } end describe 'GET /api/v1/blogs' do it 'Ϩεϙϯε͕APIυΩϡϝϯτͱҰக͢Δ' do get '/api/v1/blogs' assert_response_schema_confirm end end end APIεΩʔϚͷಡΈࠐΈ
  31. committee-railsͷ࢖͍ํ 
 
 describe 'Api::V1::BlogsController', type: :request do include Committee::Rails::Test::Methods

    def committee_options @committee_options ||= { schema_path: Rails.root.join('APIεΩʔϚͷύε'), old_assert_behavior: false } end describe 'GET /api/v1/blogs' do it 'Ϩεϙϯε͕APIυΩϡϝϯτͱҰக͢Δ' do get '/api/v1/blogs' assert_response_schema_confirm end end end εΩʔϚݕূ༻ϝιουͷఆٛݩΫϥεͷಡΈࠐΈ
  32. committee-railsͷ࢖͍ํ 
 
 describe 'Api::V1::BlogsController', type: :request do include Committee::Rails::Test::Methods

    def committee_options @committee_options ||= { schema_path: Rails.root.join('APIεΩʔϚͷύε'), old_assert_behavior: false } end describe 'GET /api/v1/blogs' do it 'Ϩεϙϯε͕APIυΩϡϝϯτͱҰக͢Δ' do get '/api/v1/blogs' assert_response_schema_confirm end end end APIεΩʔϚͱ࣮ࡍͷAPIͷ஋ͷݕূ
  33. ໨࣍ ɾOpen APIͱؔ࿈༻ޠͷઆ໌ ɾOpen APIࣗಈςετӡ༻ ɾOpen APIࣗಈςετӡ༻͔Βͷֶͼ

  34. ໨࣍ ɾOpen APIͱؔ࿈༻ޠͷઆ໌ ɾOpen APIࣗಈςετӡ༻ ▶︎ Open APIࣗಈςετӡ༻͔Βͷֶͼ

  35. ศརʹͳͬͨ൓໘ ৭ʑͱࢼߦࡨޡͨ͠
 ͜ͱ͕͋ͬͨͷͰ
 ͦͷ͓࿩Λ…

  36. ࣄҊ1: ͋Ε…ςετམͪͳ͘ͳ͍ʁ

  37. APIΛมߋͯ͠ɺ ࣮૷ͱεΩʔϚͷؒʹ ࠩ෼͕͋Δͷʹ CI͕௨ͬͯΔ…

  38. committee-railsͷམͱ݀͠⛳

  39. assert_request_schema (assert_response_schema)Ͱݕূ͞ΕΔύϥϝʔλ͸ required Ͱࢦఆͨ͠ϑΟʔϧυ͚ͩ post: summary: POST /api/v1/blogs description: ϒϩά࡞੒API

    tags: - blog requestBody: content: application/json: type: object properties: blog: type: object required: - title - content ݟͯΔͷίί͚ͩ
  40. ղܾࡦ

  41. ޙड़͢ΔͷͰҰ୴εΩοϓ

  42. ࣄҊ2: ҟৗܥͷAPIεΩʔϚͱ ͦͷςετͲ͏͢Δʁ

  43. ྫ͑͹͜Μͳ৔߹ͷ࿩ class BlogsController < ApplicationController ※தུ
 def create
 ※தུ begin

    ※ਖ਼ৗܥͷॲཧ rescue ::Mongoid::Errors::Validations render status: :bad_request, json: { errors: blog.errors } end end
  44. ྫ͑͹͜Μͳ৔߹ͷ࿩ class BlogsController < ApplicationController ※தུ
 def create
 ※தུ begin

    ※ਖ਼ৗܥͷॲཧ rescue ::Mongoid::Errors::Validations render status: :bad_request, json: { errors: blog.errors } end end ͦ΋ͦ΋ίίͷ෦෼ͷৄࡉΛͲ͜·Ͱ APIυΩϡϝϯτʹ࢒͔͢໰୊
  45. ղܾࡦ

  46. YAMLʹ͸࠷௿ݶͷεςʔλείʔυͱ Τϥʔ಺༰ͷ഑ྻ͕ฦͬͯ͘Δ͜ͱ͚ͩΛఆٛ responses: ※தུ '400': description: Bad Request content: application/json:

    schema: type: object properties: errors: type: array blogs: {} required: - errors Τϥʔ഑ྻ͕ඞਢͰ͋Δ ͜ͱ͚ͩఆٛ͢Ε͹Α͠ ͱͨ͠
  47. ͜ͷ෦෼ʹ͍ͭͯ͸౰֘API͕ ಛఆগ਺ͷ։ൃऀ޲͚(SSKDs)APIͳͷͰ ෆಛఆଟ਺ͷ։ൃऀ޲͚(LSUDs)API΄Ͳ γϏΞͰ͸ͳ͍఺͕͋Δ͔΋…

  48. ࣄҊ3: CSVΞοϓϩʔυ (μ΢ϯϩʔυ) APIͷ εΩʔϚͱͦͷςετ Ͳ͏͢Δʁ

  49. ͦ΋ͦ΋CSVϑΝΠϧͷத਎ ·ͰOpen APIͰఆٛ͢Δ΋ͷ ͳͷ͔ʁ

  50. ͜Μͳstack overflowΛൃݟ

  51. APIͷϨεϙϯεͷCSVΛ Open APIͷYAMLͰ Ͳ͏ॻ͘ͷʁతͳ࣭໰

  52. ͦͷճ౴͕ͪ͜Β

  53. ʻ༁ʼ Open API ࢓༷Ͱ͸ CSV ϨεϙϯεͷྫΛఏڙ ͍ͯ͠·ͤΜɻ ͦͷͨΊɺεΩʔϚ͸จࣈྻܕɺ จࣈྻͷ഑ྻɺ·ͨ͸ۭͷεΩʔϚͷ͍ͣΕ͔ ʹͳΓ·͢ɻ(͜Ε͸ʮ೚ҙͷ஋ʯΛҙຯ͠·͢)

  54. ʻ༁ʼ Open API ࢓༷Ͱ͸ CSV ϨεϙϯεͷྫΛఏڙ ͍ͯ͠·ͤΜɻ ͦͷͨΊɺεΩʔϚ͸จࣈྻܕɺ จࣈྻͷ഑ྻɺ·ͨ͸ۭͷεΩʔϚͷ͍ͣΕ͔ ʹͳΓ·͢ɻ(͜Ε͸ʮ೚ҙͷ஋ʯΛҙຯ͠·͢)

  55. ͔֬ʹ…ެࣜΛௐ΂ͯ΋ͦΕΒ͍͠ ྫ͸ͳ͔ͬͨ (2020.08࣌఺)

  56. ϑϩϯτ/όοΫΤϯυͰڞ༗͍ͨ͜͠ͱɺ ࣮૷ͱOpen APIͷఆٛͷҰகΛ Ͳ͜·Ͱݕূ͢΂͖͔ٞ࿦

  57. ղܾࡦ

  58. Content-Type ͕ text/csv ʹͳ͍ͬͯΔ͜ͱɺ εςʔλείʔυͷ֬ೝ ͕࠷௿ݶग़དྷΕ͹ OKͱ͢Δ͜ͱʹ requestBody: content: text/csv:

    schema: type: string responses: '200': description: OK content: text/csv: schema: type: string
  59. ݁ہͷͱ͜Ζ Ͳ͜·Ͱςετ͢Δʁ ໰୊

  60. required Ͱࢦఆ͠ͳ͔ͬͨ ϑΟʔϧυ͸ݕূग़དྷͳ͍͚Ͳ ͍͍ͷ͔ʁ

  61. required Ͱࢦఆ͑͢͠͞Ε͹ ҰԠνΣοΫ͸ग़དྷΔ͚Ͳ ͦΕͰ͍͍ͷ͔ʁ… (೰·͍͠

  62. ϑϩϯτΤϯυͱ όοΫΤϯυͰ ࿩͠߹ͬͨ݁Ռ

  63. ݁࿦

  64. RSpec࣮ߦ࣌ʹ required Ͱࢦఆ͠ͳ͍ͱ εΩʔϚνΣοΫग़དྷͳ͍ͷ͸ αʔόʔαΠυͷϥΠϒϥϦ (committee-rails)ͷ౎߹ʂ APIεΩʔϚʹ͸αʔόʔαΠυଆ ͷ౎߹ΛͳΔ΂͘൓ө͠ͳ͍

  65. ɾԿΛ ɾͲ͜·Ͱ ɾͲΜͳ෩ʹ APIεΩʔϚͱͯ͠ ఆٛ͠ɺςετ͍͔ͯ͘͠͸ ໌֬ͳਖ਼ղ͕ͳ͍ͷͰ೰Ή

  66. ղܾࡦ

  67. ਖ਼ղ͕ແ͍͔Βɺ ࣗ෼ͨͪͰ ϧʔϧΛ࡞Δ

  68. ελΠϧΨΠυΛ ࡞੒ͯࣾ͠಺esaͰγΣΞ ࣗ෼ͨͪͷ൑அ࣠Λ࣋ͭΑ͏ ʹ͍ͯ͠Δ

  69. ɾOpen APIͷςετʹcommittee-rails͸ ɹ༗༻✨ ɾͱ͸͍͑…Open API͸શͯΛࣗಈԽͨ͠ ɹςετͰΧόʔ͖͠Εͳ͍ͷͰ஫ҙ ɾOpen APIͷςετपΓ͸໌֬ͳਖ਼ղ͕ ɹͳ͍ͷͰɺͲ͜·ͰΛݕূ͢Δ͔͸ ɹͦͷΞϓϦͷཁ݅࣍ୈ

    ·ͱΊ
  70. ࠂ஌

  71. ͪ͜Β΋ੋඇνΣοΫͯ͠Έ͍ͯͩ͘͞ ςοΫϒϩά࢝Ί·ͨ͠

  72. ͝ਗ਼ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠