3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RSpecでHTTP通信を記録するVCRの簡単な設定を考える

Last updated at Posted at 2024-10-04

はじめに

VCRという gem を使うと、RSpecのテスト実行中に API を直接叩かず、代わりに過去のリクエスト・レスポンスの記録(カセットと呼ばれるYAMLファイル)を繰り返し使用することができます。

VCRには色んな設定項目がありますが、個人的には結局はシンプルな使い方しかしないことが多いので、VCRの基本機能を簡単に使える設定を考えてみました。

VCRの細かい機能については公式ドキュメントやネット上のブログ記事をご参照ください。

実行環境

  • OS: LMDE 6 (faye) x86_64
  • ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]
  • rails-7.1.3.2
  • webmock-3.23.1
  • vcr-6.3.1
  • rspec-core-3.13.0
  • rspec-rails-6.1.3

やりたいこと

論より Run

手を動かして、色々試した結果をリポジトリに残しました。

設定ファイル

ここではspec/support/vcr.rbを作り、そこにVCRの設定を記述しています。

VCR自体の設定より、RSpecの設定を工夫しました。

spec/support/vcr.rb
require 'vcr'

# VCRの設定
VCR.configure do |c|
  c.cassette_library_dir = 'spec/cassettes'
  c.hook_into :webmock
  c.ignore_localhost = true
  c.ignore_hosts "chromedriver.storage.googleapis.com"
  c.default_cassette_options = {
    record: :once,
    match_requests_on: %i[method host path query]
  }
end

# RspecにVCR関連オプションを渡す仕組みと自動的にVCRを使いHTTP通信を記録する仕組みを定義
RSpec.configure do |c|
  c.around(:each, :vcr) do |example|
    cassette_path_segments = example.metadata[:file_path].sub(%r{.*/spec/}, '').sub('.rb', '').split(File::SEPARATOR)
    cassette_path = File.join(cassette_path_segments)

    case example.metadata
    in { vcr: true }
      vcr_overrides = {}
    in { vcr: { **vcr_overrides } }
      vcr_overrides[:record] = :new_episodes if vcr_overrides[:record] == true
    end

    vcr_overrides[:record] = :new_episodes if ENV['VCR_RECORD']

    VCR.use_cassette(cassette_path, vcr_overrides) { example.call }
  end
end

基本的な使い方

{ vcr: true }RSpecメタデータ に渡すことにより、VCRの機能を有効化します。

describe ExampleApiClient, vcr: true do
  describe "#list_todos" do
    it "responds with 200 status" do
      response = described_class.new.list_todos()

      expect(response.status).to eq(200)
      expect(response.body).to be_present
    end
  end
end

RSpecの仕様なのか :vcr メタデータの渡し方は複数あります。

細かい設定を指定せずに VCR を有効化したい場合は、以下のどれでもOKです。

  • describe ExampleApiClient, :vcr do ...
  • describe ExampleApiClient, vcr: true do ...
  • describe ExampleApiClient, vcr: {} do ...

カセットに Web 通信を記録する方法

カセットに Web 通信を記録する方法は2パターン想定しています。

  1. 一時的に{ vcr: { record: true } }RSpec の メタデータに渡す
  2. 一時的に環境変数VCR_RECORD=1をつけてrspec コマンドを実行する

カセットファイルは spec ファイルのファイル名を元に決定的に生成します。例えば、spec ファイルが ./spec/services/my_api_client_spec.rbの場合、カセット名は./spec/cassettes/services/my_api_client_spec.ymlとなります。

VCRオプションのオーバーライド

:recordオプションと:match_requests_onオプションはメタデータに渡しオーバーライドできるようにしてあります。

describe ExampleApiClient, vcr: { record: :new_episodes } do
  describe "#list_todos" do
    it "responds with 200 status" do
      # ...snip...
    end
  end
end

:tada::tada::tada:

VCR の configure_rspec_metadata!

VCRにはconfigure_rspec_metadata!メソッドが存在し、ここで実施したことと似たようなことができるようです。

VCR.configure do |c|
  # ...snip...
  c.configure_rspec_metadata!
end

configure_rspec_metadata!の提供する機能で問題ないのであれば、1行のコードで解決しますが、configure_rspec_metadata!は公式ドキュメントに詳しく説明されておらず挙動がよくわかりません。ソースコードを読んでみましたが、それでもよくわかりませんでした。

個人的には10行程度のコードで自作できるのであれば、自分で書いたほうがいいんじゃないかな〜と思ってます。

おわりに

RSpecVCRを簡単に使う方法を共有させていただきました。

なにか情報があれば、ぜひお便りください :bow:

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?