Gotanda.js#2 で request-specを利用していい感じにモックデータを作ってフロントエンド開発を楽にしたい! というLTをした
ご飯おいしくて最高だった。(GaiaX さんありがとうございました!)
ご飯うまい #gotandajs
— じょう (@joe_re) 2016, 1月 8
資料
www.slideshare.net
お正月休みにautomockというGemを作った。 joe-re.hatenablog.com
その紹介と、これで何を実現したいのか、という内容を中心にLTさせてもらった。
(js勉強会なのにgemかよという感じですが、まぁ中のコードのほとんどはjsなので。。)
automockとは何なのか
RSpecで書かれたrequest-specの実行時に発生したレスポンスを抽出し、WebAPIのレスポンスのモックデータを生成する。
そしてRailsが返却するレスポンスを奪い、モックデータに差し替えるプロキシサーバを立ち上げる。
SPAを開発する場面においては、サーバサイドとクライアントサイドで扱うコンテキストはWebAPIのIFしか共通しない。
そこから先の世界についてはお互い知らない。
つまりクライアントサイドにとってはWebAPIによって得られる情報が全てであり、本当に雲の向こうにデータがあるかどうかは知りようがない。
automockはこの性質を利用する。
サーバサイドにデータの用意をせずとも、request-specで書いた状態を再現することができる。
autodoc というrubygemsにインスパイアされて作ったもので、 autodocはドキュメントを生成するんだけど、こちらはモックデータを生成する。
どんなメリットがあるのか
前述の通りSPAにおいてのクライアントサイドにとっては、サーバサイドに本当にデータがあるかどうかは動作する上で直接関係がない。
ゆえに開発をする上で、面倒なデータの用意などせずとも誰でも描画の確認や微調整は簡単にできるように、パターン別にレスポンスをモックしよう!
という発想は昔からあって、具体的には以下のような実装がある。
stubbyは昔僕も使っていたのだけど、モックデータを自前で用意しないといけないので、実装との乖離を起こさないようにするのが大変だった。
automockを使うと、モックデータは実装を元に自動で生成されることになるので、実装との乖離は発生しない。
こうしてメンテナンスの煩わしさから解放されるのと、実際に受け取ったresponseからモックデータを作成する(人の手を介さない)ので、信頼性を保てる点が利点だ。
作りたい世界
フロントエンドエンジニアとサーバサイドエンジニアがそれぞれを実装する場面においては、
サーバ先輩「request-spec、cucumberでシナリオ書いて実行できるようにしたお。」
クライアント後輩「うっすうっす。automockでレスポンスモックして、シナリオに基づいて画面作っていくっす。」
みたいな会話ができる。
specを書くことでautomockが機能し、開発効率が上がる。
開発効率が上がることでspecを書くモチベーションが高まる。
specを書くことでまた開発効率が上がる。
というループを実現したい。
Gotanda.js
Gotanda.js、すごく温かみのある会で楽しかった。
主催はまさかりより温かみというモットーで運営しているそうで、LTの敷居も低い。
お近くのJSerはみんな参加すればいいと思う。
また次回もよろしくお願いします!
といいつつ懇親会で開催者とお話しして、次回は弊社で開催させてもらえることになりそうなので、次回は運営側に回りそうです。(よろしくお願いします!)
Railsのrequest-specからレスポンスを抽出して、サーバのレスポンスをモックできるgemを作った
明けましておめでとうございます!
正月中にswift覚えて、イケイケモバイルエンジニアに華麗な転身を遂げる予定でしたが結局swiftは1行も書きませんでした。
しかしswiftを代償に捧げた結果、Railsのrequest-specからレスポンスを抽出して、サーバのレスポンスをモックできるautomockというgemができました。
automock is 何
WebAPIに対しては、極力中のロジックに関与せず(モックも極力使わずに)、特定のリクエストを投げたら決まったレスポンスが返ることをブラックボックスにテストするのがいいよね、というベストプラクティスがあり、この形式で書かれたものはrequest-specと呼ばれています。 これに関しては以下の記事が詳しいです。
RSpecでRequest Describer - Qiita
このテストは実際にrequestを投げてresponseを受け取るので、HTTPで流れる情報の全てを扱うことができます。
Rspecには autodocという id:r7kamura さんの作ったgemがあって、これはrequest-specのテストを実行するとドキュメントが自動生成されるという最高のユーザ体験を提供してくれます。
このgemの発想は最高で、ドキュメントと実装の乖離は解消されて、何よりテストを書くモチベーションが格段に向上します。
autodocの「テストを書いたらドキュメントが生成される」という発想にインスパイアされて作ったのがautomockです。 これはRailsが返すレスポンスを奪い取って、request-specから抽出したレスポンスに置き換えることができます。
使い方
インストール方法などはドキュメントをご参照いただければ。 Rubyな世界でのインターフェースはautodocとほぼ一緒です。
responseを抽出すると、こんな感じでファイルができます。
$ ls -l automock/data/api/v1/users/ -rw-r--r-- 1 masato_noguchi staff 520 Jan 3 19:29 DELETE_receives_204.json -rw-r--r-- 1 masato_noguchi staff 535 Jan 3 19:27 GET_receives_200_and_users_json.json -rw-r--r-- 1 masato_noguchi staff 520 Jan 3 19:29 POST_receives_201.json -rw-r--r-- 1 masato_noguchi staff 520 Jan 3 19:29 PUT_receives_200.json
ファイルパスはAPIのパスで、ファイル名は method名 + it のタイトルになります。 もっと見やすい形式がある気がしてならないので、アドバイスください。
automockはプロキシサーバと、モック対象のレスポンスを管理する画面とでサーバを2つ起動します。 サーバを起動し、localhost:8000にアクセスすると管理画面を見ることができます。 (portは起動時の引数で変更可能)
左が未選択のファイルで、右が選択済みのファイルのリストになります。 (雑な感じのUIですみません。暇を見つけてもうちょいどうにかします。)
proxy serverはデフォルトで8001番で起動しています。
開発時はここにアクセスしていきます。
何も選択していない状態であれば、Railsのレスポンスがそのまま返ってきます。
例えば GET /api/v1/users
を例にとって見てみます。
全てを未選択にして、
レスポンスはこんな感じ。
今度はGET /api/v1/uesrs
選択状態にします。
そうすると、request-specから抽出したレスポンスが返却されるようになります。
動機とか狙いとか今後の展望とか
フロントエンド開発時にレスポンスをモックするという発想はかなり昔からあって、1年ぐらい前には僕はstubbyとかを使ってました。
しかしこの手法はあまり流行っていない感覚があって、モックデータを自前で用意する必要がある以上、実装との乖離が発生してしまい、メンテナンスコストがかかってしまうところが問題なのかなぁ、と思っています。
automockを使えば基本的にはrequest specを書いていれば、後は実行する時にボタンをぽちぽち押すだけになります。
SPAとWebAPIが全盛のこの時代においては、サーバサイドとクライアントサイドの境界線ははっきりしてきました。
機能開発やバグの修正時にも、サーバサイドとクライアントサイドを別々に実装していくことが多くなってきていて、ともすればサーバサイドとフロントエンドを開発する人は別だったりします。
そんな時に間を取りもつ係になりたい。人類の役に立ちたい。
今後の展望としては、現在uriしかマッチングのキーにしてないので、プログラマブルに条件を組めるようにしたいなー、とか、現状Railsしか対応してないけど他のフレームワークにも対応したいなー(そもそもProxy部分はnodejsで書いているのでRailsに依存していない)、とかざっくりいろいろあります。
まだドッグフーディングできてなくて、いっぱいバグありそう。 もし使ってみてくれた方いましたら、フィードバックいただけたら嬉しいです。
新宿.rb#30で、僕はどうしてもlibsassが使いたかったんだ!というLTをした
ザックが来ていて、写真を撮ってもらえて浮かれた。
資料
www.slideshare.net
割りと赤裸々に、Libsass on Sprockets を実現するために苦しんだ話をさせてもらった。
これは西日暮里.rbでもLTさせてもらったsprocketsを捨てたい話の延長線の話で、gulpを使ってフロントエンドでビルドをした成果物(assets)をapp/assetsに配置する時の苦労話のstyle編。
具体的には
- 複数エントリーポイントの差分ビルドをどうやって実現するか
- asset_pathヘルパーをどうやって解決するか
の2つの問題があった。
複数エントリーポイントの差分ビルドをどうやって実現するか
これはproductionデプロイ時には関係なくて、開発時の悩みの話。
開発時のSprocketsさんは、依存関係を定義しておけば、リクエストされたタイミングでassetsを動的にコンパイルする。
styleに複数エントリーポイントがあってもなくても、リクエストされた段階で依存関係を解決して、assetsのurlを提供してくれる。
なのでファイルの変更を監視する必要はない。
しかしSprocketsさんに頼らずにgulpでビルドする場合には事前にビルドすることになるため、app/assetsに出力した段階で依存関係を解決しておく必要がある。
つまり、ファイルが変更されたタイミングでの再ビルドが必要になる。
コードベースが小さければ、大元のエントリーポイントを1つだけ設けて、全てビルドしてapp/assetsに配置すればいいのだけど、コードベースが大きくなってくると、1回あたりのビルド時間が長くなってしまう。
開発時にファイルの変更が入るたびに1s以上待つようになると、非常に苦痛で発狂しかねない。
ということで差分ビルドする必要がある。
そのためにはgulpタスク内でsassの依存関係(@import)を辿れるようにすればいい、ということでやってみたのが以下の記事。
最善策かどうかは置いといて、現状とりあえずうまく動いている。
asset_pathヘルパーをどうやって解決するか
sprockets外しで避けては通れない、asset_pathヘルパーをどうやって解決するか、という問題。
sprocketsはassetsファイルに変更があった場合には、ブラウザのキャッシュを効かせないため、ファイル名にdigestを付与する。
このdigestを無視して記述することができるのが、asset_pathヘルパーメソッドで、Sprocketsでruby-sassを使ってビルドする際には このヘルパーメソッドが使える。
だけどasset_pathはあくまでSprocketsの仕組みで、libsassには当然ないし、そもそもgulpでビルドした段階ではsprocketsのdigestを知ることはできない。
これをSprocketsのRailに乗っかったままどうやって解決するか、というのは下記の記事が参考になる。
しかし開発段階で、.css.erbなファイルにはしたくない。
影響範囲が大きいので、imageをpublicに配置するようにするのもどうかな。。
あとある事情で、どうしてもruby-sassを撲滅したい理由もあった。(つまり.scssなファイルはapp/assetsには置きたくない。(詳しくはLT資料を参考)
そのためにどうしたか、というのが以下のqiitaの記事。
簡単に言うと
gulpで無理やり.css.erbに変換するか。erbなら余計な処理もなくて軽いでしょ
という雑な対応。まぁうまく動いた。
これもっとかっこいい解決策あるだろ、という感じがする。
具体的にはsprocketsでcssのプロセッサーを自作すればいいのでは?と思っているのだけど、sprockets力が足りなくてそこまでには至っていません。
かっこいい解決策をお持ちの方は是非教えてください!
さいごに
新宿.rb、運営されてる方々、参加された方々お疲れ様でした!
次回以降も是非参加させていただきたいと思っています。
よろしくお願いします <(_ _)>