Ruby のテストで RSpec を使う方法

チェリー本（プロを目指すためのRuby入門）のテストを RSpec で行いたいと思い備忘録として投稿します。
RSpec を用いて Ruby のテストを行う方のご参考になればと思います。

## [Bundlerのインストール](#1-Bundlerのインストール)
bundler をインストール

```ruby:
$ gem install bundler
```

bundler のバージョン

```ruby:
$ bundler -v
Bundler version 2.2.6
```

Ruby のバージョン

```ruby:
$ ruby -v
ruby 2.7.1p83
```

## [Bundler で RSpec をインストール](#2-Bundler で RSpec をインストール)
任意のディレクトリに Gemfile の作成

```ruby:
$ bundle init
```

Gemfile に rspec を追記

```ruby:Gemfile
source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }


# gem "rails"
+ gem "rspec"

```

Gemfile にリスト化した gem をインストール

```ruby:
$ bundle install
```

## [RSpec の初期化](#3-RSpec の初期化)
.rspec , spec/spec_helper.rb の２つのファイルを作成
プログラムを実行する際は、最初に``bundle exec``を記載 (指定無しだと互換性を考慮せずにシステム最新のgemを使ってしまう)

 ```ruby:
$ bundle exec rspec --init
  create   .rspec
  create   spec/spec_helper.rb
```

spec/spec_helper.rb のコメントアウトを外して有効化する
※ オプション説明は割愛します

```ruby:spec/spec_helper.rb
RSpec.configure do |config|

・・・中略・・・

# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
- =begin
  # This allows you to limit a spec run to individual examples or groups
  # you care about by tagging them with `:focus` metadata. When nothing
  # is tagged with `:focus`, all examples get run. RSpec also provides
  # aliases for `it`, `describe`, and `context` that include `:focus`
  # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
  config.filter_run_when_matching :focus

・・・中略・・・

  # 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
```


## [ファイル構成](#4-ファイル構成)
以下の構成でファイルを作成する

```ruby:
rspec_test
├── Gemfile
├── Gemfile.lock
├── lib
│   └── fizz_buzz.rb
└── spec
    ├── fizz_buzz_spec.rb
    └── spec_helper.rb
```

## [spec_helper.rb でファイルを指定](#5-spec_helper.rb でファイルを指定)
spec_helper.rb に以下の設定を追記して、lib ディレクトリにあるファイルを``require `spec_helper` ``で読み込む

```ruby:spec/spec_helper.rb

Dir[File.join(File.dirname(__FILE__), "../lib/**/*.rb")].each { |f| require f }
```

## [テストを実行](#6-テストを実行)

```ruby:lib/fizz_buzz.rb
def fizz_buzz(n)
  if n % 15 == 0
    "Fizz Buzz"
  elsif n % 3 == 0
    "Fizz"
  elsif n % 5 == 0
    "Buzz"
  else
    n.to_s
  end
end
```

```ruby:spec/fizz_buzz_spec.rb
require 'spec_helper'

RSpec.describe 'FizzBuzz' do
  it 'fizz_buzz' 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(4)).to eq '4'
    expect(fizz_buzz(5)).to eq 'Buzz'
    expect(fizz_buzz(6)).to eq 'Fizz'
    expect(fizz_buzz(15)).to eq 'Fizz Buzz'
  end
end
```

テストを実行する

```ruby:
$ bundle exec rspec

Randomized with seed 7546

FizzBuzz
  fizz_buzz

Top 1 slowest examples (0.00115 seconds, 14.2% of total time):
  FizzBuzz fizz_buzz
    0.00115 seconds ./spec/fizz_buzz_spec.rb:4

Finished in 0.00811 seconds (files took 0.11893 seconds to load)
1 example, 0 failures

Randomized with seed 7546
```

**テストが失敗していないのでOK**  
  
  
テストを失敗してみる

```ruby:spec/fizz_buzz_spec.rb
require 'spec_helper'

RSpec.describe 'FizzBuzz' do
  it 'fizz_buzz' 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(4)).to eq '4'
    expect(fizz_buzz(5)).to eq 'Buzz'
-   expect(fizz_buzz(6)).to eq 'Fizz'
+   expect(fizz_buzz(6)).to eq '6Fizz'
    expect(fizz_buzz(15)).to eq 'Fizz Buzz'
  end
end
```

```ruby:
$ bundle exec rspec

Randomized with seed 60110

FizzBuzz
  fizz_buzz (FAILED - 1)

Failures:

  1) FizzBuzz fizz_buzz
     Failure/Error: expect(fizz_buzz(6)).to eq '6Fizz'

       expected: "6Fizz"
            got: "Fizz"

       (compared using ==)
     # ./spec/fizz_buzz_spec.rb:10:in `block (2 levels) in <top (required)>'

Top 1 slowest examples (0.0254 seconds, 79.1% of total time):
  FizzBuzz fizz_buzz
    0.0254 seconds ./spec/fizz_buzz_spec.rb:4

Finished in 0.03211 seconds (files took 0.13643 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/fizz_buzz_spec.rb:4 # FizzBuzz fizz_buzz

Randomized with seed 60110

```
ちゃんとエラーしているのでテストOK  


## 参考記事
* [Bundlerの使い方](https://qiita.com/oshou/items/6283c2315dc7dd244aef)
* [RailsじゃないRSpec3環境を構築する方法](https://qiita.com/yusabana/items/db44b81bdddf6ed0e9f5)