0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails初学者】RSpecのペアプロで学んだモデルテストの書き方(備忘録)

Last updated at Posted at 2025-10-01

RSpecのペアプロで学んだモデルテストの書き方(備忘録)

はじめに

初めてペアプロに参加させていただき、そこでRSpecでモデルテストを書く流れを学びました。
この記事は自分用の備忘録として、まとめておきます。
(ペアプロ自体の体験記事は、また別で)

describe / context / it の使い分けについて

RSpecではこの3つをよく使います。最初は全部同じに見えたけど、役割を意識すると整理できる。

RSpec.describe User, type: :model do
  describe "バリデーション" do
    context "有効な場合" do
      it "バリデーションを通る" do
        # テストコード
      end
    end
  end
end
  • describe: テスト対象や観点を書く(例: "バリデーション", "インスタンスメソッド")
  • context: 条件を書く(例: "有効な場合", "名前が空の場合")
  • it: 期待値を書く(例: "バリデーションを通る")

書き方の流れは「何をテストする → どんな条件 → どうなるべきか」となる


正常系と異常系を分ける

  • 正常系
    まずは「正しく動く場合」
context "有効な場合" do
  let(:user) { build(:user) }
  
  it "バリデーションを通る" do
    expect(user.valid?).to be true
  end
end

ポイントとして

  • letでテストデータを簡潔に定義できる
  • valid?メソッドでバリデーションが通るかをチェックする

  • 異常系
    「エラーになる場合」
context "名前が空の場合" do
  let(:user) { build(:user, name: '') }
  
  it "無効である" do
    expect(user.valid?).to be false
    expect(user.errors[:name]).to include("を入力してください")
  end
end

異常系では「バリデーションが失敗する」+「正しいエラーメッセージが出る」を両方確認する。


build と create の違い

何度も出てきた重要ポイント

# build: User.new と同じ (DBに保存しない)
let(:user) { build(:user, name: "") }

# create: User.create! と同じ (DBに保存する)
create(:user, email: "test@example.com")
  • 基本はbuildを使う(DBに書き込まないので速い)
  • 他のレコードとの関係をテストしたいときだけcreateを使う
  • 「DBに保存が必要かどうか」で判断する

重複チェックのテスト

メールアドレス重複をテストする時はcreateが必要

context "メールアドレスが重複している場合" do
  it "無効である" do
    create(:user, email: "test@example.com")  # 先にDBに保存
    user = build(:user, email: "test@example.com")
    expect(user.valid?).to be false
    expect(user.errors[:email]).to include("はすでに存在します")
  end
end
  • 「すでに存在する状態」を作るためにcreateを使う

エラー検証の2つの方法

ペアプロで学んだエラーチェックの書き方

includeを使う

expect(user.errors[:email]).to include("を入力してください")

メッセージの一部が含まれているかを確認するため


be_of_kindを使う

expect(user.errors).to be_of_kind(:password, :blank)
  • エラーの種類でチェックできる
  • メッセージが変わってもテストが壊れにくい

メールアドレス形式のバリデーション

  • formatのテストも書けるらしい
context "メールアドレスの形式が不正な場合" do
  it "無効である" do
    user = build(:user, email: "090-1111-2222")
    expect(user.valid?).to be false
    expect(user.errors).to be_of_kind(:email, :invalid_format)
  end
end
  • 明らかにメールアドレスでない文字列でテストするのが良き

contextのネストについて

  • ネストはできるだけ浅くする
  • やっても2段階までがいいみたい
# Good
describe "バリデーション" do
  context "名前が空の場合" do
    it "無効である" do
    end
  end
  
  context "メールアドレスが空の場合" do
    it "無効である" do
    end
  end
end

テストを書くときの流れ

  1. 何をテストするか決める(describe)
  2. どんな条件か考える(context)
  3. どうなるべきか書く(it)
  4. テストデータを準備する(let, build, create)
  5. 検証する(expect)
  • この流れで考えるとスムーズに書ける

まとめ

学んだこととして

  • describe / context / it の役割を理解
  • buildcreateの違い
  • 正常系から書いて異常系を追加していく流れ
  • エラーチェック方法が今回学んだこと以外にもたくさんある
  • contextのネストは浅くする

RSpecは半年ぶりに触りました。
「とりあえず、このパターンで書けばいい」という形が少し見えてきた気がします。
引き続き、書いていきたいと思います。
初学者のため、記事が間違えていたらすいません。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?