Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
JSON Schema と 
API テスト 
2014/08/29 (Sat) 
YAPC::Asia Tokyo 2014 
清水 直樹
自己紹介 
• 清水 直樹 (@deme0607) 
• SWET @ DeNA 
• SWET: Software Engineer in Test 
• 2013年 4月 新卒入社
自己紹介② 
• テスト用のライブラリ 
• randexp-multibyte 
• https://rubygems.org/gems/randexp-multibyte 
• Rubyist Magazine 「Ruby 初心者の新卒エン...
今日の話 
• API 結合テストとは? 
• JSON Schema とは? 
• JSON Schema を API 結合テストに活用
API結合テスト
API (単体) テスト 
API 
Server 
Test 
1. テストデータをリクエスト 
として送信 
[request] 
GET api/user 
id: 1 
[response] 
id: 1 
name: deme0607...
それだけで十分? 
• API は様々なコンポーネントと結合して動作 
API 
Server 
User 
API 
Server 
DB 
Load Balancer / Reverse Proxy 
[request] [response...
API結合テスト 
• 実環境で動作しているAPIを実際のクライアン 
トと同じ経路からテスト 
API 
Server 
結合 
テスト 
API 
Server 
DB 
Load Balancer / Reverse Proxy 
[re...
API結合テスト 実施フロー 
• 仕様ドキュメントから、正常系・異常系テストリク 
エストデータを作成 
• リクエストデータ ≒ テストケース 
• 仕様とリクエストデータから、期待するレスポンス 
を定義 
• テスト用クライアントからリ...
今日の話 
• API 結合テストとは? 
• JSON Schema とは? 
• JSON Schema を API 結合テストに活用
JSON Schema とは? 
• JSONで表現されるデータに対してデータ定義 
するSchemaを記述する枠組み 
• json-schema.org で公開されている 
• 現在、draft4
例 
• JSON データ 
! 
• 日本語の仕様 
! 
! 
• JSON Schema 
{ 
"id": 
12345678, 
"name": 
"Naoki 
Shimizu", 
"email": 
"deme0607@exam...
JSON Schema, 何が嬉しい? 
• データの検証にも使える 
• Machine Readable なデータの定義ができるので、Validatorの 
入力にできる 
• 仕様と実装の乖離が減る 
• 上記のようなValidatorを...
• Validator を使ってAPIサーバのリクエスト・レスポンスのSchemaとの整合性を検証 
• perl-JSV: Perlのデータに対する JSON Schema Validator 
• https://github.com/zi...
JSON Schema について詳しくは 
WEB+DB Press vol.82 特集1 「Web API デザインの鉄則」をご覧ください
今日の話 
• API 結合テストとは? 
• JSON Schema とは? 
• JSON Schema を API 結合テストに活用
(再) API結合テスト 実施フロー 
• 仕様ドキュメントから、正常系・異常系テストリク 
エストデータを作成 
• リクエストデータ ≒ テストケース 
• 仕様とリクエストデータから、期待するレスポンス 
を定義 
• テスト用クライアン...
API 仕様が JSON Schema 
で書かれていたら?
• 正常系・異常系のリクエストデータを自動生 
成できるかも? 
• 仕様とリクエストデータから、期待するレス 
ポンスも自動で定義できるかも? 
• 仕様から、クライアントも自動生成できるか 
も?
APIの結合テスト、 
全部自動でできちゃう?
そんなうまい話はありません
だが、今よりもっと楽する 
ことはできるはず
やりたいこと 
• JSON Schema で記述された API の仕様から 
• 正常系・異常系のリクエストデータ生成 
• 期待するレスポンスの定義 
• APIクライアントの生成
json-fuzz-generator 
• JSON Schema から、そのSchemaに対して正常 
系・異常系のデータを生成 
• Ruby のライブラリ 
• 異常系のデータはFuzzingに基いている 
• 誤りの含まれたデータを次...
デモ
正常系データの生成 
# 
require 
"json-­‐fuzz-­‐generator" 
# 
JSON::Fuzz::Generator.default_param(schema_file) 
{ 
"id" 
=> 
0, 
"n...
異常系データの生成 
[ 
["sample", 
"array"], 
true, 
73, 
nil, 
0.34259093948835795, 
"hoge", 
{"id"=>"a", 
"name"=>"hoge", 
"birth...
JSON Schema から自動生成 
したリクエストデータは、 
テストケースとして十分か?
残念ながらNoです
• ドメイン知識に基づくケースは生成できない 
• JSON Schemaではデータのフォーマット以上のこ 
とは定義できない 
• (例) 友達にメッセージを送るAPIで、「友達でない 
ユーザへのメッセージ送信」という異常系リクエス 
ト ...
API結合テスト 自動化への道 
• リクエストデータの生成 
• レスポンスの検証 
• APIクライアントの生成
リクエストデータの生成 
• フォーマットによるもの 
• json-fuzz-generator によって生成できる 
• ドメインの特性によるもの 
• JSON Schema からの生成は不可能
レスポンスの検証 
• フォーマット 
• JSON Schema による Validator で可能 
• perl-JSV (Perl), json-schema (Ruby) 
• APIのロジックに基づくもの 
• 例: リクエストで指...
APIクライアントの自動生成 
• jsonism で生成可能 (Ruby ライブラリ) 
client 
= 
Jsonism::Client.new(schema: 
schema) 
client.methods(false) 
#=> ...
API結合テスト 自動化への道 
リクエスト生成レスポンス検証 
クライアント 
生成 
フォーマットドメイン特性フォーマットロジック 
fuzz-json-generator 
★ perl-JSV 
json-schema ★ jsonis...
まとめ 
• JSON Schema で仕様を記述すると開発でも 
テストでも利点がある 
• JSON Schema を使って、API結合テストの自 
動化に取り組んでいる 
• 自動化が進むと、より高品質な開発・テスト 
に集中できる
ありがとうございました 
• json-fuzz-generator 
• https://rubygems.org/gems/json-fuzz-generator 
• Twitter 
• https://twitter.com/deme...
json-fuzz-generator要改善点 
• 正常系データの複数生成 
• 例: 各種境界値 
• 現状、最大値・最小値が定義されているような数値は範囲内のラン 
ダム値を返すような実装 
• 未対応のschema 
• pattern...
• 異常系パラメータの精度向上 
• Fuzzingでは桁あふれを起こしうる数値や文字化けを起こしやすい文 
字列を入力することが効果的 
• 現状は単純な異常値しか生成してない 
• stringを期待するデータにintegerを出力 
• ...
Upcoming SlideShare
Loading in …5
×

JSON Schema と API テスト YAPC::Asia Tokyo 2014

12,492 views

Published on

YAPC::Asia Tokyo 2014 Talk
https://www.youtube.com/watch?v=bxNMk6XP2JA

Published in: Technology
  • Be the first to comment

JSON Schema と API テスト YAPC::Asia Tokyo 2014

  1. 1. JSON Schema と API テスト 2014/08/29 (Sat) YAPC::Asia Tokyo 2014 清水 直樹
  2. 2. 自己紹介 • 清水 直樹 (@deme0607) • SWET @ DeNA • SWET: Software Engineer in Test • 2013年 4月 新卒入社
  3. 3. 自己紹介② • テスト用のライブラリ • randexp-multibyte • https://rubygems.org/gems/randexp-multibyte • Rubyist Magazine 「Ruby 初心者の新卒エンジニアが gem パッケージ公開に至るまで」 • http://magazine.rubyist.net/?0046- RandexMultibyteGem
  4. 4. 今日の話 • API 結合テストとは? • JSON Schema とは? • JSON Schema を API 結合テストに活用
  5. 5. API結合テスト
  6. 6. API (単体) テスト API Server Test 1. テストデータをリクエスト として送信 [request] GET api/user id: 1 [response] id: 1 name: deme0607 email: deme0607@example.com 2. レスポンスデータを期待結果 と比較
  7. 7. それだけで十分? • API は様々なコンポーネントと結合して動作 API Server User API Server DB Load Balancer / Reverse Proxy [request] [response]
  8. 8. API結合テスト • 実環境で動作しているAPIを実際のクライアン トと同じ経路からテスト API Server 結合 テスト API Server DB Load Balancer / Reverse Proxy [request] [response]
  9. 9. API結合テスト 実施フロー • 仕様ドキュメントから、正常系・異常系テストリク エストデータを作成 • リクエストデータ ≒ テストケース • 仕様とリクエストデータから、期待するレスポンス を定義 • テスト用クライアントからリクエストを送り、レス ポンスを検証
  10. 10. 今日の話 • API 結合テストとは? • JSON Schema とは? • JSON Schema を API 結合テストに活用
  11. 11. JSON Schema とは? • JSONで表現されるデータに対してデータ定義 するSchemaを記述する枠組み • json-schema.org で公開されている • 現在、draft4
  12. 12. 例 • JSON データ ! • 日本語の仕様 ! ! • JSON Schema { "id": 12345678, "name": "Naoki Shimizu", "email": "deme0607@example.com" } ! { "type": "object", "properties": { "id": { "type": "integer", "minimum": 10000000 }, "name": { "type": "string" }, "email": { "type": "string", "format": "email" } } } フィールド型詳細 id integer ユーザのidを表す。 10000000以上の値。 name string ユーザの名前を表す文字列。 email string ユーザのメールアドレス。 RFC5322形式の文字列。
  13. 13. JSON Schema, 何が嬉しい? • データの検証にも使える • Machine Readable なデータの定義ができるので、Validatorの 入力にできる • 仕様と実装の乖離が減る • 上記のようなValidatorを活用し、APIのリクエスト・レスポン スを検証 • グローバル対応 • JSONは機械にも人間にも読みやすい
  14. 14. • Validator を使ってAPIサーバのリクエスト・レスポンスのSchemaとの整合性を検証 • perl-JSV: Perlのデータに対する JSON Schema Validator • https://github.com/zigorou/perl-JSV use JSON; use JSV::Validator; my $request = { id => 12345678, name => "Naoki Shimizu", email => "deme0607@example.com", }; my $schema = decode_json($json_file); my $validator = JSV::Validator-­‐>new; my $result = $validator-­‐>validate($schema, $request); if ($result) { ...
  15. 15. JSON Schema について詳しくは WEB+DB Press vol.82 特集1 「Web API デザインの鉄則」をご覧ください
  16. 16. 今日の話 • API 結合テストとは? • JSON Schema とは? • JSON Schema を API 結合テストに活用
  17. 17. (再) API結合テスト 実施フロー • 仕様ドキュメントから、正常系・異常系テストリク エストデータを作成 • リクエストデータ ≒ テストケース • 仕様とリクエストデータから、期待するレスポンス を定義 • テスト用クライアントからリクエストを送り、レス ポンスを検証
  18. 18. API 仕様が JSON Schema で書かれていたら?
  19. 19. • 正常系・異常系のリクエストデータを自動生 成できるかも? • 仕様とリクエストデータから、期待するレス ポンスも自動で定義できるかも? • 仕様から、クライアントも自動生成できるか も?
  20. 20. APIの結合テスト、 全部自動でできちゃう?
  21. 21. そんなうまい話はありません
  22. 22. だが、今よりもっと楽する ことはできるはず
  23. 23. やりたいこと • JSON Schema で記述された API の仕様から • 正常系・異常系のリクエストデータ生成 • 期待するレスポンスの定義 • APIクライアントの生成
  24. 24. json-fuzz-generator • JSON Schema から、そのSchemaに対して正常 系・異常系のデータを生成 • Ruby のライブラリ • 異常系のデータはFuzzingに基いている • 誤りの含まれたデータを次々に入力するテスト 手法
  25. 25. デモ
  26. 26. 正常系データの生成 # require "json-­‐fuzz-­‐generator" # JSON::Fuzz::Generator.default_param(schema_file) { "id" => 0, "name" => "hoge", "birthday” => "1992-­‐06-­‐27" } JSON Schema の入力 ! { "title": "Basic Schema", "type": "object", "properties": { "id" : { "type": "integer", "minimum": 0 }, "name": { "type": "string" }, "birthday": { "type": "string", "format": "date" } } } 正常系データの出力
  27. 27. 異常系データの生成 [ ["sample", "array"], true, 73, nil, 0.34259093948835795, "hoge", {"id"=>"a", "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>"1", "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0.1, "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>["sample", "array"], "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>false, "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>nil, "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0.0, "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>{}, "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>"hoge", "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>-­‐1, "name"=>"hoge", "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0, "name"=>["sample", "array"], “birthday"=>"1992-­‐06-­‐27"}, ! {"id"=>0, "name"=>true, "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0, "name"=>97, "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0, "name"=>nil, "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0, "name"=>0.7547537108664406, "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0, "name"=>{}, "birthday"=>"1992-­‐06-­‐27"}, {"id"=>0, "name"=>"hoge", "birthday"=>["sample", "array"]}, {"id"=>0, "name"=>"hoge", "birthday"=>false}, {"id"=>0, "name"=>"hoge", "birthday"=>11}, {"id"=>0, "name"=>"hoge", "birthday"=>nil}, {"id"=>0, "name"=>"hoge", "birthday"=>0.5380909041403419}, {"id"=>0, "name"=>"hoge", "birthday"=>{}}, {"id"=>0, "name"=>"hoge", "birthday"=>"2010-­‐01-­‐32"}, {"id"=>0, "name"=>"hoge", "birthday"=>"n2010-­‐01-­‐01"}, {"id"=>0, "name"=>"hoge", "birthday"=>"2010-­‐1-­‐01"}, {"id"=>0, "name"=>"hoge", "birthday"=>"2010-­‐01-­‐1"}, {"id"=>0, "name"=>"hoge", "birthday"=>"2010-­‐01-­‐01n"}, ]
  28. 28. JSON Schema から自動生成 したリクエストデータは、 テストケースとして十分か?
  29. 29. 残念ながらNoです
  30. 30. • ドメイン知識に基づくケースは生成できない • JSON Schemaではデータのフォーマット以上のこ とは定義できない • (例) 友達にメッセージを送るAPIで、「友達でない ユーザへのメッセージ送信」という異常系リクエス ト • ドメイン知識が必要なケースの設計に集中できる
  31. 31. API結合テスト 自動化への道 • リクエストデータの生成 • レスポンスの検証 • APIクライアントの生成
  32. 32. リクエストデータの生成 • フォーマットによるもの • json-fuzz-generator によって生成できる • ドメインの特性によるもの • JSON Schema からの生成は不可能
  33. 33. レスポンスの検証 • フォーマット • JSON Schema による Validator で可能 • perl-JSV (Perl), json-schema (Ruby) • APIのロジックに基づくもの • 例: リクエストで指定したユーザidのデータが返ってくる • JSON Schema からは不可能
  34. 34. APIクライアントの自動生成 • jsonism で生成可能 (Ruby ライブラリ) client = Jsonism::Client.new(schema: schema) client.methods(false) #=> [:create_app, :delete_app, :info_app, :list_app, :update_app] # GET /apps client.list_app # GET /apps/1 client.info_app(id: 1) # POST /apps client.create_app(name: "alpha") # PATCH /apps/1 client.update_app(id: 1, name: "bravo") # DELETE /apps/1 client.delete_app(id: 1)
  35. 35. API結合テスト 自動化への道 リクエスト生成レスポンス検証 クライアント 生成 フォーマットドメイン特性フォーマットロジック fuzz-json-generator ★ perl-JSV json-schema ★ jsonism ドメイン知識やロジック部分に集中したテスト設計が可能
  36. 36. まとめ • JSON Schema で仕様を記述すると開発でも テストでも利点がある • JSON Schema を使って、API結合テストの自 動化に取り組んでいる • 自動化が進むと、より高品質な開発・テスト に集中できる
  37. 37. ありがとうございました • json-fuzz-generator • https://rubygems.org/gems/json-fuzz-generator • Twitter • https://twitter.com/deme0607
  38. 38. json-fuzz-generator要改善点 • 正常系データの複数生成 • 例: 各種境界値 • 現状、最大値・最小値が定義されているような数値は範囲内のラン ダム値を返すような実装 • 未対応のschema • pattern (正規表現) • patternにマッチする/しない文字列を自動生成 • $ref (参照) 系
  39. 39. • 異常系パラメータの精度向上 • Fuzzingでは桁あふれを起こしうる数値や文字化けを起こしやすい文 字列を入力することが効果的 • 現状は単純な異常値しか生成してない • stringを期待するデータにintegerを出力 • 最大値・最小値の範囲から外れる値を出力 • プロダクトに基づくパラメータの生成 • 過去にバリデーション漏れ・問題を起こしたパラメータなど • ライブラリに同梱するのではなく、ユーザが動的に追加できる仕組 み

×