RSpec導入の手順[Rails]

#**はじめに**
独自Railsアプリを開発するにあたって最初はテストコードを書いていませんでしたが、バグが多々発生し、テストコードを書く必要性を強く実感したので、今回は簡単にテストコード導入の流れをまとめていきます。

Rails標準でMinitestが利用できるようになっておりますが、今回はRSpecを利用するとします。

#**環境**
Rails 5.2.2
Ruby 2.5.1

#**Rspecとは**
**Rspecは、Rubyを元に作成されたテストに特化した言語です。`rspec-rails`というGemをインストールすることで、Rspecを利用できるようになります。**

#**テストの種類**
テストは、主に単体テストと統合テストの2種類に分類されます。

##**単体(Unit)テスト**
ひとつのプログラムのまとまりに関して、その単体が正常に動くかを確認するテストのことです。Railsでいうと、**モデルクラスひとつ、コントローラークラス一つにつきそれぞれテストコードを書きます**。

##**統合(Integration)テスト**
複数のプログラムが連動して行われる処理が意図した通りに行われるかを確かめるテストのことです。一連の流れをシミュレートします。

#**テストコードを開発環境に導入する**

##**必要なライブラリをインストール**
Gemfileに下記のように追記します。

```Gemfile
group :development, :test do
  .
  .
  gem 'rspec-rails'
end

group :development do
  gem 'web-console, '~> 2.0'
end
```
そして、ターミナルからGemをインストールします。

```
$ bundle install
```
##**RSpec用設定ファイルを作成**

次に`rails g rspec:install`コマンドを実行して、RSpec用の設定ファイルを作成します。

```
$ rails g rspec:install
Running via Spring preloader in process 11661
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
```
上記コマンドによって、`rails_helper.rb`と`spec_helper.rb`の二つのファイルが作成されました。
**`rails_helper.rb`ファイルには、RailsでRSpecを利用する際の共通の設定を書きます。**
また、`spec_helper.rb`ファイルにも、RSpec用の共通の設定をかいておきますが、**こちらはRSpecをRails無しで利用する際に利用します**。

また、同時に作成された`.rspec`ファイルに下記の記述を追記します。

```.rspec
--format documentation
```

##**RSpecが問題なく導入できたか確認**
`rspec`コマンドを実行する。

```
$ bundle exec rspec
No examples found.

Finished in 0.00058 seconds (files took 0.22899 seconds to load)
0 examples, 0 failures
```

##**Rspec用ディレクトリを作成**

　specファイルには、対応する**クラス名_spec.rbという命名規則がある**ので、仮にbook.rbのBookモデルに関してテストコードを書きたければ、**appディレクトリ以下にあるテストの対象となるコードの在りどころと対応させ**、book_spec.rbファイルを配置します。

```
takuyanin:~/model_practice/spec
$ ls
controllers/		models/			rails_helper.rb		spec_helper.rb

$ cd models/

$ ls
book_spec.rb
```
といった感じですね。

`book_spec.rb`内に記述するテストコードはここでは割愛しますが、一行目には`require 'rails_helper'`を書きます。

```book_spec.rb
require 'rails_helper'
```

これにより、**rails_helper.rb内の記述を読み込むことができ、共通の設定を有効にします。**つまり、この記述は、**全てのspecファイルに書き込む必要があります。**


RspecをRailsに導入する手順は基本的には以上になりますが、テストコードを記述するにあたって、よく使うライブラリである`factory_girl`の導入も下記に記しておきます。

##**factory_girlの導入**
**factory_girlとは簡単にダミーのインスタンスを作成することができるGemです**。他のファイルで予め各クラスのインスタンスに定めるプロパティを設定しておき、specファイルからメソッドを利用してその通りのインスタンスを作成します。

factory_girlを利用するために下記のようにGemfileに記述します。

```Gemfile
group :development, :test do
  .
  .
  gem 'factory_girl_rails', '~> 4.4.1'
end
```

記述後、`bundle install`を行います。

次にspecフォルダ配下に`factories`フォルダを作成し、その下にfactory_girlの定義を記述するファイルを配置します。

ファイル名は、**インスタンスの複数形に.rbの拡張子をつけたもの**となります。

```spec/factories/books.rb
Factory.define do

  factory :book do
    title : "Rspec入門"
    .
    .
    .
  end

end
```

factory_girlによってインスタンスを作成する際、`FactoryGirl.build(:book)`のように記述が冗長になるため、レシーバーであるクラスの`FactoryGirl`という記述を省略するとスッキリします。

そのために`spec/rails_helper.rb`を次のように編集します。

```rails_helper.rb
.
.
RSpec.configure do |config|
  .
  .
  config.include FactoryGirl::Syntax::Methods
  .
  .
end 
```
すると、インスタンス生成の際、`build(:book)` と記述を省略することができます。
これでfactory_girlの導入は完了です。

また、テストコードを書く際には、Fakerというライブラリもよく利用されるので下記に載せておきます。

##**Fakerの導入**
**Fakerとは、emailや電話番号、名前などのダミーデータを作成するためのGemです。**Fakerのメソッドはfactory_girlの設定ファイルの中で利用されることが多いです。

では、Gemfileに追記します。

```Gemfile
group :test do
  gem 'faker'
end
```

Fakerのダミーデータの生成は簡単です。一例として、

```
$ rails c -e test
Running via Spring preloader in process 13884
Loading test environment (Rails 5.2.2)
irb(main):001:0> Faker::Internet.email
=> "josiah@blick.co"
irb(main):002:0> Faker::Internet.password(6)
=> "44Hk80"
irb(main):003:0> Faker::Internet.free_email
=> "ivy@hotmail.com"
irb(main):004:0> Faker::Name.first_name
=> "Sharri"
irb(main):005:0> Faker::Name.last_name
=> "Williamson"
irb(main):006:0> Faker::Team.name
=> "Tennessee dolphins"
irb(main):007:0> Faker::Lorem.sentence
=> "Cupiditate nisi occaecati consequuntur."
```
などがあります。
ポイントは、**Fakerの挙動を確認する時は、テスト環境でコンソールを起動することです。**理由は、Fakerライブラリをテスト環境にしか導入していないためです。

Fakerに関しては以上となります。

#**補足**
RSpecに限った話ではありませんが、テストコードを書く際によく言われる原則がありますので、ここに記しておきます。

##**テストコードを書く際の原則**

1. 各exampleで期待する値は1つ
2. 期待する結果をはっきりわかりやすく記述
3. 起きて欲しいことと起きてほしくないこと両方をテストする
4. 境界値をテストする
5. 可読性を考えつつ、適度にDRYにする


#**終わりに**
テストに限ったことではありませんが、新しいことを導入するときには少なからずハードルを感じるはずです。ですので手順を書き留めておくことにより、次に始動するプロジェクトなどでもスムースに導入していきたいと思います。

少しでも役に立ったという方は、いいね、お願いします(^^)