質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1917閲覧

APIのテスト(request_spec)を書いています。処理を共通化したいです。

thesnowman

総合スコア154

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2021/02/06 15:00

今現在以下のようにテストを書いています。正常系と、異常系でcontextを分けています。

質問
get '/api/books'というのが、itやexampleのブロック中じゃないと使えないらしく
ステータスコード200を返すというテストと、正しい数のデータを返すというテストのそれぞれの中でget '/api/books'を実行しています。
これを共通化するような手段はございますでしょうか?

RSpec.describe BooksController, type: :request do let!(:stores) { FactoryBot.create_list(:book, 10) } describe '#index' do context 'リクエストが成功した場合' do it 'ステータスコード200を返す' do get '/api/books' expect(response).to have_http_status(:ok) end it '正しい数のデータを返す' do get '/api/books' json = JSON.parse(response.body) expect(json.length).to eq(stores.length) end end context 'URLが存在しない場合' do it 'ステータスコード404を返す' do get '/api/wrong_path' expect(response).to have_http_status(:not_found) end end end end

以下のように、1つのテストの中に複数のアサーションを入れればいけますが、基本的に1テスト=1アサーションにしたいのでこれは避けたいと思います。

it '正しいレスポンスを返す' do get '/api/books' json = JSON.parse(response.body) expect(response).to have_http_status(:ok) expect(json.length).to eq(stores.length) end

※その他、質問以外の箇所でご指摘等あれば、いただけますと幸いでございます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

RSpec で DRI や処理の共通化を考えるのは基本的にお勧めしませんが、掲題の話であれば subject を使うと良いです。

RSpec.describe BooksController, type: :request do let!(:stores) { FactoryBot.create_list(:book, 10) } describe '#index' do context 'リクエストが成功した場合' do subject { get '/api/books' } it 'ステータスコード200を返す' do subject expect(response).to have_http_status(:ok) end # こっちでもいけるかな it { is_expected.to have_http_status(:ok) } it '正しい数のデータを返す' do subject json = JSON.parse(response.body) expect(json.length).to eq(stores.length) end end context 'URLが存在しない場合' do it 'ステータスコード404を返す' do get '/api/wrong_path' expect(response).to have_http_status(:not_found) end end end end

あくまで私個人の話ですが、 subject は「テスト対象を明確化する」ために使っていて、テストの最初に記載して後から読んでもわかりやすいようにしています。あまり共通化目的ではなく、一回だけの場合でも多用しています。

あともう一つ、json を取得して中身を確認するテストはよく書くので、こういうのもよくやります。

# spec/support/request_helper.rb # frozen_string_literal: true module RequestHelper module JsonHelpers def json return if response.body.blank? @json ||= Oj.load(response.body) end end end

このライブラリを request spec でのみ有効化します。

# spec/rails_helper.rb : RSpec.configure do |config| config.include RequestHelper::JsonHelpers, type: :request :

こうしておくと、 json = JSON.parse(response.body) みたいなコードをいちいち書かなくてもよくなります。

基本的に1テスト=1アサーションにしたい

というのはよくわかる話なのですが、テストが増えてくるととにかく example の数を減らして高速化したくなります。なので実際のところ例に挙げられている下の形にまとめられることは多いです。
テストの内容をシンプルに明確にしたいという意味では、仰る通りのやり方の方がいいんですけどね。

投稿2021/02/06 16:49

oakbow

総合スコア227

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問