🎃
RSpecの`eq`と`be`の違いを完全理解!初心者向け徹底解説
RSpecのeqとbeの違いを完全理解!初心者向け徹底解説
RSpecでテストを書いている時、eqとbeのどちらを使えばいいか迷ったことはありませんか?この記事では、この2つのマッチャーの違いを具体例とともにわかりやすく解説します。
TL;DR(要約)
-
eq: 値の等価性をチェック(==と同じ) -
be: オブジェクトの同一性をチェック(equal?と同じ)
基本的な違い
eqマッチャー
eqは値の等価性を比較します。Rubyの==メソッドと同じ動作をします。
# 値が同じかどうかをチェック
expect(1 + 1).to eq(2)
expect("hello").to eq("hello")
expect([1, 2, 3]).to eq([1, 2, 3])
beマッチャー
beはオブジェクトの同一性を比較します。Rubyのequal?メソッドと同じ動作をします。
# 同じオブジェクトかどうかをチェック
str1 = "hello"
str2 = str1
expect(str2).to be(str1) # 同じオブジェクトなのでパス
具体例で理解しよう
文字列の場合
RSpec.describe "文字列の比較" do
it "eqとbeの違い" do
str1 = "hello"
str2 = "hello"
str3 = str1
# 値は同じだが、異なるオブジェクト
expect(str1).to eq(str2) # ✅ パス(値が同じ)
expect(str1).not_to be(str2) # ✅ パス(異なるオブジェクト)
# 同じオブジェクトを参照
expect(str3).to eq(str1) # ✅ パス(値が同じ)
expect(str3).to be(str1) # ✅ パス(同じオブジェクト)
end
end
数値の場合
RSpec.describe "数値の比較" do
it "小さな整数の場合" do
a = 1
b = 1
# 小さな整数はRubyが同じオブジェクトを使い回す
expect(a).to eq(b) # ✅ パス
expect(a).to be(b) # ✅ パス
end
it "大きな整数の場合" do
a = 1000000
b = 1000000
expect(a).to eq(b) # ✅ パス(値が同じ)
expect(a).not_to be(b) # ✅ パス(異なるオブジェクト)
end
end
配列の場合
RSpec.describe "配列の比較" do
it "eqとbeの違い" do
arr1 = [1, 2, 3]
arr2 = [1, 2, 3]
arr3 = arr1
# 値は同じだが、異なるオブジェクト
expect(arr1).to eq(arr2) # ✅ パス(要素が同じ)
expect(arr1).not_to be(arr2) # ✅ パス(異なるオブジェクト)
# 同じオブジェクトを参照
expect(arr3).to be(arr1) # ✅ パス(同じオブジェクト)
end
end
よくある使い分けパターン
1. 通常の値の比較にはeq
RSpec.describe User do
it "ユーザー名が正しく設定される" do
user = User.new(name: "太郎")
expect(user.name).to eq("太郎")
end
end
2. オブジェクトの同一性確認にはbe
RSpec.describe "ファクトリーパターン" do
it "シングルトンオブジェクトが同じインスタンスを返す" do
instance1 = Logger.instance
instance2 = Logger.instance
expect(instance1).to be(instance2)
end
end
3. boolean値の場合
RSpec.describe "boolean値のテスト" do
it "truthy/falsyな値のテスト" do
# 真偽値そのものをテスト
expect(user.active?).to be(true)
expect(user.deleted?).to be(false)
# 値の存在をテスト
expect(user.email).to be_truthy
expect(user.deleted_at).to be_falsy
end
end
beの特殊な使い方
be_truthy / be_falsy
# 真偽値の判定
expect("hello").to be_truthy # 空文字列以外は真
expect(nil).to be_falsy # nilは偽
expect(0).to be_truthy # 0は真(JavaScriptとは違う!)
be_nil
# nilかどうかの判定
expect(user.deleted_at).to be_nil
expect(user.deleted_at).not_to be_nil
be_present / be_blank(Rails環境)
# Railsの場合
expect(user.name).to be_present
expect(user.bio).to be_blank
実践的な例:モデルのテスト
RSpec.describe User do
let(:user) { User.new(name: "太郎", email: "taro@example.com") }
describe "#initialize" do
it "正しい値で初期化される" do
# 値の比較にはeq
expect(user.name).to eq("太郎")
expect(user.email).to eq("taro@example.com")
end
it "初期状態が正しく設定される" do
# boolean値の確認にはbe
expect(user.active?).to be(true)
expect(user.admin?).to be(false)
# nilの確認
expect(user.deleted_at).to be_nil
end
end
describe "#duplicate" do
it "異なるオブジェクトが作成される" do
duplicated_user = user.duplicate
# 値は同じ
expect(duplicated_user.name).to eq(user.name)
expect(duplicated_user.email).to eq(user.email)
# でも異なるオブジェクト
expect(duplicated_user).not_to be(user)
end
end
end
まとめ
| マッチャー | 用途 | Rubyのメソッド | 例 |
|---|---|---|---|
eq |
値の等価性 | == |
expect(1 + 1).to eq(2) |
be |
オブジェクトの同一性 | equal? |
expect(obj1).to be(obj2) |
be_truthy |
真偽値判定 | !!value |
expect("hello").to be_truthy |
be_falsy |
偽値判定 | !value |
expect(nil).to be_falsy |
be_nil |
nil判定 | nil? |
expect(value).to be_nil |
覚え方のコツ
-
値を比較したい →
eqを使う -
同じオブジェクトか確認したい →
beを使う -
boolean値をテストしたい →
be(true)/be(false) -
存在確認したい →
be_truthy/be_falsy/be_nil
適切なマッチャーを選ぶことで、テストの意図が明確になり、保守性の高いテストコードが書けるようになります。最初は迷うかもしれませんが、この違いを意識することで、より良いテストが書けるようになるでしょう!
Discussion