VCRを使ってRSpecのwebmockを作成する方法
前回、RubyGemを自作してローカルで動かす方法について書きました。
yamano3201.hatenablog.jp
前回記事にも書きましたが、THETAのgemを自作しようとしています。
APIの中身はこちらで確認できます。
API Reference · v2.1 · API & SDK | RICOH THETA Developers
THETAのAPIを叩くためにはWi-Fiで接続する必要があります。
gemを作成している間ずっとWi-Fiで繋いでるわけにもいかないので、まずはmockについて調べました。
そしたらVCRという便利なものがありました。知らなかったです。
morizyun.github.io
VCRを使ってRSpecのwebmockを作成してみたのでメモしておきます。
gemを作成する目線で書いています。
VCRとは
VCRとは、webmock用のデータを自動で作成してくれるgemです。
実際にHTTP通信した結果を記録して、mockを作成してくれます。
gemspec作成
さっそくmockを作成する手順を書いていきます。
まずは、ruby_theta.gemspecに下の3つを追加します。
spec.add_development_dependency "vcr" spec.add_development_dependency "webmock" spec.add_dependency "httparty"
追加したらbundle installしておきます。
spec_helper.rb に追加
つづいてspec_helper.rb に下の内容を追加します。
require 'vcr' VCR.configure do |config| config.cassette_library_dir = "spec/fixtures/vcr_cassettes" config.hook_into :webmock config.default_cassette_options = { record: ENV.fetch('RECORD'){ :once }.to_sym } end
cassette_library_dir で指定したディレクトリにmockがymlとして作成されます。
default_cassette_options のrecord値にallを指定することで記録状態を変更することができます。
このオプションを指定しない場合は、初回のみHTTP通信を行いそのときの状態を記録してくれます。
2度目以降の実行ではmockを使用するのでHTTP通信は発生せず記録状態も変更されません。
作成中は記録状態を変更したいこともあるので、コマンドラインから切り替えられるようにrecodeの値に環境変数を指定できるようにしました。
qiita.com
後でも書きますが、RECORDにallを指定してテストを実行すると、記録状態を上書きして変更できます。
specファイル
例としてTHETAとセッションを張るspecを追加してみました。
spec/ruby_theta_spec.rb
require 'spec_helper' describe Theta do let(:theta) { Theta.new } context 'commands' do it 'startSession' do VCR.use_cassette("start_session") do response = theta.start_session expect(response.code).to eq(200) end end end end
ここでは200が返ってくることしかテストしてません。気が向いたらbodyの中身とかテストしてもいいかもしれません。
このタイミングでbundle exec rake spec してテストが失敗することを確認しておきます。
テスト対象コードを作成
上で書いたテストを成功させるための、テスト対象コードを作成していきます。
lib/ruby_theta/ruby_theta.rbにinitializeを書いていきます。
require "httparty" require "json" require "ruby_theta/modules/commands" class Theta module Modules; end include HTTParty include Theta::Modules::Commands def initialize(options={}) @theta_ip = options[:ip] || '192.168.1.1' self.class.base_uri @theta_ip end end
つづいて、lib/ruby_theta/modules/commands.rb にセッションを張るコードを作成します。
class Theta module Modules module Commands def start_session self.class.post("/osc/commands/execute", {:body => {"name" => "camera.startSession"}.to_json}) end end end end
RSpec実行
上でも書きましたがallを指定すると、記録状態を上書きして変更することができます。
実行前にTHETAとPCをWi-Fiで接続しておきます。
bundle exec rake spec or RECORD=all bundle exec rake spec
mockの中身
RSpecを実行すると、実際のHTTP通信の結果がyamlとして記録されます。
spec/fixtures/vcr_cassettes/start_session.yml
--- http_interactions: - request: method: post uri: http://192.168.1.1/osc/commands/execute body: encoding: UTF-8 string: '{"name":"camera.startSession","parameters":{}}' headers: Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: - "*/*" User-Agent: - Ruby response: status: code: 200 message: OK headers: Server: - server Cache-Control: - no-cache, no-store, max-age=0, must-revalidate Pragma: - no-cache Expires: - '0' Max-Age: - '0' X-Content-Type-Options: - nosniff Connection: - close Accept-Ranges: - bytes Content-Length: - '95' Content-Type: - application/json; charset=utf-8 body: encoding: UTF-8 string: '{"name":"camera.startSession","state":"done","results":{ "sessionId":"SID_0001","timeout":180}}' http_version: recorded_at: Sun, 24 Apr 2016 11:32:18 GMT recorded_with: VCR 3.0.1
requestとresponseの中身が確認できますね。
以上で1ケースですが、VCRを使ってRSpecのwebmockが作成できました。
最後に
ちゃんとテストを書きながらgemを作成したかったので、2,3年前に買ったRSpec Bookを読み返しました。
The RSpec Book (Professional Ruby Series)
- 作者: David Chelimsky,Dave Astels,Zach Dennis,角谷 信太郎,豊田 祐司,株式会社クイープ
- 出版社/メーカー: 翔泳社
- 発売日: 2012/02/22
- メディア: 大型本
- 購入: 7人 クリック: 141回
- この商品を含むブログ (19件) を見る
RSpecのバージョンが古かったのもあるし、mockについてはVCRが便利すぎたのでそこまで参考にはならなかったのですが、復習にはなりました。
mockを使った単体テストはこれでサクッと書けそうです。
セッション張って撮影して画像を取得してセッション閉じるといったようなユースケースごとのテストを、mockを使って書けると良いですね。
ユースケースごとのテストは実機でもテストできるようにしておくと、さらに安心ですかね。
気が向いたら、また書きます。