赤黒木の代償として実装が複雑という話が出てきており、これはSedgewick先生がCourseraの講座でも言っていたことを思い出した。特に2008年のLeft-Leaning Red Black Treeの発表以前、とあるデータベースプロバイダが赤黒木の削除の実装を誤ったために障害を起こしたという話。(木の高さを常に一定に保つことが保証されていないHibbard deletionを採用したので木の高さが高くなりすぎ、再構築のためにシステムダウンするほどだった)
committeeにはrequest validation, coercion, test assertion, stub機能などありますが同プロジェクトで使った機能はCommittee::Middleware::ResponseValidationのみです。これは名前の通りRack middlewareであり、アプリケーション(この場合は我々が提供するAPI server)のレスポンスを検証します。
test assertionをすべてのテストに都度書いていくのは面倒なため、API定義が書かれているすべてのエンドポイントについて自動的に検証を走らせるようにしています。OpenAPIによる定義が書かれていない場合は検証は行われません。
# config/environments/test.rbRails.application.configure do
config.middleware.use(Committee::Middleware::ResponseValidation, schema_path: Rails.root.join("openapi/index.yaml"), raise: true)
end
1) #GET /:language/api/users/:idFailure/Error: subject { get "/ja/api/users/#{user.id}" }
Committee::InvalidResponse:
trueclass is TrueClass but it's not valid integer in #/components/schemas/User/properties/is_teacher # ./spec/requests/api/users_spec.rb:160:in `block (3 levels) in <top (required)>'# ------------------# --- Caused by: ---# OpenAPIParser::ValidateError:# true class is TrueClass but it's not valid integer in #/components/schemas/User/properties/is_teacher# ./spec/requests/api/users_spec.rb:160:in `block (3 levels) in <top (required)>'
これでテスト実行時にOpen API specificationと実装の乖離に気づけるようになりました。
…本当でしょうか?
実はこの検証だけでは実装との乖離を完全に防ぐことはできません。用意されたテストデータに対してしかテストを行っていないためです。たとえば上記コードでは user というテストデータを生成してそのデータに基づいてレスポンスを返すAPIを検証していますが、もしこのデータが変わったとしてもAPIが定義通りに動くことは保証しません。開発者が想定した正常系ド真ん中のテストデータによってしか動かない可能性もあります。