はじめに
rspecについて学んでいます。
備忘録的な記事です。
基本の3構文
🤔どうも、describe
・context
・it
の3つが重要なようです。
使い方の例として、ChatGPTは以下のような例を示してきました。
# calculator_spec.rb
require 'calculator'
describe Calculator do
describe '#add' do
context 'when adding positive numbers' do
it 'returns the sum of the numbers' do
calculator = Calculator.new
expect(calculator.add(1, 2)).to eq(3)
end
end
context 'when adding negative numbers' do
it 'returns the sum of the numbers' do
calculator = Calculator.new
expect(calculator.add(-1, -2)).to eq(-3)
end
end
context 'when adding a positive number and a negative number' do
it 'returns the correct sum' do
calculator = Calculator.new
expect(calculator.add(-1, 2)).to eq(1)
end
end
end
end
これを見る限り、describe
・context
・it
は
「テストを実行するための必須構造」というよりも、
「ベストプラクティスなテストをサポートするための構造」ぽい。
回答
はい、その通りです。
describe
、context
、it
は、RSpecにおけるテストコードを整理し、可読性を高めるための構造を提供しますが、これらがなければテストを実行できないわけではありません。 これらの構造要素は、テストの目的、テストケースの条件、期待される振る舞いを明確にするためのガイドラインとして機能し、テストコードの読みやすさやメンテナンスの容易さを大きく向上させます。
この理解は大きいですね~
検証メソッドexpect().to matcher()
expect(object).to eq(expect_object)
expect(boolean).to be true
expect(variable).to be be_nil
expect(array).to be be_empty
expect(object).to be be_invalid
このような形で使うようです。最後のbe_invalid
は重要ですね。validation errorを出しているか。
matcher
はeq
とかbe
ですね。
factory bot
でテストデータを作成
例を出してもらいました。
# spec/factories/users.rb
FactoryBot.define do
factory :user do
first_name { "John" }
last_name { "Doe" }
email { "john.doe@example.com" }
password { "securepassword" }
end
end
Factorybotを使用してcreate
している例
# spec/models/user_spec.rb
RSpec.describe User, type: :model do
describe "Validations" do
it "is valid with valid attributes" do
user = FactoryBot.create(:user)
expect(user).to be_valid
end
it "is invalid without a first name" do
user = FactoryBot.build(:user, first_name: nil)
expect(user).not_to be_valid
end
end
end
DBにおけるseed
を連想しました。あれは初期データでこちらはテストデータ。永続性の点で違いがありますね。
メソッド
-
create
:データベースにオブジェクトを保存する。レコードを利用したテストを行う場合 -
build
:データベースにオブジェクトを保存しない。中間オブジェクトの生成や、モデルレベルのバリデーションなど。
なお、以下はどちらで書いてもよいようです。
user = FactoryBot.create(:user)
user = create(:user)
user = FactoryBot.build(:user)
user = build(:user)