RSpecを導入する手順

# はじめに

Rubyで何かを開発するにあたってRSpecを導入したい。

https://rspec.info/

RSpec公式の「Let's get started!」を見たり、[RDoc](https://rspec.info/documentation/3.13/rspec-core/#install)を読んだりして導入はできるけど、メモ書き程度に導入手順を残す。

なお、RubyやBundler、gitは導入済みであるとする

# 手順

## 1. 開発用のディレクトリを作る

```sh
$ mkdir awesome_directory
$ cd awesome_directory
```

## 2. budler init

開発用のディレクトリの中でGemfileを生成する

```sh
$ bundler init
$ ls
Gemfile
```

## 3. Gemfileを編集する

```Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

gem "rspec", "~> 3.0"
```

```sh
% git diff
diff --git a/Gemfile b/Gemfile
index d2403f1..7afe5b1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,4 +2,4 @@
 
 source "https://rubygems.org"
 
-# gem "rails"
+gem "rspec", "~> 3.0"
```

## 4. bundle install

```sh
$ bundle install
Fetching gem metadata from https://rubygems.org/...
Resolving dependencies...
Bundle complete! 1 Gemfile dependency, 7 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```

Gemfile.lockができる。

```
$ % ls
Gemfile         Gemfile.lock
```

## 5. rspec --init

初期化をする

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

## 6. テストの実行を試してみる

まずは実行できるかどうかの確認のために、適当なファイルを生成する。
`hoge.rb`はテスト対象、`spec/hoge_spec.rb`はテスト用のファイル。RSpecのファイルは `_spec.rb`というsuffixをつけるのが慣例。

```sh
$ touch hoge.rb
$ touch spec/hoge_spec.rb
```

`hoge.rb`と`spec/hoge_spec.rb`にコードを書く。

```hoge.rb
class Hoge
  def self.hello
    puts 'Hello, Hoge!'
  end
end
```

```spec/hoge_spec.rb
RSpec.describe Hoge do
  describe '.hello' do
    it 'prints "Hello!" to the console' do
      expect { Hoge.hello }.to output("Hello!\n").to_stdout
    end
  end
end
```

RSpecを実行してみる。

```sh
$ bundle exec rspec spec/hoge_spec.rb 

An error occurred while loading ./spec/hoge_spec.rb.
Failure/Error:
  RSpec.describe Hoge do
    describe '.hello' do
      it 'prints "Hello!" to the console' do
        expect { Hoge.hello }.to output("Hello!\n").to_stdout
      end
    end
  end

NameError:
  uninitialized constant Hoge
# ./spec/hoge_spec.rb:1:in `<top (required)>'
No examples found.


Finished in 0.00004 seconds (files took 0.17748 seconds to load)
0 examples, 0 failures, 1 error occurred outside of examples
```

Hoge classが読み込めないというエラーが発生するので、`spec/spec_helper.rb`もしくは`spec/hoge_spec.rb`で読み込むようにする。
以下は、`spec/spec_helper.rb`で`hoge.rb`のみ読み込む設定の例。

```spec/spec_helper.rb
(省略)

require_relative '../hoge'

RSpec.configure do |config|

(省略)
```

再度RSpecを実行するとテストがパスする。


```sh
$ bundle exec rspec spec/hoge_spec.rb
.

Finished in 0.00313 seconds (files took 0.15465 seconds to load)
1 example, 0 failures
```

念の為、テストが落ちることも確認する。

```sh
class Hoge
  def self.hello
    puts 'Bad...'
  end
end
```

```sh
% rspec spec/hoge_spec.rb
F

Failures:

  1) Hoge.hello prints "Hello!" to the console
     Failure/Error: expect { Hoge.hello }.to output("Hello!\n").to_stdout
     
       expected block to output "Hello!\n" to stdout, but output "Hello, Hoge!\n"
       Diff:
       @@ -1 +1 @@
       -Hello!
       +Bad...
       
     # ./spec/hoge_spec.rb:4:in `block (3 levels) in <top (required)>'

Finished in 0.01361 seconds (files took 0.21231 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/hoge_spec.rb:3 # Hoge.hello prints "Hello!" to the console
```

## 追加でやりたいこと

### テストファイルごとに`RSpec.describe`と書かなくてもいいようにする

https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration#expose_dsl_globally=-instance_method

`RSpec.configuer`に`expose_dsl_globally`を追加する。

```spec/spec_helper.rb
(省略)

RSpec.configure do |config|
  config.expose_dsl_globally = true

(省略)
```

# 最後に

他にメモしておきたいことができたら追記します。