はじめに
この記事ではポートフォリオ作成中に学んだことを自分のために記録しています。
初学者のため理解が不十分なところがあるかもしれませんが、その場合はご指摘いただけると幸いです。
やりたいこと
- VCRを使ってAPIを使用しているメソッドのテストを書く
YouTube Data API v3を使用して動画情報を検索するヘルパーメソッドのテストをRSpecで書いていきます。
実装の詳細は下記の記事でまとめているのでよければご覧ください。
【Rails】Youtube APIを使ってIDで動画を検索する
VCRとは?
テストでのHTTP通信を1回目で記録しておき、以降のテストではその記録(カセットと呼ばれるyamlファイル)を使用することで通信の結果を再現してくれるgem。
2回目以降のテストは実際のHTTP通信を行わないため処理が早くなります。
また、APIを使用するテストにおいては何度テストを実行しても割り当てを消費しないというメリットがあります。
やること
- gemのインストール
- 設定ファイルの作成
- テストの記述
- 機密情報を環境変数に書き換え
gemのインストール
gem 'vcr'
gem 'webmock'
webmockも一緒にインストールします。
設定ファイルの作成
公式ではspec/spec_helper.rbに追記していましたが、作成中のポートフォリオではspec/supportにcapybaraの設定ファイルを置いているのでvcrも同様に設定ファイルを作成します。
require 'vcr'
VCR.configure do |config|
config.cassette_library_dir = "spec/vcr"
config.hook_into :webmock
config.configure_rspec_metadata!
config.default_cassette_options = { :erb => true }
config.allow_http_connections_when_no_cassette = true
end
設定の内容
config.cassette_library_dir = "spec/vcr"
カセットの保存先を指定
config.hook_into :webmock
webmockを使ってHTTP通信をスタブ化
config.configure_rspec_metadata!
RSpecでvcrを使う時の設定
config.default_cassette_options = { :erb => true }
カセット内でerb形式の記述を使うための設定(環境変数を使用するため)
config.allow_http_connections_when_no_cassette = true
カセットを使用しないテストではHTTP通信を許可
これをfalseにするとvcrを使わない他のテストが一部通らなくなってしまいました。
なお、spec/support内に作成した設定ファイルを有効にするにはspec/rails_helper.rbの変更が必要です。
Rails.root.glob('spec/support/**/*.rb').sort.each { |f| require f } #コメントアウトを外す
テストの記述
describe "#video_title" do
it "渡されたIDを持つ動画のタイトルを返すこと", :vcr => "youtube_success" do
expect(helper.video_title("HIgvP7B3Hg8")).to include "Runaway Baby"
end
end
vcrを使いたいテストに :vcr の記述を追加します。
自動的にカセット名をつけてくれるようですが、カセット名を指定して作成することもできます。(上記ではyoutube_successを指定)
機密情報を環境変数に書き換え
---
http_interactions:
- request:
method: get
uri: https://youtube.googleapis.com/youtube/v3/videos?id=HIgvP7B3Hg8&key=<%= ENV['YOUTUBE_API_KEY'] %>&part=snippet
body:
encoding: UTF-8
string: ''
headers:
・・・
初回のテストを実行するとこのようなカセットが作成されます。
上記の例ではヘッダーのURIにAPIキーが含まれていたので環境変数に書き換えました。
APIキーに限らずユーザー名・パスワードなどカセット内に機密情報が含まれる場合があるので要注意です。
カセット作成の際に機密情報をマスキングしてくれる Filter sensitive data という機能もあるのですが、これを使ってAPIキーを環境変数に置きかえようとしたところ謎の改行が入ってしまったので自力で変更しました。
GitHub ActionsでRSpecを実行する場合
- GitHubリポジトリのsecretsにAPIキーを登録
- ワークフローを定義しているファイルに環境変数を追記
env:
YOUTUBE_API_KEY: ${{ secrets.YOUTUBE_API_KEY }}
これでGitHub Actions上のRSpecでもカセットを使用してテストを実行することができました。
感想
できるだけ公式の情報を基に実装したのでドキュメントを読むのに時間がかかりましたが、その分理解して進められた気がします。
カセットの中身を見ることでリクエスト・レスポンスはこういうやりとりをしているんだな〜という勉強にもなりました。