俺流Request specのフォーマット

## 背景

最近、個人でRuby on Railsを使ってWebサービスのAPIを開発しています。
その際にRSpecを使って主にRequest specを書きました。
spec形式の書き方で試行錯誤したので公開してみます。

## 俺流Request spec

まずは、コードを共有させていただきます。

組織のCRADを実装したOrganization APIのrequest specです。
rails_helperやメソッドに処理をさせているところもあって、
わかりづらいかもしれませんが動いているコードの一部をほぼそのまま持ってきました。

```organizations_request_spec.rb
RSpec.describe 'Organizations', type: :request do
  # 共通のデータ
  let!(:user) { create(:user) }
  let!(:uneditable_user) { create(:user) }
  let!(:organization) { create(:organization) }

  let(:prepare_data) { -> {} }
  let(:headers) { {} }
  let(:params) { {} }

  before do
    prepare_data.call
  end

  describe 'GET /index' do
    before { get organizations_path, headers:, params: }

    context '認証時' do
      let(:headers) { user.create_new_auth_token }

      context 'クエリパラメータが指定されていない場合' do
        it 'リクエストが成功すること' do
          expect(response).to have_http_status(:ok)
        end

        it 'マイボックスが含まれないこと' do
          expect(parsed_response.organizations).not_to include(serialize_organization(user.mybox))
        end

        it 'アクセスできるグループが含まれていること' do
          expect(parsed_response.organizations).to include(serialize_organization(organization))
        end

        it 'アクセスできないグループが含まれないこと' do
          expect(parsed_response.organizations).not_to include(serialize_organization(inaccessible_organization))
        end
      end

      describe 'クエリパラメータを指定' do
        context 'include_myboxパラメータがtrueの場合' do
          let(:params) { { include_mybox: true } }

          it 'リクエストに成功すること' do
            expect(response).to have_http_status(:ok)
          end

          it 'マイボックスが含まれること' do
            expect(parsed_response.organizations).to include(serialize_organization(user.mybox))
          end
        end
      end
    end

    context '未認証時' do
      it '401エラーになること' do
        expect(response).to have_http_status(:unauthorized)
      end
    end
  end

  describe 'GET /show' do
    let(:request_organization) {}
    before { get organization_path(request_organization.name), headers:, params: }

    context '認証時' do
      let(:headers) { user.create_new_auth_token }

      context 'アクセス権限があるグループの場合' do
        let(:request_organization) { organization }

        it 'リクエストが成功すること' do
          expect(response).to have_http_status(:ok)
        end

        it 'リクエストしたグループが返却されること' do
          expect(parsed_response.name).to eq(request_organization.name)
        end
      end

      context 'アクセス権限がないグループの場合' do
        let(:request_organization) { inaccessible_organization }

        it '404エラーになること' do
          expect(response).to have_http_status(:not_found)
        end
      end
    end

    context '未認証時' do
      let(:request_organization) { organization }

      it '401エラーになること' do
        expect(response).to have_http_status(:unauthorized)
      end
    end
  end

```

## 目指したもの

**describeやcontextで定義した内容をその直下に実装すること**を目指しました。
普通に書くと、どうしてもAPIのリクエスト（上記のコードだと `get organizations_path, headers:, params:` )がit付近で呼び出す感じになってしまう。

こんな感じ

```好みじゃない書き方.rb
describe 'GET /index' do
    context '認証時' do
      context 'クエリパラメータが指定されていない場合' do
        before { get organizations_path, headers: user.create_new_auth_token }

        it 'リクエストが成功すること' do
          expect(response).to have_http_status(:ok)
        end
```


これががどうもRSpecらしくないような気がしてしまって
`let` を駆使して記述してみました。


```好みな書き方.rb
  describe 'GET /index' do
    before { get organizations_path, headers:, params: }

    context '認証時' do
      let(:headers) { user.create_new_auth_token }

      context 'クエリパラメータが指定されていない場合' do
        it 'リクエストが成功すること' do
          expect(response).to have_http_status(:ok)
        end
```

どちらがお好みですか？


## 実際に書いてみて

今のところ書きやすいし読みやすい。そして、問題も起きていません。
ただ、あまり同じ書き方をしている例が見つけられなかったので、少し不安ではあります。
俺流はだいたい後々後悔するので...（個人開発では、わかっててもやってしまう）

なので、まだオススメはしません。お見せするだけ。