RSpecに入門してみた
はじめに
どうも、どすこいです。
就活が終わり卒業までに何か新しいチャレンジをしようと考えプログラミングの勉強を始めました。
自分が勉強していく中で気になったことなどをまとめていきます。
今回は、Rubyのテストでよく使われているテストフレームワークのRSpecについての記事になります。
対象読者
- 私のように勉強したての初心者を対象にしています。
- Rubyに入門した人
- チェリー本のMinitestを行いRSpecを使ってみたい人
扱う範囲
今回は入門ですので、インストールの説明から、具体例として、RubyでFizzBuzzのプログラムを書き、説明をしていきます。Ruby on RailsでのControllerやModelのテストなどはまた別の記事に載せます。
RSpecとは
RSpecは、Rubyプログラムのためのテストフレームワークです。特に、振る舞い駆動開発(BDD: Behavior-Driven Development)のアプローチをサポートしており、自然言語に近い形でテストケースを記述することができます。これにより、テストコードがドキュメンテーションとしての役割も果たすようになります。
RSpecの主な特徴
- 記述が直感的:RSpecのテストは「describe」や「it」などのメソッドを使用して、自然言語に近い形で記述されます。
- 豊富なマッチャ:期待値と実際の値を比較するための多くのマッチャ(例: eq, be_truthy, includeなど)が提供されています。
- カスタムマッチャの作成:独自のマッチャを定義することも可能です。
- モックとスタブ:テストの際に外部の依存関係を模倣(モック)したり、特定のメソッドの戻り値を固定(スタブ)することができます。
- タグ付け:テストケースやテストグループにタグを付けて、特定のタグのテストだけを実行することができます。
以下は、公式Docummentです。
インストール方法
Ruby単体で使う場合(rubyとbundleのインストール方法は省略してます)
[手順]
- bundle initでGemfileを生成
- Gemfileに「gem “rspec”」を記述し、bundle install
- RSpec設定ファイルの生成
- spec_helper.rbの有効化
bundle initでGemfileを生成
bundle init
Gemfileに「gem “rspec”」を記述し、bundle install
gem “rspec”
bundle install
RSpec設定ファイルの生成
bundle exec rspec --init
上記のコマンドを実行すると、「.rspec」と「spec/spec_helper.rb」の2ファイルが生成されます。
spec_helper.rbの有効化
3.で生成されたspec_helper.rbの「=begin」と「=end」を削除し、spec_helper.rbを有効化する。
# 中略
=begin //削除
# 中略
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
=end //削除
end
実際に使ってみよう
今回は、チェリー本の最初の例題である「FizzBuzzプログラムを作成する」を具体例として用います。
ファイル構成
libファイルにfizzbuzzのプログラム
specにRSpecのファイル
testにMinitestのファイル
.
├── Gemfile
├── Gemfile.lock
├── README.md
├── lib
│ └── fizz_buzz.rb
├── spec
│ ├── fizz_buzz_spec.rb
│ └── spec_helper.rb
└── test
└── fizz_buzz_test.rb
まずは、fizz_buzz.rbにfizzbuzzのプログラムを書きます。
def fizz_buzz(n)
if n % 15 == 0
'FizzBuzz'
elsif n % 3 == 0
'Fizz'
elsif n % 5 == 0
'Buzz'
else
n.to_s
end
end
続いて、Minitestの場合のテストコードを書きます。
require 'minitest/autorun'
require_relative "../lib/fizz_buzz.rb"
class FizzBuzzTest < Minitest::Test
def test_fizz_buzz
assert_equal '1', fizz_buzz(1)
assert_equal '2', fizz_buzz(2)
assert_equal 'Fizz', fizz_buzz(3)
assert_equal 'Buzz', fizz_buzz(5)
assert_equal 'FizzBuzz', fizz_buzz(15)
end
end
terminalで実行します。
ruby test/fizz_buzz_test.rb
Run options: --seed 28700
# Running:
.
Finished in 0.000458s, 2183.4061 runs/s, 10917.0307 assertions/s.
1 runs, 5 assertions, 0 failures, 0 errors, 0 skips
テストが通っていることが分かります。
では続いて、RSpecのテストコードを書きます。
require_relative "../lib/fizz_buzz.rb"
RSpec.describe 'FizzBuzz' do
it 'FizzBuzzの返り値正しいかを確認する' do
expect(fizz_buzz(1)).to eq '1'
expect(fizz_buzz(2)).to eq '2'
expect(fizz_buzz(3)).to eq 'Fizz'
expect(fizz_buzz(5)).to eq 'Buzz'
expect(fizz_buzz(15)).to eq 'FizzBuzz'
end
end
terminalで実行します。RSpecのテストコードを実行する際は、bundle exec rspec
とします。
bundle exec rspec
.
Finished in 0.02057 seconds (files took 0.11506 seconds to load)
1 example, 0 failures
テストが通っていることが分かります。
RSpecの基本的な使い方の説明
この節では、先ほどのfizz_buzz_spec.rbを見ながらRSpecの基本的な使い方について説明していきます。
describe '何かのクラスやメソッドの説明' do
context 'ある状況や条件の説明' do
it '期待する振る舞いの説明' do
expect(実際の値).to eq 期待する値
end
end
end
describe: テストのグループ化
context: 条件を分けたりするときに使う
it: example という単位にまとめる役割をする。it do ~ endの の中が正ければ全てexampleがパスしたことになります。
expect: expect(X).to eq Yの形で用います。この場合は、xがyと等しいになります。
fizz_buzz_spec.rbの場合の説明をしていきます。
require_relative "../lib/fizz_buzz.rb" //fizz_buzzファイルの読み込み
RSpec.describe 'FizzBuzz' do //FizzBuzzのテストを宣言する。
it 'FizzBuzzの戻り値が正しいかを確認する' do //itでテストの内容を書く
expect(fizz_buzz(1)).to eq '1' //fizz_buzzの引数が1の時、戻り値が1
expect(fizz_buzz(2)).to eq '2'
expect(fizz_buzz(3)).to eq 'Fizz'
expect(fizz_buzz(5)).to eq 'Buzz'
expect(fizz_buzz(15)).to eq 'FizzBuzz'
end
end
リファクタリングの余地はありますがこの記事では記載しません。
おまけ
.rspec
に--format documentation
を追加すると、出力結果が見やすくなります。
FizzBuzz
FizzBuzzの戻り値正しいかを確認する
Finished in 0.00112 seconds (files took 0.05465 seconds to load)
1 example, 0 failures
まとめ
- 現場で使われているRSpecについての超基本的について記載しました
- テストコードを書いて、よりエンジニアとして成長していきたいなと思いました。
- 「チェリー本の例題を全てRSpecで書いてみた」という記事も続編で書きます。
参考にしたサイト
Discussion