【RSpecテスト】システムスペック・リクエストスペック

## システムスペック・リクエストスペックとは何か？
どちらもRailsアプリケーションのテストで使用されるが、
目的やテスト範囲が異なる。

---

## **1. システムスペック (System Spec)**

### **概要**
- システム全体の動作をテストする。
- **ブラウザを操作するユーザーの視点**で、アプリケーション全体の動作を確認するテスト。

### **特徴**
- 実際のブラウザ操作に近いテストが可能（Capybaraを利用）。
- **画面遷移**や**UIの要素**を確認できる。
- ユーザーの操作を実際に試しながら、アプリケーションの動きを確認します。

### **どんなことを確認するか**
ログイン機能のあるシステムだと…
- ログインページからログインし、ユーザ画面へ遷移するか？
- フォームに入力できるか？
- ボタンをクリックしたときの挙動。
- ログイン失敗した時、エラーメッセージが表示されるか？

### **コード例**
```ruby
describe 'ログインのテスト' do
  context 'ログイン成功した場合のテスト' do
    # ここにまとめて書ける！コードが簡潔！
    before do
      fill_in 'user[name]', with: user.name
      fill_in 'user[password]', with: user.password
      click_button 'Log in'
    end

    it 'ログイン後のリダイレクト先が正しいか' do
      expect(current_path).to eq '/users/' + user.id.to_s
    end

    it 'ログイン後にユーザー名が表示されるか' do
      expect(page).to have_content user.name
    end
  end
end
```

### **メリット**
- ユーザー目線で動作を確認できるため、バグを見つけやすい。
- UIの動作やフロー全体の動作をテストできる。

### **デメリット**
- テストの実行が遅い（ブラウザ操作をシミュレートするため）。
- 細かいロジックの確認には向かない。

---

## **2. リクエストスペック (Request Spec)**

### **概要**
- **HTTPリクエストを直接送信**して、そのレスポンスを確認する。
- 主に、**コントローラの挙動やAPIエンドポイント**の動作を確認する。
`APIエンドポイント`とは…
URLそのものを指す。APIが提供する特定の機能・データにアクセスするための決められた入口としてのURL。

### **特徴**
- ユーザ視点ではなく、クライアントとサーバのやり取りをテストする。
- コントローラのアクションが適切に動作しているかを確認する。

### **どんなことを確認するか**
ログイン機能のあるシステムだと…
- セッション（サーバー側で認証状態を保持する仕組み）が開始されるか？
- トークン（認証状態を示すデータをクライアントで保持する仕組み）が発行されるか？
- ログイン失敗した時は、セッション・トークン発行されない。
- 間違った情報を送信した時、エラーレスポンスが返るか。
- APIエンドポイントがリクエストに対して、期待されるデータ構造や内容を持つJSON形式のレスポンスを返すか
`JSONレスポンスとは`
URL・レスポンスが正しいか？データ構造が正しいか？

### **コード例**
```ruby
# Rails のテスト環境を設定するために使うコード
require 'rails_helper'

RSpec.describe 'ログイン機能', type: :request do
  # ユーザー作成（テストデータ）
  let!(:user) { create(:user, email: 'test@example.com', password: 'password') }

  describe 'POST /login' do
    context 'ログイン成功した場合' do
      before do
        post '/api/login', params: { email: 'test@example.com', password: 'password' }
      end

      it '成功したレスポンスを返す' do
        expect(response).to have_http_status(:success)
      end

      it 'レスポンスにトークンが含まれているか' do
        expect(json['token']).to be_present
      end
    end

    context 'ログイン失敗した場合' do
      before do
        post '/api/login', params: { email: 'test@example.com', password: 'wrongpassword' }
      end

      it '認証エラーとしてレスポンスを返す' do
        expect(response).to have_http_status(:unauthorized)
      end

      it 'エラーメッセージが正しいか' do
        expect(json['error']).to eq('Invalid credentials')
      end
    end

    context 'メールアドレスやパスワードが空の場合' do
      before do
        post '/api/login', params: { email: '', password: '' }
      end

      it 'エラーレスポンスを返す' do
        expect(response).to have_http_status(:unprocessable_entity)
      end

      it 'エラーメッセージが正しいか' do
        expect(json['error']).to eq('Email and password are required')
      end
    end
  end
end
```

### **メリット**
- テストが速い（ブラウザ操作は不要）。
- APIやバックエンドの挙動を確実に確認できる。

### **デメリット**
- 実際の画面操作はテストできない（システムスペックとは役割が異なる）。

---

## **システムスペックとリクエストスペックの違い**

| **項目**            | **システムスペック**                  | **リクエストスペック**             |
|---------------------|---------------------------------------|------------------------------------|
| **視点**            | ユーザー目線                          | コントローラやAPIの動作            |
| **対象**            | 画面遷移、UI、システム全体の動作確認    | HTTPリクエストとレスポンス         |
| **実行速度**        | 遅い                                  | 速い                               |
| **使用目的**        | ユーザー操作の再現、統合テスト         | コントローラやAPIのユニットテスト  |
| **使用ライブラリ**  | Capybara                              | なし（RSpecの標準機能）            |

---

## **結論**
- **システムスペック**: 
システム全体の動作を確認したいときに使用（ユーザー目線）。
- **リクエストスペック**: 
コントローラやAPIの動作を確認したいときに使用（開発者目線）。